invokedynamic goes public

7 views
Skip to first unread message

John Rose

unread,
May 20, 2008, 12:17:55 AM5/20/08
to JVM Languages
Hello, JVM language folks!

The early draft review for the invokedynamic instruction is now
available. You can find more information via my blog:
http://blogs.sun.com/jrose/entry/invokedynamic_goes_public

Best wishes,
-- John

Geert Bevin

unread,
May 20, 2008, 6:21:45 AM5/20/08
to John Rose, jvm-la...@googlegroups.com
Thanks a lot John, downloaded the spec and will read through it as
soon as possible.

Best regards,

Geert

--
Geert Bevin
Terracotta - http://www.terracotta.org
Uwyn "Use what you need" - http://uwyn.com
RIFE Java application framework - http://rifers.org
Music and words - http://gbevin.com

Rich Hickey

unread,
May 20, 2008, 8:54:13 AM5/20/08
to JVM Languages
Thanks! Still working through it, but a fundamental question:

Why does invokedynamic mirror invokevirtual, esp. in looking like an
instance method call? Isn't a multi-language extension point like
invokedynamic a good place to abandon the hard-wiring of single-
dispatch? It seems like further dictation of Java-like object systems,
at the expense of newer (and older) ideas, like languages based on
functions, or non-member dispatch methods.

It's all function calls underneath. Distinguishing a 'receiver' makes
the first argument needlessly special - in particular, it can't be
null or a primitive.

The method handles seem to get this right, why shouldn't invokedynamic
do the same?

Rich

Ola Bini

unread,
May 20, 2008, 8:59:53 AM5/20/08
to jvm-la...@googlegroups.com
Rich Hickey wrote:
> Thanks! Still working through it, but a fundamental question:
>
> Why does invokedynamic mirror invokevirtual, esp. in looking like an
> instance method call? Isn't a multi-language extension point like
> invokedynamic a good place to abandon the hard-wiring of single-
> dispatch? It seems like further dictation of Java-like object systems,
> at the expense of newer (and older) ideas, like languages based on
> functions, or non-member dispatch methods.
>
> It's all function calls underneath. Distinguishing a 'receiver' makes
> the first argument needlessly special - in particular, it can't be
> null or a primitive.
>
> The method handles seem to get this right, why shouldn't invokedynamic
> do the same?
>
> Rich
>
Actually, if you read a bit closer you will see that the receiver
doesn't have real special status at all, and doesn't even have to be
used for the dispatching. You can in fact dispatch on all or none
arguments, just how you'd like it.

The good point about having it use invokeinterface is that we don't
generate anything that can't be loaded in earlier versions. Also the
space for new bytecodes is getting a bit thin.

Cheers

--
Ola Bini (http://ola-bini.blogspot.com)
JRuby Core Developer
Developer, ThoughtWorks Studios (http://studios.thoughtworks.com)
Practical JRuby on Rails (http://apress.com/book/view/9781590598818)

"Yields falsehood when quined" yields falsehood when quined.


Rich Hickey

unread,
May 20, 2008, 9:20:03 AM5/20/08
to JVM Languages


On May 20, 8:59 am, Ola Bini <ola.b...@gmail.com> wrote:
> Rich Hickey wrote:
> > Thanks! Still working through it, but a fundamental question:
>
> > Why does invokedynamic mirror invokevirtual, esp. in looking like an
> > instance method call? Isn't a multi-language extension point like
> > invokedynamic a good place to abandon the hard-wiring of single-
> > dispatch? It seems like further dictation of Java-like object systems,
> > at the expense of newer (and older) ideas, like languages based on
> > functions, or non-member dispatch methods.
>
> > It's all function calls underneath. Distinguishing a 'receiver' makes
> > the first argument needlessly special - in particular, it can't be
> > null or a primitive.
>
> > The method handles seem to get this right, why shouldn't invokedynamic
> > do the same?
>
> > Rich
>
> Actually, if you read a bit closer you will see that the receiver
> doesn't have real special status at all, and doesn't even have to be
> used for the dispatching. You can in fact dispatch on all or none
> arguments, just how you'd like it.
>

Well, it does have to exist, and will be passed to the call, right?
And the spec says right up front:

"It makes no requirements on its receiver argument, except that it be
a non-null object reference."

So if the actual first argument of the target function isn't an
object, this will just be a dummy that will have to be passed around
and skipped over. It seems like it could also prevent direct linking
to some useful variations of method handles without an intervening
receiver-stripper adapter thunk.

> The good point about having it use invokeinterface is that we don't
> generate anything that can't be loaded in earlier versions. Also the
> space for new bytecodes is getting a bit thin.
>

I'm not advocating for any particular implementation, but it seems you
could just as easily overload the meaning of invokestatic for some
'special' type.

Rich

John Rose

unread,
May 20, 2008, 2:17:58 PM5/20/08
to jvm-la...@googlegroups.com
On May 20, 2008, at 6:20 AM, Rich Hickey wrote:

> So if the actual first argument of the target function isn't an
> object, this will just be a dummy that will have to be passed around
> and skipped over. It seems like it could also prevent direct linking
> to some useful variations of method handles without an intervening
> receiver-stripper adapter thunk.

Yes, if a language wants dynamic linkage for arguments which are all
statically typed, it will have to pass a non-null dummy object in the
compiled code. (E.g., the null string.)

The whole design is predicated on the notion that such adapter thunks
are readily optimized by the JVM. Adding an "ignore receiver"
adapter is no big deal.

> I'm not advocating for any particular implementation, but it seems you
> could just as easily overload the meaning of invokestatic for some
> 'special' type.

That's not a bad suggestion; you are right that it is mainly just a
question of bytecode syntax. The invokestatic opcode could (like
invokeinterface) mention java.dyn.Dynamic as the location of the
method, which won't really exist. The normal linkage of this guy
would fail the first time the instruction executes on an old JVM.

All the invoke opcodes have linkage behavior the first time they
execute, so the invokestatic linkage sequence could be enhanced with
an extra check for the invokedynamic case.

The receiver would be just a vanilla first argument (statically typed
or not) and the call site would undergo the same state changes as the
spec. describes for invokeinterface.

But the invokeinterface opcode wins (in my mind) for three reasons:

1. It is more compatible with existing tool chains, because makes the
weakest promises of all the invoke opcodes.

2. Because the semantics are the most dynamic of the invoke opcodes,
JVM implementations are likely to perform the least early binding on
this opcode. Almost all JVM implementations perform some sort of
search or match operation at interface calls, which unlike the other
invokes do not lend themselves easily to early binding tricks. Any
early binding trick is an occasion where the JVM has to check for the
invokedynamic case. The fewer the better, for JVM implementors.

3. The extra instruction length (5 bytes) gives JVM implementors more
options. I'm using those bytes (in the prototype I'm working on) to
index into a call site table managed by the linker.

If we were doing a JVM++ from scratch, then, yes, there would be no
reason to overload an existing bytecode, or make a spurious
distinction on the first argument. But that's a project for another
day.

Thanks for the good comments!

-- John

Rich Hickey

unread,
May 20, 2008, 5:40:21 PM5/20/08
to JVM Languages


On May 20, 2:17 pm, John Rose <John.R...@Sun.COM> wrote:
> On May 20, 2008, at 6:20 AM, Rich Hickey wrote:
>
> > So if the actual first argument of the target function isn't an
> > object, this will just be a dummy that will have to be passed around
> > and skipped over. It seems like it could also prevent direct linking
> > to some useful variations of method handles without an intervening
> > receiver-stripper adapter thunk.
>
> Yes, if a language wants dynamic linkage for arguments which are all
> statically typed, it will have to pass a non-null dummy object in the
> compiled code. (E.g., the null string.)
>
> The whole design is predicated on the notion that such adapter thunks
> are readily optimized by the JVM. Adding an "ignore receiver"
> adapter is no big deal.
>

Maybe, but it seems like an onion, and a source of complexity and
redundant effort. Given the preference for the invokeinterface opcode,
might it be possible to accept either null or some 'ignore-me'
sentinel value for the receiver, such receiver value being recognized
by the infrastructure and omitted from consideration/use in call site
processing and target method processing?

Rich

John Rose

unread,
May 20, 2008, 5:46:58 PM5/20/08
to jvm-la...@googlegroups.com
On May 20, 2008, at 2:40 PM, Rich Hickey wrote:

might it be possible to accept either null or some 'ignore-me'

sentinel value for the receiver, such receiver value being recognized

by the infrastructure and omitted from consideration/use in call site

processing and target method processing?


Maybe, if the adapter technique has some practical problem.

-- John

Rémi Forax

unread,
May 20, 2008, 6:41:45 PM5/20/08
to jvm-la...@googlegroups.com
I have some remarks about the EDR.

At the end of section "Initial call site processing":
- in the last sentence, |CallSite.setTargetMethod should be
||CallSite.setTarget.|

In section about StaticContext "Context attribute of the reified call
site" :
- equals() should be boolean equals(Object)
- StaticContext use get*, by example getType() but MethodHandle use type().
- the next to last note is about a mysterious UID ?

In section "Language-specific bootstrap methods" registerBootstrapMethod
should be public static.

Futhermore, i am not sure StaticContext is the right name,
but i'm not able to find a better one.

About the invalidation, is it possible to invalidate using a StaticContext ?
or better using a bitwise conbination of the callerClass, the method name
and the method signature.

And now the big question, why MethodType need to be a reified object
and not a signature like (I)I ?

Rémi

ekul...@gmail.com

unread,
May 20, 2008, 10:58:46 PM5/20/08
to JVM Languages
On May 20, 2:17 pm, John Rose <John.R...@Sun.COM> wrote:

> But the invokeinterface opcode wins (in my mind) for three reasons:
>
> 1. It is more compatible with existing tool chains, because makes the
> weakest promises of all the invoke opcodes.

John, I am somewhat confused by this comment and the following note
in the EDR:

"It is a little known corollary of the JVM verifier design that
interface types cannot be statically checked. The JVM only enforces an
interface type on the receiver of an invokeinterface instruction, and
at explicit tests like checkcast. The JVM is thus more lenient
regarding interface types than the Java language. The pseudo-code
examples here include casts to Dynamic, but there would be no
checkcast in the corresponding actual bytecodes."

So, I wonder if you already thoughts of any specifics how does
invokeinterface-based invokedynamic would affect existing type-
checking tools? For example, calculation of the StackMapTable
structures, requires finding of the common super type, so it seem like
we'll have to put a special case for merging java.dyn.Dynamic types
and similar issue probably would appear in the classic recursive
verifier. Doesn't that negate the idea of reusing existing tools as
opposed to introducing special opcode for incokedynamic? Unless of
course the idea is to make invokedynamic work without bumping the
bytecode version, but then there is a risk of regression from older
JVMs if someone used java.dyn.Dynamic type and then run the same code
on the JVM supporting invokedynamic (but I guess this is really low
probability).

regards,
Eugene

John Rose

unread,
May 20, 2008, 10:44:17 PM5/20/08
to jvm-la...@googlegroups.com
On May 20, 2008, at 3:41 PM, Rémi Forax wrote:
> I have some remarks about the EDR.
>
> At the end of section "Initial call site processing":
> - in the last sentence, |CallSite.setTargetMethod should be
> ||CallSite.setTarget.|

Right; that is a last-minute name change that got away.

> In section about StaticContext "Context attribute of the reified call
> site" :
> - equals() should be boolean equals(Object)
> - StaticContext use get*, by example getType() but MethodHandle
> use type().
> - the next to last note is about a mysterious UID ?

Yes, fallout from another late simplification. Please ignore.

The confusion between structure-based and identity-based equality is
from the same change. Here's the current intention, imperfectly
represented in the EDR and subject to review: StaticContext is a
pure struct (like a Lisp s-expr) with structure-based equality.
CallSite uses identity-based equality, and sites at different BCIs
(and different inlining splits, and perhaps different bulk-reset
generations) have CallSites with equilvaent StaticContexts but
different identities.

Open question: Does BCI need to be exposed in the StaticContext?
Default answer: No, not useful enough, and there are workarounds if
such information is needed.

I'll publish patches to the EDR and push a new micro-version through
JCP (which takes 10 business days) when they accumulate.

> In section "Language-specific bootstrap methods"
> registerBootstrapMethod
> should be public static.

Yes.

> Futhermore, i am not sure StaticContext is the right name,
> but i'm not able to find a better one.

We're open to different names, of course. The distinction (of
course) is between the syntactic content of the call site, which does
not change, and the dynamic state built on top, which does change.

> About the invalidation, is it possible to invalidate using a
> StaticContext ?
> or better using a bitwise conbination of the callerClass, the
> method name
> and the method signature.

One idea there is to allow you to create a StaticContext of your own
which has a distinct wildcard value (probably null) instead of any of
those specifics.

The catch with bulk invalidation is that it cannot make too many
promises about its precision. I think it should be legal for a
simplified JVM to clear all call sites every time anything is bulk-
invalidated. (What do you think?) Given that, fancy pattern
expressions are a nice-to-have, not an essential.

> And now the big question, why MethodType need to be a reified object
> and not a signature like (I)I ?


First of all, a string does not have enough information. The minimum
requirement is a string plus a ClassLoader reference, to give a
meaning to the class names embedded in the string. So there's an
object in there somewhere. The sweet spot is probably a sequence of
Class references, which is what MethodType is.

(There are open questions about class loading, which we'll figure
out. As with standard JVM signatures, a MethodType can be created,
and compared with other method types for equality, before all of its
component types are loaded. The spec should probably say something
about this, especially the effect of asking such a MethodType for one
if its unloaded component types. Cf. Class.forName.)

Second, MethodType matching is based on exact structural matches,
with no coercions at all. (Like the JVM linkage model itself.) So
it is natural to require that they are always created uniquely. This
means they cannot be some user-managed type like Class[] or
{String,ClassLoader}. See the comments in the EDR about interning.

Third, if it is reified, it can then be made opaque, allowing JVM
implementors to play tricks under the hood. A JVM could cache things
like adapter handlers in hidden fields, if it is so inclined. JVMs
generally have ad hoc tables of such things, which might be cleaned
up if MethodTypes were integrated all the way down. They don't have
to be, but it is an attractive option.

Thanks for the close reading and excellent comments, Rémi!

Best,
-- John

John Rose

unread,
May 21, 2008, 1:01:54 AM5/21/08
to jvm-la...@googlegroups.com
On May 20, 2008, at 7:58 PM, ekul...@gmail.com wrote:

> On May 20, 2:17 pm, John Rose <John.R...@Sun.COM> wrote:
>
>> But the invokeinterface opcode wins (in my mind) for three reasons:
>>
>> 1. It is more compatible with existing tool chains, because makes the
>> weakest promises of all the invoke opcodes.
>

> John, I am somewhat confused by this comment ... it seem like


> we'll have to put a special case for merging java.dyn.Dynamic types
> and similar issue probably would appear in the classic recursive
> verifier.

Dynamic types will not in general appear on local variables.
Remember that the spec. says that Dynamic is just a trick for marking
call sites, not a type for object references. Merge-ups will often
produce Object as the receiver of an invokedynamic, which the
verifier (and other type checkers) must happily accept.

-- John

Eugene Kuleshov

unread,
May 21, 2008, 1:33:16 AM5/21/08
to JVM Languages
On May 21, 1:01 am, John Rose <John.R...@Sun.COM> wrote:

> > John, I am somewhat confused by this comment ... it seem like
> > we'll have to put a special case for merging java.dyn.Dynamic types
> > and similar issue probably would appear in the classic recursive
> > verifier.
>
> Dynamic types will not in general appear on local variables.
> Remember that the spec. says that Dynamic is just a trick for marking
> call sites, not a type for object references. Merge-ups will often
> produce Object as the receiver of an invokedynamic, which the
> verifier (and other type checkers) must happily accept.

I see... But then it all rely on assumption is that no one can use
or return an implementation of Dynamic interface, which isn't
restricted anyhow or is it?

For some reason I also thought that verifier is checking that call
receiver type declares method that is being called. Is it actually not
the case when receiver type is an interface? Otherwise verifier would
need to be changed to accept all methods when Dynamic is used as
receiver.

regards,
Eugene

John Rose

unread,
May 21, 2008, 12:33:30 PM5/21/08
to jvm-la...@googlegroups.com
On May 20, 2008, at 10:33 PM, Eugene Kuleshov wrote:

> I see... But then it all rely on assumption is that no one can use
> or return an implementation of Dynamic interface, which isn't
> restricted anyhow or is it?

There's neither benefit nor harm to a class implementing Dynamic.

>
> For some reason I also thought that verifier is checking that call
> receiver type declares method that is being called. Is it actually not
> the case when receiver type is an interface? Otherwise verifier would
> need to be changed to accept all methods when Dynamic is used as
> receiver.

There is some overlap in terms here. The typestate verifier (per se)
does not perform linkage. But linkage can be viewed as a distinct
phase of verification. The invokedynamic functionality necessarily
alters linkage semantics. (I.e., the method mentioned at the call
site would never link normally to a method of Dynamic, since Dynamic
has no methods at all.) But this divergence of functionality happens
only at the first actual execution of the instruction. There are no
necessary checks which happen earlier, which might trip up a tool.
Of course, lint-like tools which look for strange patterns might find
invokedynamic, well, strange.

-- John

Rémi Forax

unread,
May 21, 2008, 4:47:39 PM5/21/08
to jvm-la...@googlegroups.com
John Rose a écrit :

> On May 20, 2008, at 3:41 PM, Rémi Forax wrote:
>
>> I have some remarks about the EDR.
>>
>> At the end of section "Initial call site processing":
>> - in the last sentence, |CallSite.setTargetMethod should be
>> ||CallSite.setTarget.|
>>
>
> Right; that is a last-minute name change that got away.
>
>
>> In section about StaticContext "Context attribute of the reified call
>> site" :
>> - equals() should be boolean equals(Object)
>> - StaticContext use get*, by example getType() but MethodHandle
>> use type().
>> - the next to last note is about a mysterious UID ?
>>
>
> Yes, fallout from another late simplification. Please ignore.
>
> The confusion between structure-based and identity-based equality is
> from the same change. Here's the current intention, imperfectly
> represented in the EDR and subject to review: StaticContext is a
> pure struct (like a Lisp s-expr) with structure-based equality.
> CallSite uses identity-based equality, and sites at different BCIs
> (and different inlining splits, and perhaps different bulk-reset
> generations) have CallSites with equilvaent StaticContexts but
> different identities.
>
> Open question: Does BCI need to be exposed in the StaticContext?
> Default answer: No, not useful enough, and there are workarounds if
> such information is needed.
>
I can see a use case that require BCIs to be exposed. The compiler can
encode
information (by example reified generics :) in one annotation (runtime
invisible)
in a table BCI -> runtime type and use the BCI provided at callsite
to extract runtime type from the annotation.

In the same time, i wonder if it can prevent optimisation like inlining.


> I'll publish patches to the EDR and push a new micro-version through
> JCP (which takes 10 business days) when they accumulate.
>
>
>> In section "Language-specific bootstrap methods"
>> registerBootstrapMethod
>> should be public static.
>>
> Yes.
>
>
>> Futhermore, i am not sure StaticContext is the right name,
>> but i'm not able to find a better one.
>>
> We're open to different names, of course. The distinction (of
> course) is between the syntactic content of the call site, which does
> not change, and the dynamic state built on top, which does change.
>

I wonder if the separation of static/dynamic states is not a premature
optimization.
The spec could be relaxed and only require one class CallSite and let
the VM implementors
choose if they want to create only one class or more in order to share
states between
call sites.

This allows by example to only create one CallSite by thread and populate it
with the information as needed.


>
>> About the invalidation, is it possible to invalidate using a
>> StaticContext ?
>> or better using a bitwise conbination of the callerClass, the
>> method name
>> and the method signature.
>>
> One idea there is to allow you to create a StaticContext of your own
> which has a distinct wildcard value (probably null) instead of any of
> those specifics.
>

I have a bad feeling about reusing StaticContext here.
I prefer having another object implementing a simple query mecanism
in order to separate concern.

Someting like:
CallSiteQuery query=CallSiteQueris.and(CallSiteQueries.name("hello") ,
CallSiteQueries.callerClass(Dummy.class));
Linkage.invalidate(query); // invalidate at least all call sites with
name "hello" and caller class Dummy
// it can invalidate more call
sites (perhaps all).||

> The catch with bulk invalidation is that it cannot make too many
> promises about its precision. I think it should be legal for a
> simplified JVM to clear all call sites every time anything is bulk-
> invalidated. (What do you think?)

i agree.


> Given that, fancy pattern
> expressions are a nice-to-have, not an essential.
>

yes.


>
>> And now the big question, why MethodType need to be a reified object
>> and not a signature like (I)I ?
>>
>
>
> First of all, a string does not have enough information. The minimum
> requirement is a string plus a ClassLoader reference, to give a
> meaning to the class names embedded in the string. So there's an
> object in there somewhere. The sweet spot is probably a sequence of
> Class references, which is what MethodType is.
>
> (There are open questions about class loading, which we'll figure
> out. As with standard JVM signatures, a MethodType can be created,
> and compared with other method types for equality, before all of its
> component types are loaded. The spec should probably say something
> about this, especially the effect of asking such a MethodType for one
> if its unloaded component types. Cf. Class.forName.)
>
> Second, MethodType matching is based on exact structural matches,
> with no coercions at all. (Like the JVM linkage model itself.) So
> it is natural to require that they are always created uniquely. This
> means they cannot be some user-managed type like Class[] or
> {String,ClassLoader}. See the comments in the EDR about interning.
>

about interning that why i had suggested a String which are interned too.


> Third, if it is reified, it can then be made opaque, allowing JVM
> implementors to play tricks under the hood. A JVM could cache things
> like adapter handlers in hidden fields, if it is so inclined. JVMs
> generally have ad hoc tables of such things, which might be cleaned
> up if MethodTypes were integrated all the way down. They don't have
> to be, but it is an attractive option.
>

ok, i understand now.


> Thanks for the close reading and excellent comments, Rémi!
>
> Best,
> -- John
>

cheers,
Rémi

John Rose

unread,
May 21, 2008, 5:46:50 PM5/21/08
to jvm-la...@googlegroups.com
On May 21, 2008, at 1:47 PM, Rémi Forax wrote:

>> Open question: Does BCI need to be exposed in the StaticContext?
>> Default answer: No, not useful enough, and there are workarounds if
>> such information is needed.
>>
> I can see a use case that require BCIs to be exposed. The compiler can
> encode
> information (by example reified generics :) in one annotation (runtime
> invisible)
> in a table BCI -> runtime type and use the BCI provided at callsite
> to extract runtime type from the annotation.
>
> In the same time, i wonder if it can prevent optimisation like
> inlining.

It is also fragile. There are some JVM features (e.g., debugging and
AOP) which edit bytecodes after a bytecode backend creates them and
before the JVM runs them. These features can shift BCIs, so they are
an unstable (buggy) key to use for distinguishing call sites.

Here's what I'm thinking of adding to the spec.:
>> (<em>Note:</em> There is no need to specify a bytecode index in a
>> call site&rsquo;s static context. Such a number would not be very
>> useful, even if the dynamic language backend built some sort of
>> BCI-based table, because low-level bytecode editing could change
>> bytecode indexes independently of the backend. If individual call
>> sites must be distinguished, and if the call site objects
>> themselves are unsuitable as map keys, the language backend can
>> create extra back-channels by embedding data in the method name
>> string, or in hidden arguments.)


> I wonder if the separation of static/dynamic states is not a premature
> optimization.
> The spec could be relaxed and only require one class CallSite and let
> the VM implementors
> choose if they want to create only one class or more in order to share
> states between
> call sites.

It is easier (IMO) to define, document, and implement an immutable
object which is then an immutable property of a mutable object, than
to document a merged object with some properties mutable and others
not. Also, the two kinds of data have inherently different object
identity behaviors. One is a value object and the other a non-
forgeable capability reference. To me it looks confusing to merge them.

I'm considering this language to explain the distinct roles:
>> The interface <code>StaticContext</code> provides a channel for
>> the JVM to inform bootstrap code of which call sites are being
>> linked. A static context is immutable linkage information
>> permanently associated with each call site. It is pure structure;
>> its identity (as detected by reference equality) is insignificant.
>>
>> The interface <code>CallSite</code> provides the necessary
>> &lsquo;hook&rsquo; for bootstrap methods (or failing methods) to
>> update the state of an <code>invokedynamic</code>
>> instruction&rsquo;s linkage state. A call site has a single
>> mutable variable, the target method, plus an immutable static
>> context. The identity of a call site object (as detected by
>> reference equality) is significant.

> This allows by example to only create one CallSite by thread and
> populate it
> with the information as needed.

No, CallSite objects are durable references, even across threads.

>> One idea there is to allow you to create a StaticContext of your own
>> which has a distinct wildcard value (probably null) instead of any of
>> those specifics.
>>
> I have a bad feeling about reusing StaticContext here.
> I prefer having another object implementing a simple query mecanism
> in order to separate concern.

It's a Lispy design, since StaticContext is pure structure with no
behavior. It seems both safe and economical to me. But the
wildcarding story is weak.

> Someting like:
> CallSiteQuery query=CallSiteQueris.and(CallSiteQueries.name("hello") ,
> CallSiteQueries.callerClass(Dummy.class));
> Linkage.invalidate(query); // invalidate at least all call sites with
> name "hello" and caller class Dummy
> // it can invalidate more
> call
> sites (perhaps all).||

That looks nice. Hmm. Is there a way to do something like this
without pushing all that implementation down into the JVM?

-- John

P.S. I will be collecting possible EDR diffs on my weblog, at:
http://blogs.sun.com/jrose/resource/InvokeDynamic-EDR-diffs.html

Rémi Forax

unread,
May 21, 2008, 7:09:13 PM5/21/08
to jvm-la...@googlegroups.com
John Rose a écrit :

> On May 21, 2008, at 1:47 PM, Rémi Forax wrote:
>
>
>>> Open question: Does BCI need to be exposed in the StaticContext?
>>> Default answer: No, not useful enough, and there are workarounds if
>>> such information is needed.
>>>
>>>
>> I can see a use case that require BCIs to be exposed. The compiler can
>> encode
>> information (by example reified generics :) in one annotation (runtime
>> invisible)
>> in a table BCI -> runtime type and use the BCI provided at callsite
>> to extract runtime type from the annotation.
>>
>> In the same time, i wonder if it can prevent optimisation like
>> inlining.
>>
>
> It is also fragile. There are some JVM features (e.g., debugging and
> AOP) which edit bytecodes after a bytecode backend creates them and
> before the JVM runs them. These features can shift BCIs, so they are
> an unstable (buggy) key to use for distinguishing call sites.
>
ok.

> Here's what I'm thinking of adding to the spec.:
>
>>> (<em>Note:</em> There is no need to specify a bytecode index in a
>>> call site&rsquo;s static context. Such a number would not be very
>>> useful, even if the dynamic language backend built some sort of
>>> BCI-based table, because low-level bytecode editing could change
>>> bytecode indexes independently of the backend. If individual call
>>> sites must be distinguished, and if the call site objects
>>> themselves are unsuitable as map keys, the language backend can
>>> create extra back-channels by embedding data in the method name
>>> string, or in hidden arguments.)
>>>
hidden argument -> extra space used before by quick invokeinterface opcode ?
There is currently no way to access to that info.

>
>> I wonder if the separation of static/dynamic states is not a premature
>> optimization.
>> The spec could be relaxed and only require one class CallSite and let
>> the VM implementors
>> choose if they want to create only one class or more in order to share
>> states between
>> call sites.
>>
>
> It is easier (IMO) to define, document, and implement an immutable
> object which is then an immutable property of a mutable object, than
> to document a merged object with some properties mutable and others
> not. Also, the two kinds of data have inherently different object
> identity behaviors. One is a value object and the other a non-
> forgeable capability reference. To me it looks confusing to merge them.
>
Ok, it's more easy to explain but I clearly understand the meaning of
ClassSite
and its semantics. It's not that obvious for StaticContext

> I'm considering this language to explain the distinct roles:
>
>>> The interface <code>StaticContext</code> provides a channel for
>>> the JVM to inform bootstrap code of which call sites are being
>>> linked.
Bootstrap code uses CallSite not StaticContext.

Object bootstrapInvokeDynamic(CallSite site, Object receiver, Object... arguments)

So i don't understand why you need this object.
Is it because you need it to simplify VM internals ?
In that case, isn't it too hotspot specific ?


>>> A static context is immutable linkage information
>>> permanently associated with each call site. It is pure structure;
>>> its identity (as detected by reference equality) is insignificant.
>>>
>>> The interface <code>CallSite</code> provides the necessary
>>> &lsquo;hook&rsquo; for bootstrap methods (or failing methods) to
>>> update the state of an <code>invokedynamic</code>
>>> instruction&rsquo;s linkage state. A call site has a single
>>> mutable variable, the target method, plus an immutable static
>>> context. The identity of a call site object (as detected by
>>> reference equality) is significant

[...]


>> This allows by example to only create one CallSite by thread and
>> populate it
>> with the information as needed.
>>
>
> No, CallSite objects are durable references, even across threads.
>

ok. so a CallSite can be stored and setTarget() can be called at any time.

[...}


>
>> Someting like:
>> CallSiteQuery query=CallSiteQueris.and(CallSiteQueries.name("hello") ,
>> CallSiteQueries.callerClass(Dummy.class));
>> Linkage.invalidate(query); // invalidate at least all call sites with
>> name "hello" and caller class Dummy
>> // it can invalidate more
>> call
>> sites (perhaps all).||
>>
>
> That looks nice. Hmm. Is there a way to do something like this
> without pushing all that implementation down into the JVM?
>

yes, that the idea. This is just the external Java API.
The internal one depends on how the VM is able to invalidate call sites.

> -- John
>
> P.S. I will be collecting possible EDR diffs on my weblog, at:
> http://blogs.sun.com/jrose/resource/InvokeDynamic-EDR-diffs.html
>
>

cheers,
Rémi

Nicholas Riley

unread,
May 22, 2008, 12:37:41 AM5/22/08
to jvm-la...@googlegroups.com
In article <4834AB99...@univ-mlv.fr>,
Rémi Forax <fo...@univ-mlv.fr> wrote:

> yes, that the idea. This is just the external Java API.
> The internal one depends on how the VM is able to invalidate call
> sites.

Perhaps there could be one or more 'tags' associated with a call site
which could be used for querying and bulk invalidation? It would make
it easier for multiple consumers which can each indicate their
dependencies independently. (I'm also referring to the Java API here
- just having a persistent identifier per call site would be enough to
create a mapping at the Java level.)

--
Nicholas Riley <njr...@uiuc.edu> | <http://www.uiuc.edu/ph/www/njriley>

John Rose

unread,
May 22, 2008, 2:28:10 AM5/22/08
to jvm-la...@googlegroups.com
On May 21, 2008, at 4:09 PM, Rémi Forax wrote:

> hidden argument -> extra space used before by quick invokeinterface
> opcode ?
> There is currently no way to access to that info.

Sadly, it is permanently dead, because the JVM requires a fixed bit
pattern there.

No, I was referring to a real extra Java argument passed to the
method handle, not corresponding to any user-visible argument.

Note that the bytecoded method name is an uninterpreted string
(reported by StaticContext.name). Therefore language implementations
are free to format that string any way they like.

For example the method name could be (to stretch the point) an XML
structure, one of whose attributes gave the actual method name to
call, with the rest of the structure giving a plethora of attributes
and elements which would be significant to the runtime (via the
bootstrap method).

More reasonably, the method name could append a suffix (delimited by
an special character like a colon) to give extra information about
the call to the bootstrap method. See the paragraph in my blog on
exotic names:
> It is actually useful define a few extra dangerous characters. In
> many languages, symbols have attributes beyond their basic
> spelling. (For example, Fortress symbols have a font attribute, and
> Common Lisp symbols have a package prefix.) Characters like square
> brackets and backquote which are allowed by the JVM but dangerous
> in the present sense are opportunities for adding more structure to
> the bytecode names of symbols. Languages are therefore free to use
> the colon character, and (in non-class names) square brackets and
> colon to add structure to their symbols. It is best if the basic
> spelling of the symbol comes first, so that low-level tools have a
> reasonable chance of demangling at least that part of the symbol.
>
> Source: http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm


>
>
>>>> The interface <code>StaticContext</code> provides a channel for
>>>> the JVM to inform bootstrap code of which call sites are being
>>>> linked.
> Bootstrap code uses CallSite not StaticContext.
>
> Object bootstrapInvokeDynamic(CallSite site, Object receiver,
> Object... arguments)

Dynamic things are inherently younger than static ones, so the
dynamic state descriptor has a pointer to the static descriptor,
which can be shared between several dynamic state descriptors. The
bootstrap method gets the dynamic guy, and whatever static guy he
refers to (via CallSite.staticContext).

> So i don't understand why you need this object.
> Is it because you need it to simplify VM internals ?

No, except in the general sense of hygiene; it may be helpful to
factor apart static from dynamic descriptions.

>> That looks nice. Hmm. Is there a way to do something like this
>> without pushing all that implementation down into the JVM?
>>
> yes, that the idea. This is just the external Java API.
> The internal one depends on how the VM is able to invalidate call
> sites.

Whatever we do, let's start simple and work from there. This has to
be relatively easy for JVM implementors to add to their systems.

On May 21, 2008, at 9:37 PM, Nicholas Riley wrote:
> Perhaps there could be one or more 'tags' associated with a call site
> which could be used for querying and bulk invalidation? It would make
> it easier for multiple consumers which can each indicate their
> dependencies independently.

I have the same comment about JVM implementation on this suggestion,
Nicholas. If a language runtime wants this structure, it can create
it without JVM help by putting the tags into method suffixes, and
registering the CallSite objects in some global searchable structure.

Tagging instructions at the JVM level involves BCI tables and lots of
toolchain headaches. (When we get annotations on local declarations,
which really should mean annotations on bytecode instructions, this
will get much easier, suddenly.)

Best wishes,
-- John

Nicholas Riley

unread,
May 22, 2008, 3:01:34 AM5/22/08
to jvm-la...@googlegroups.com
In article <584EE940-737A-4B36...@sun.com>,
John Rose <John...@Sun.COM> wrote:

> On May 21, 2008, at 9:37 PM, Nicholas Riley wrote:
> > Perhaps there could be one or more 'tags' associated with a call site
> > which could be used for querying and bulk invalidation? It would make
> > it easier for multiple consumers which can each indicate their
> > dependencies independently.
>
> I have the same comment about JVM implementation on this suggestion,
> Nicholas. If a language runtime wants this structure, it can create
> it without JVM help by putting the tags into method suffixes, and
> registering the CallSite objects in some global searchable structure.

OK, that makes sense. I'm already using suffixes to denote specialized
versions of methods, so I will have to figure out some kind of
hashing/encoding mechanism for the tags, or I guess I could use indexes
into yet another table. When I get some more experience applying it
I'll post back here.

> Tagging instructions at the JVM level involves BCI tables and lots of
> toolchain headaches. (When we get annotations on local declarations,
> which really should mean annotations on bytecode instructions, this
> will get much easier, suddenly.)

You chopped the parenthetical statement in which I said I didn't mean
that :-) but I understand and agree it'd be nice to have in the future.

Thanks,
--
Nicholas Riley <njr...@uiuc.edu>

John Rose

unread,
May 22, 2008, 3:05:29 AM5/22/08
to jvm-la...@googlegroups.com
On May 22, 2008, at 12:01 AM, Nicholas Riley wrote:

You chopped the parenthetical statement in which I said I didn't mean 

that :-) but I understand and agree it'd be nice to have in the future.


Ah, now I understand that statement.  Yes, the StaticContext exposes the symbolic content of the invokedynamic instruction, and this is what you can build a "persistent identifier" from.

-- John

Rémi Forax

unread,
May 22, 2008, 3:41:24 AM5/22/08
to jvm-la...@googlegroups.com
John Rose a écrit :

> On May 21, 2008, at 4:09 PM, Rémi Forax wrote:
>
>
>> hidden argument -> extra space used before by quick invokeinterface
>> opcode ?
>> There is currently no way to access to that info.
>>
>
> Sadly, it is permanently dead, because the JVM requires a fixed bit
> pattern there.
>
> No, I was referring to a real extra Java argument passed to the
> method handle, not corresponding to any user-visible argument.
>
> Note that the bytecoded method name is an uninterpreted string
> (reported by StaticContext.name). Therefore language implementations
> are free to format that string any way they like.
>
There is just a small problem: bytecoded method name are visible in
stack trace dump,
so this means stack trace rewriting.

[...]


>> Bootstrap code uses CallSite not StaticContext.
>>
>> Object bootstrapInvokeDynamic(CallSite site, Object receiver,
>> Object... arguments)
>>
> Dynamic things are inherently younger than static ones, so the
> dynamic state descriptor has a pointer to the static descriptor,
> which can be shared between several dynamic state descriptors. The
> bootstrap method gets the dynamic guy, and whatever static guy he
> refers to (via CallSite.staticContext).
>
>
>> So i don't understand why you need this object.
>> Is it because you need it to simplify VM internals ?
>>
> No, except in the general sense of hygiene; it may be helpful to
> factor apart static from dynamic descriptions.
>

yes, it may be but this factorisation can be done at JVM level (using
the same C++ struct)
or at Java Level. In my opinion, the current spec is too rigid because
it compels
to have a reified representation of the static states.

So in my opinion StaticContext object is not a requirement but a way to
implement the spec.
You can say that CallSite contains dynamic info and static ones without
requiring
a StaticContext.


>
>>> That looks nice. Hmm. Is there a way to do something like this
>>> without pushing all that implementation down into the JVM?
>>>
>>>
>> yes, that the idea. This is just the external Java API.
>> The internal one depends on how the VM is able to invalidate call
>> sites.
>>
> Whatever we do, let's start simple and work from there. This has to
> be relatively easy for JVM implementors to add to their systems.
>

I agree.


> On May 21, 2008, at 9:37 PM, Nicholas Riley wrote:
>
>> Perhaps there could be one or more 'tags' associated with a call site
>> which could be used for querying and bulk invalidation? It would make
>> it easier for multiple consumers which can each indicate their
>> dependencies independently.
>>

[..]
> Best wishes,
> -- John
>
Rémi

Geert Bevin

unread,
May 22, 2008, 6:06:54 AM5/22/08
to jvm-la...@googlegroups.com
Hi John,

I'm still reading through the spec but have an initial question. Will
the invokedynamic instruction only be able to mimic the invokevirtual
instruction, or will there be some kind of support for invokespecial
too? I can see a great use-case here to hook in at object
instantiation time and perform some other logic instead of calling the
constructor.

Continuing the read ...

Geert

--

Rémi Forax

unread,
May 22, 2008, 8:27:47 AM5/22/08
to jvm-la...@googlegroups.com
Geert Bevin a écrit :

> Hi John,
>
> I'm still reading through the spec but have an initial question. Will
> the invokedynamic instruction only be able to mimic the invokevirtual
> instruction, or will there be some kind of support for invokespecial
> too?
Remplacing an invokeSpecial by invokeDynamic (invokeDynamic on
java.dyn.Dynamic)
will lead to code that will be rejected by the bytecode verifier :(
Thus there is no support for invokeSpecial.

> I can see a great use-case here to hook in at object
> instantiation time and perform some other logic instead of calling the
> constructor.
>
A constructor must be called before a field access or a method call, see
JVM spec 4.9.4.

> Continuing the read ...
>
> Geert
>
cheers,
Rémi

John Rose

unread,
May 22, 2008, 4:06:00 PM5/22/08
to jvm-la...@googlegroups.com
On May 22, 2008, at 12:41 AM, Rémi Forax wrote:

So in my opinion StaticContext object is not a requirement but a way to 

implement the spec.  You can say that CallSite contains dynamic info and static ones without 

requiring a StaticContext.


I asked the EG (esp. the JVM implementors) about this.  If merging the types saves some JVM implementors from managing two objects, and it doesn't unexpectedly hurt some other JVM, then my esthetic scruples don't matter much, and we'll probably merge the types.  Thanks for pushing this point!

The merged type would look like:

interface CallSite {
    /** The target method of this site, or null if it is unlinked. */
    public MethodHandle getTarget();
    /** Relink this site, or unlink it if target is null. */
    public void setTarget(MethodHandle target);

    /** The calling class.  (Immutable.) */
    Class callerClass();
    /** The name specified in the invokedynamic instruction.  (Immutable.) */
    String name();
    /** The result and parameter types derived from the call descriptor.   (Immutable.) */
    MethodType type();
}

Comments?

As someone suggested for method handles, this type could also be changed to a fixed class with encapsulated allocation managed by the JVM.  This doesn't seem to buy much.

-- John

John Rose

unread,
May 22, 2008, 4:09:41 PM5/22/08
to jvm-la...@googlegroups.com
On May 22, 2008, at 3:06 AM, Geert Bevin wrote:
 I can see a great use-case here to hook in at object
instantiation time and perform some other logic instead of calling the
constructor.

Working around constructor sequencing is probably a bad idea, though there are unsafe primitives in hotspot that serialization uses.

If you are generating code for your own language's objects, build an initialization protocol which takes place after all constructors are run.  (If the constructors get in the way, just make them be no-ops.)  Then you won't need to inject code into the constructor sequence.  And, of course, consider using protected constructors and factory methods to build your language's objects.

On May 22, 2008, at 5:27 AM, Rémi Forax wrote:

Remplacing an invokeSpecial by invokeDynamic (invokeDynamic on 

java.dyn.Dynamic)

will lead to code that will be rejected by the bytecode verifier :(

Thus there is no support for invokeSpecial.


For support for invokespecial, look at MethodHandles.unreflectSpecial.

This would allow dynamic language compilers to implement super.foo().

A reflective caller check during method handle creation will ensure that nobody gets to create a super.foo() capability unless they would also be able to use the corresponding invokespecial call directly.

Thanks,
-- John

Nicholas Riley

unread,
May 22, 2008, 5:34:52 PM5/22/08
to jvm-la...@googlegroups.com
In article <483523A4...@univ-mlv.fr>,
Rémi Forax <fo...@univ-mlv.fr> wrote:

> There is just a small problem: bytecoded method name are visible in
> stack trace dump, so this means stack trace rewriting.

Are there any JVM dynamic languages that don't already do this using JSR
45 mechanisms? This doesn't seem like an issue as the raw generated
code is already unlikely to make much sense to the language user.
--
Nicholas Riley <njr...@uiuc.edu>

Reply all
Reply to author
Forward
0 new messages