invokenonvirtual opcode?

110 views
Skip to first unread message

Brian Frank

unread,
Jun 5, 2007, 12:38:21 PM6/5/07
to JVM Languages
Is there any plans within the JSR 292 work to give us an
invokenonvirtual opcode? Or at the least remove the restrictions on
the invokespecial opcode?

Not having the ability to invoke a method non-virtually can be
frustrating when trying to implement C# style versioning techniques or
explicit "super" calls from mixins.

Has anyone had to deal with this issue? What work-arounds have you
used? The obvious solution is to implement every virtual method as a
static method, then have the instance method call into it. But that
basically doubles your method calling overhead which seems a pretty
steep price to pay.

John Wilson

unread,
Jun 5, 2007, 12:58:04 PM6/5/07
to jvm-la...@googlegroups.com

Not being able to call a super method from outside a class is a PITA
when implementing MetaClasses. However I suspect there there might be
security concerns about allowing this (there generally are!).

Initially I don't plan to support super.foo() in Ng for this very reason.

As the only super calls which go via the MetaClass are from code which
the Ng compiler is generating then I have two options.

1/ create a synthetic method which can be called which then does the
super call for every method which is called via super in the class.
The MetaClass than calls this method to dispatch the super call.

e.g.

public void super$$foo() {
super.foo()
}

2/ Give the MetaClass the chance to handle to call if it wants to and
dispatch the method and generate a direct call if it doesn't want to
do magic.

e.g.

Object res = metaClass.invokeMethod("foo")

if ( res == SomeMarkerSingleton) {
super.foo()
}

The second approach is attractive but has at least two problems:

a/ If there are multiple versions of foo with the same number of
parameters on the superclass then dispatching the method directly is
tricky.

b/ You can't do processing before and after the call in the MetaClass.


John Wilson

Charles Oliver Nutter

unread,
Jun 5, 2007, 2:22:28 PM6/5/07
to jvm-la...@googlegroups.com
John Wilson wrote:
> On 6/5/07, Brian Frank <brian...@gmail.com> wrote:
>> Is there any plans within the JSR 292 work to give us an
>> invokenonvirtual opcode? Or at the least remove the restrictions on
>> the invokespecial opcode?
>>
>> Not having the ability to invoke a method non-virtually can be
>> frustrating when trying to implement C# style versioning techniques or
>> explicit "super" calls from mixins.
>>
>> Has anyone had to deal with this issue? What work-arounds have you
>> used? The obvious solution is to implement every virtual method as a
>> static method, then have the instance method call into it. But that
>> basically doubles your method calling overhead which seems a pretty
>> steep price to pay.
>
> Not being able to call a super method from outside a class is a PITA
> when implementing MetaClasses. However I suspect there there might be
> security concerns about allowing this (there generally are!).
>
> Initially I don't plan to support super.foo() in Ng for this very reason.

FWIW, Ruby only supports 'super' calling of the same-named method in the
superclass. You can't force calling the super implementation of an
arbitrary method. However if you know in a child class you'll want to be
able to call the super implementation, you can alias it to something
else first.

class A
def foo
puts :a_foo
end

def bar
puts :a_bar
end
end

class B < A
def foo
super # => "a_foo"
bar # => "b_bar
old_bar # "a_bar"
end

alias :old_bar :bar
def bar
puts :b_bar
end
end

Unsurprisingly, I prefer this "explicit devirtualization" over 'super'
tricks.

- Charlie

John Rose

unread,
Jun 5, 2007, 5:28:46 PM6/5/07
to jvm-la...@googlegroups.com
On Jun 5, 2007, at 9:38 AM, Brian Frank wrote:

> Is there any plans within the JSR 292 work to give us an
> invokenonvirtual opcode? Or at the least remove the restrictions on
> the invokespecial opcode?

No, the 292 work is centered around a more open-ended virtual invoke,
not a less-virtual invoke. But it's an intriguing idea to add to the
list.

> Not having the ability to invoke a method non-virtually can be
> frustrating when trying to implement C# style versioning techniques or
> explicit "super" calls from mixins.

As Charles pointed out, if the callee class is expecting to support such
features, it can create aliased non-virtual entry points.

If the callee class is not expecting such things, there are lots of
nasty
security issues, and I'd have to see a detailed example before making
future suggestions.

I think a better way to factor this would be to supply new hooks for
non-virtual entry points, to be used between cooperating classes.
Examples of such hooks would be a no-overhead method aliasing
facility, or a "friend" declaration, by which a class could grant
extended
access to other classes. (We've long needed "friends" to implement
the access semantics of inner classes.)

> Has anyone had to deal with this issue? What work-arounds have you
> used? The obvious solution is to implement every virtual method as a
> static method, then have the instance method call into it.

I think that's roughly what Scala does. It seems a reasonable way
to go. (See below.)

> But that
> basically doubles your method calling overhead which seems a pretty
> steep price to pay.

To me, that doesn't seem a steep price for two reasons: 1. method call
overhead is not that big, especially if the target method does something
non-trivial, and 2. adapter methods are a fact of life on the JVM and
are routinely optimized in the JIT (by inlining away the extra level
of calling).

-- John

Jochen Theodorou

unread,
Jun 7, 2007, 5:55:47 AM6/7/07
to jvm-la...@googlegroups.com
John Rose schrieb:

> On Jun 5, 2007, at 9:38 AM, Brian Frank wrote:
>
>> Is there any plans within the JSR 292 work to give us an
>> invokenonvirtual opcode? Or at the least remove the restrictions on
>> the invokespecial opcode?
>
> No, the 292 work is centered around a more open-ended virtual invoke,
> not a less-virtual invoke. But it's an intriguing idea to add to the
> list.

there are other issues going into the same direction as well. For
example calling methods that are not public. What if I extend a Java
class with a Groovy class and need to call a protected method of the
super class? As long as the call ends up as being done from the current
class all is fine, but the effect is that I need to create one of these
entry points for each protected/package private method in the super
class. Well for each one I need, but in many languages I don't know what
methods I will need and which not. And if a call really ends up in being
done from the runtime, but should look like it has been done from the
class, then I will also have to have such entry points for each non
public method of the current class as well.

If now your language has a very generic version of "super", then you
need to create one of these entry points for each method in the super
class that is public or protected.

Just by extending Object you already end up with a huge bunch of methods
unless you can guarantee, that you will never do the call from "outside".

Now imagine what happens when you subclass such a class. again you
create methods for "this" and for "super", while reusing the old
versions of "super". The old versions of "this" can be reused if it is
calling a protected method, but in other cases it is lost.

And all this, because there is invokevirtual and invokespecial. Just by
having a invokenonvirtual The number of methods needed here could be cut
in half.


[...]


> I think a better way to factor this would be to supply new hooks for
> non-virtual entry points, to be used between cooperating classes.
> Examples of such hooks would be a no-overhead method aliasing
> facility, or a "friend" declaration, by which a class could grant
> extended
> access to other classes. (We've long needed "friends" to implement
> the access semantics of inner classes.)

What I don't understand here... friends sounds like I need to know the
classes in friendship at compile time. I am not sure this is really of
value. I still can't call a protected method of a normal java class
then, because it doesn't know the friend. If knowing the friends at
compile time is not needed.. then why is this less of a security hole
then a invokenonvirtual or static entry points?

[...]


>> But that
>> basically doubles your method calling overhead which seems a pretty
>> steep price to pay.
>
> To me, that doesn't seem a steep price for two reasons: 1. method call
> overhead is not that big, especially if the target method does something
> non-trivial, and 2. adapter methods are a fact of life on the JVM and
> are routinely optimized in the JIT (by inlining away the extra level
> of calling).

we have luck, that the amount of methods possible in a class is so high.
I mean you would need a class with several thousand methods to get a
serious problem with the extra entry points.

But I have a question here for inlining, it is usually runtime calling
entry point calling virtual method. What is inlined here? The virtual
method is inlined in the entry point? Or is the static method inlined in
the runtime? I mean if I woudn't need the runtime in between to for
example call a private method of the same class, then I would do the
call directly without the entry point. If I get some kind of method
object from the runtime, (let us call the class RuntimeMethod) that I do
the call on, then the static method might be inlined to
RuntimeMethod#invokeIt, but that's all, isn't it? The overhead to call
the virtual invokeIt remains, the overhead to call the goal method
remains too. So am I right, that such a mechanism would *always* be 2-3
times slower than a normal invocation while ignoring the time I needed
to do my custom method selection?

I am just asking because I don't know enough about the JIT compiler.

bye blackdrag

--
Jochen "blackdrag" Theodorou
Groovy Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/

John Wilson

unread,
Jun 7, 2007, 7:22:00 AM6/7/07
to jvm-la...@googlegroups.com

For those people reading this thread who are not intimately familiar
with the problems of code generation it might help if I gave an
example:

Consider the Java class C

public class C {
protected void foo() {}
}

in my dynamic language I subclass C

case 1:

public class C1 extends C {
protected void foo() {super.foo()}
}

case 2:


public class C2 extends C {
protected void bar() {foo()}
}

Now, what code must my dynamic language compiler generate?

In a dynamic language compiled to bytecode you do not, in general,
generate direct calls to methods. Rather you make a call to a separate
class passing the information about the call that you want to make.
(implementations differ but the principle is always the same).

The general problem is how can a class M which is not a subclass of C1
or C2 and which is not in the same package as C, C1 and C2 make the
calls to foo on C?

In case 1 it cannot solve this problem unless it generates a synthetic
public helper method on C1 which just calls super.foo().

In case 2 the class which actually makes the call at runtime can used
reflection (which allows protected and private methods to be called if
the security manager allows it) or it can generate a synthetic public
helper method on C2 and call that method directly.

As Jochen points out, generating these synthetic methods results in an
explosion in the number of methods on the class. Many of not most
Dynamic languages allow you to call methods on objects where the name
of the method is not known at compile time:

e.g. in Groovy I can right

this."$myName"()

and (I think)

super."$myName"()

which will call the method whose name is the value of the myName variable.

This means that the compiler has, in general to generate synthetic
proxy methods for all the non public methods and fields on the class
(essentially, turning the fields into properties).

Note that Java has this problem too. The implementation of inner
classes require the generation of some synthetic methods. However
because of the static nature of Java the compiler can tell precisely
which methods are needed and so largely avoids the method explosion
issue.

So it would be really nice to have a way of avoiding generating these
methods with a new bytecode (which would help Java as well). However
that is quite a big ask.

It would also be really nice to be able to call a super method via
reflection. I don't, of course, fully understand the internal
consequences of adding this to reflection. however as we can already
call private and protected methods via reflection I would not have
thought the problems were major.

I hope that makes it clearer for the spectators :)

John Wilson

John Rose

unread,
Jun 7, 2007, 6:04:41 PM6/7/07
to jvm-la...@googlegroups.com
On Jun 7, 2007, at 2:55 AM, Jochen Theodorou wrote:
> there are other issues going into the same direction as well. For
> example calling methods that are not public. What if I extend a Java
> class with a Groovy class and need to call a protected method of the
> super class? ...

> And if a call really ends up in being
> done from the runtime, but should look like it has been done from the
> class...
That's the key to this particular problem: The JVM thinks that any
valid use of a protected API will be an invoke bytecode directly in
the subclass. This is inconvenient for any language that delegates
parts of a class's implementation outside of the class, e.g., to
a runtime library.

A friend-like mechanism could address this problem. The subclass
(which is generated by Groovy) could declare that its implementation
includes certain trusted Groovy classes or packages. The details
would probably be messy.

An easier way to handle it is with some form of method injection.
In this case the injected method would be an adapter generated
by the runtime to call the super method from the Groovy
class. It would be associated with (injected into) the Groovy class,
and so would have the same access rights as the original methods
of the Groovy class. (There are lightweight ways to do this that
do not cause JVM implementors grief. The key simplification is
to make the injected method anonymous with respect to the
original semantics of the target "injectee" class.)

A crude way to handle it, in the present JVM, would be to compile into
each Groovy class a loophole method which accepts a reflect.Method
and calls it from inside the class. The cost of this is that you
rely on
reflection for all calls. Worse, you create a security flaw, unless you
provide a way to authenticate the Groovy runtime to the loophole method.

> If now your language has a very generic version of "super", then you
> need to create one of these entry points for each method in the super
> class that is public or protected.

Or inject them as needed.

> Just by extending Object you already end up with a huge bunch of
> methods
> unless you can guarantee, that you will never do the call from
> "outside".

Yes. A lazy technique works much better than an eager one here.

> And all this, because there is invokevirtual and invokespecial.
> Just by
> having a invokenonvirtual The number of methods needed here could
> be cut
> in half.

Possibly. The simplest designs for invokenonvirtual would do this,
and would also break secure encapsulation. Avoiding the security
loopholes while respecting all the valid use cases looks hard to me.
(There's a reason the JVM supports non-public methods, even though
they are restrictive!)

> What I don't understand here... friends sounds like I need to know the
> classes in friendship at compile time. I am not sure this is really of
> value.

A Groovy class could delegate some of its rights to the trusted
runtime. That would be a compile-time decision.

> But I have a question here for inlining, it is usually runtime calling
> entry point calling virtual method. What is inlined here? The virtual
> method is inlined in the entry point? Or is the static method
> inlined in
> the runtime?

What typically happens is (a) the call site is monomorphic, (b) the
interpreter keeps track of this fact, (c) the compiler emits an inlined
call to the unique target method, and (d) the compiler also
does whatever is necessary to ensure that, if the program changes
and the call site becomes polymorphic, the target method code
will not get wrongly used. Step (b) is usually based on something
called a type profile. Step (d) is based on a number of tricks, notably
runtime guards, slow paths through vtables, deoptimization,
and dependency-driven code invalidation.

(It's all in the hotspot open source...!)


On Jun 7, 2007, at 4:22 AM, John Wilson wrote:
> So it would be really nice to have a way of avoiding generating these
> methods with a new bytecode (which would help Java as well). However
> that is quite a big ask.

It is. And if the use cases for the new bytecode are all of the form
"I want to emulate the semantics of the old bytecode invokefoo from
a novel context", then the cheapest way out is to invent new contexts,
not new bytecodes. Injected or associated methods would provide
such contexts. So would some sort of access delegation to the runtime.

> It would also be really nice to be able to call a super method via
> reflection. I don't, of course, fully understand the internal
> consequences of adding this to reflection. however as we can already
> call private and protected methods via reflection I would not have
> thought the problems were major.

No, I expect the technical problems are minor, for the reasons you
state.
The API could be as simple as a setSpecial call analogous to
setAccessible.

(BTW, setAccessible is a design flaw, since it puts state into Method.
But we live with it.)

But I'd rather work toward associated methods.

Cheers,

-- John


Jochen Theodorou

unread,
Jun 7, 2007, 7:26:55 PM6/7/07
to jvm-la...@googlegroups.com
John Rose schrieb:

> On Jun 7, 2007, at 2:55 AM, Jochen Theodorou wrote:
>> there are other issues going into the same direction as well. For
>> example calling methods that are not public. What if I extend a Java
>> class with a Groovy class and need to call a protected method of the
>> super class? ...
>> And if a call really ends up in being
>> done from the runtime, but should look like it has been done from the
>> class...
> That's the key to this particular problem: The JVM thinks that any
> valid use of a protected API will be an invoke bytecode directly in
> the subclass. This is inconvenient for any language that delegates
> parts of a class's implementation outside of the class, e.g., to
> a runtime library.
>
> A friend-like mechanism could address this problem. The subclass
> (which is generated by Groovy) could declare that its implementation
> includes certain trusted Groovy classes or packages. The details
> would probably be messy.

yes, I think that too. I mean if the friend is not a subclass and is not
in the same package, then you are inventing a totally new system here
and somehow I guess there is no verification unless the class knows a
special package or a special class that is allowed as friend.. If I need
to know it at compile time, then it is probably not of much use.

> An easier way to handle it is with some form of method injection.
> In this case the injected method would be an adapter generated
> by the runtime to call the super method from the Groovy
> class. It would be associated with (injected into) the Groovy class,
> and so would have the same access rights as the original methods
> of the Groovy class. (There are lightweight ways to do this that
> do not cause JVM implementors grief. The key simplification is
> to make the injected method anonymous with respect to the
> original semantics of the target "injectee" class.)

ok.. somehow I get the feeling you are not talking about the current
JVM.. maybe I missed something. I am no JVM expert ;) I guess you refer
to http://blogs.sun.com/jrose/entry/autonomous_methods_for_the_jvm That
might indeed help

> A crude way to handle it, in the present JVM, would be to compile into
> each Groovy class a loophole method which accepts a reflect.Method
> and calls it from inside the class. The cost of this is that you
> rely on
> reflection for all calls. Worse, you create a security flaw, unless you
> provide a way to authenticate the Groovy runtime to the loophole method.

hmm... that's only to not to have to loosen the access rights, yes?

[...]


>> What I don't understand here... friends sounds like I need to know the
>> classes in friendship at compile time. I am not sure this is really of
>> value.
>
> A Groovy class could delegate some of its rights to the trusted
> runtime. That would be a compile-time decision.

sure, yes, well, ok, I would still have the problem with normal java
classes, but it would help to avoid the method explosion a little. Of
course it is no solution at all for calling protected methods of a
normal java class, that are called from a Groovy class in the same
package... But in this case either reflection or the generation of a
"gateway" class are the only solutions anyway.

>> But I have a question here for inlining, it is usually runtime calling
>> entry point calling virtual method. What is inlined here? The virtual
>> method is inlined in the entry point? Or is the static method
>> inlined in
>> the runtime?
>
> What typically happens is (a) the call site is monomorphic, (b) the
> interpreter keeps track of this fact, (c) the compiler emits an inlined
> call to the unique target method, and (d) the compiler also
> does whatever is necessary to ensure that, if the program changes
> and the call site becomes polymorphic, the target method code
> will not get wrongly used. Step (b) is usually based on something
> called a type profile. Step (d) is based on a number of tricks, notably
> runtime guards, slow paths through vtables, deoptimization,
> and dependency-driven code invalidation.
>
> (It's all in the hotspot open source...!)

hehe. I had not yet time to look at it. hmm.. so if there is a central
point in the runtime doing the invocation using some kind of adapter
containing the bytecode to call the entry point, then the call site
outside the adapter is changes very often.... so it is not monomorphic I
guess.

John Rose

unread,
Jun 7, 2007, 7:38:59 PM6/7/07
to jvm-la...@googlegroups.com
On Jun 7, 2007, at 4:26 PM, Jochen Theodorou wrote:

>> An easier way to handle it is with some form of method injection.
>

> ok.. somehow I get the feeling you are not talking about the current
> JVM.. maybe I missed something. I am no JVM expert ;) I guess you
> refer
> to http://blogs.sun.com/jrose/entry/autonomous_methods_for_the_jvm
> That
> might indeed help

Yes. Method injection is a scary future for JVM implementors to
contemplate.
But there are weak forms of it which would serve interesting use cases.

>> A crude way to handle it, in the present JVM, would be to compile
>> into
>> each Groovy class a loophole method which accepts a reflect.Method
>> and calls it from inside the class. The cost of this is that you
>> rely on
>> reflection for all calls. Worse, you create a security flaw,
>> unless you
>> provide a way to authenticate the Groovy runtime to the loophole
>> method.
>
> hmm... that's only to not to have to loosen the access rights, yes?

Yes. You trust the Groovy runtime, but if the runtime has to go through
an unlocked door to do its work, then the bad guys can come in too.

Internally to the Sun JRE, the reflection API uses
Reflection.getCallerClass
to authenticate callers. The sun.misc.Unsafe class has a different
(simpler)
mechanism, which relies on the caller possessing an unforgeable
token (a reference to a restricted class).

> so if there is a central
> point in the runtime doing the invocation using some kind of adapter
> containing the bytecode to call the entry point, then the call site
> outside the adapter is changes very often.... so it is not
> monomorphic I
> guess.

Yes.

Central invocation points are a fact of life in current dynamic
languages,
but they are bottlenecks that I hope we can move away from.
A major benefit of invokedynamic will be that point-to-point method
calls
(instead of point-to-runtime-to-point calls) will be the new fact of
life.
Point-to-point calls will be much easier to optimize.

-- John

Brian Frank

unread,
Jun 8, 2007, 7:48:14 AM6/8/07
to JVM Languages
A general purpose invokenonvirtual like the CLR has would be nice -
but I agree adding a new bytecode is a "big ask" and seems unlikely.

But we already have invokespecial which is effectively a non-virtual
invocation. I understand there are security issues, but it seems like
we could safely lift some of its security restrictions. For example,
what if we relaxed the rule to allow the use of invokespecial on any
public method of a public class? Is there a use case where that would
compromise JVM security?

The method explosion solution is especially unappealing to me because
I do a lot of embedded work. I personally will continue to just make
language trade-offs to avoid the issue like John is doing in Ng.

I'm intrigued about the ability to enhance reflection to call a method
non-virtually. That would be nice back door to solve the problem
without method explosion or changing VM semantics. Then the design
could fit into the existing AccessibleObject model.

Brian

John Wilson

unread,
Jun 8, 2007, 9:11:26 AM6/8/07
to jvm-la...@googlegroups.com
On 6/8/07, Brian Frank <brian...@gmail.com> wrote:
[snip]

> The method explosion solution is especially unappealing to me because
> I do a lot of embedded work. I personally will continue to just make
> language trade-offs to avoid the issue like John is doing in Ng.
>
> I'm intrigued about the ability to enhance reflection to call a method
> non-virtually. That would be nice back door to solve the problem
> without method explosion or changing VM semantics. Then the design
> could fit into the existing AccessibleObject model.

I think that something could be done with reflection. We already have
the ability to break encapsulation and the safeguard that the security
manager can prevent this happening. I can't see any real reason why
this could not be extended to allowing super to be implemented in a
MetaClass.

I feel that refection is fertile ground which could be harvested for
higher performance. I am lead to believe that Hotspot will dynamically
compile the dispatch of methods invoked via reflection and the ASM
folks have a refection API which they claim to be pretty fast (see
crazybob's post + comments
http://crazybob.org/2007/01/fast-reflection.html).

Having a fast reflection API which did super calls and which allowed
common case calls to be done without having to crate an array for the
parameters and box primitives would be really interesting. I can
compile my own stubs for public calls and bodge round non public ones
but if somebody else will do that for me I'll be very happy. If that
other person has back door access into the JVM which makes it easier
and faster for them to do that I'll be very happy.

John Wilson

Jochen Theodorou

unread,
Jun 8, 2007, 10:25:22 AM6/8/07
to jvm-la...@googlegroups.com
John Rose schrieb:
[...]

> Internally to the Sun JRE, the reflection API uses
> Reflection.getCallerClass
> to authenticate callers. The sun.misc.Unsafe class has a different
> (simpler)
> mechanism, which relies on the caller possessing an unforgeable
> token (a reference to a restricted class).

there are two reasons why we don't use geCallerClass. One is, that is
part of a class in a sun.* package, the other is that the stack has not
always the same form, especially if one or more ProxyMetaClass are involved.

[...]


> Central invocation points are a fact of life in current dynamic
> languages,
> but they are bottlenecks that I hope we can move away from.
> A major benefit of invokedynamic will be that point-to-point method
> calls
> (instead of point-to-runtime-to-point calls) will be the new fact of
> life.
> Point-to-point calls will be much easier to optimize.

yes, I agree. I think other languages might be more on that path than
Groovy already.

Kenneth Russell

unread,
Jun 8, 2007, 1:54:32 PM6/8/07
to jvm-la...@googlegroups.com
John Wilson wrote:
> On 6/8/07, Brian Frank <brian...@gmail.com> wrote:
> [snip]
>> The method explosion solution is especially unappealing to me because
>> I do a lot of embedded work. I personally will continue to just make
>> language trade-offs to avoid the issue like John is doing in Ng.
>>
>> I'm intrigued about the ability to enhance reflection to call a method
>> non-virtually. That would be nice back door to solve the problem
>> without method explosion or changing VM semantics. Then the design
>> could fit into the existing AccessibleObject model.
>
> I think that something could be done with reflection. We already have
> the ability to break encapsulation and the safeguard that the security
> manager can prevent this happening. I can't see any real reason why
> this could not be extended to allowing super to be implemented in a
> MetaClass.
>
> I feel that refection is fertile ground which could be harvested for
> higher performance. I am lead to believe that Hotspot will dynamically
> compile the dispatch of methods invoked via reflection and the ASM
> folks have a refection API which they claim to be pretty fast (see
> crazybob's post + comments
> http://crazybob.org/2007/01/fast-reflection.html).

I believe the core Java SE reflection implementation is as fast as it
can get without changing the APIs or semantics. If you have a Method or
Constructor object which is frequently invoked, a small trampoline class
will be generated which uses Java bytecodes to perform the necessary
unboxing, pushing of values on the expression stack, and invocation of
the target method. These stub methods are compiled by the HotSpot
compilers and, in the case of the HotSpot server compiler, sometimes
completely optimized away due to the deep inlining it performs. If you
are invoking a public method on a public class, security checks are
skipped (they're unnecessary in this case); the same is true if you call
setAccessible(true).

Note that on the above web page and the pages linked from it that there
was a huge speedup in reflection in 1.4.x, which was due to the addition
of this dynamic class generation. Whatever "FastMethod / FastClass" are
doing isn't more than a factor of two faster than what's in the core
Java SE.

If people think it can be optimized further (and it might be possible
that the bytecode sequences it generates can be), please look at
src/share/classes/sun/reflect/MethodAccessorGenerator.java in the Java
SE workspace. Suggestions or contributions are welcome.

Note also that implementing super calls in reflection basically informs
the need for an invokenonvirtual bytecode because of the presence of the
bytecode-based reflection implementation.

> Having a fast reflection API which did super calls and which allowed
> common case calls to be done without having to crate an array for the
> parameters and box primitives would be really interesting. I can
> compile my own stubs for public calls and bodge round non public ones
> but if somebody else will do that for me I'll be very happy. If that
> other person has back door access into the JVM which makes it easier
> and faster for them to do that I'll be very happy.

This ties back into all of the discussions about signature-based
invocation. With the Java language as it stands now if you want to have
a general method invocation mechanism you need to pass arguments as an
array of Objects. Dynamically generating bytecodes (as is the forte of
dynamic language implementations), or hopefully using invokesignature in
the future, is the way to get higher performance by being able to
specialize the call site.

-Ken

> John Wilson

John Wilson

unread,
Jun 8, 2007, 2:28:41 PM6/8/07
to jvm-la...@googlegroups.com
On 6/8/07, Kenneth Russell <Kenneth...@sun.com> wrote:
>
> John Wilson wrote:
[snip]


Hi Ken!

Thanks for the authoritative reply.

The Object Array and Boxing/Unboxing problem is a general one when
implementing a MetaClass (which is how many dynamic languages on the
JVM introduce the degree of indirection needed to add dynamic
behaviour). The MetaClass needs an invokeMethod method which generally
looks like this

Object invokeMethod(String methodName, Object instance, Object params[])

This means that the compiler has to generate code to box and marshal
the parameters. This has to be done even if the actual method call is
made via one the fly bytecode generation rather than reflection.
(Untyped languages generally don't have to box but optionally typed
languages generally have to box the typed parameters).

The need to marshal the parameters as an Object array is a
computational cost that we'd rather not incur. So the Ng MetaClass has
many invokeMethodQuick methods as well as the generic invokeMethod
method

Object invokeMethodQuick(String methodName, Object instance) // zero parameters
Object invokeMethodQuick(String methodName, Object instance, Object
p1) // one parameter
...
Object invokeMethodQuick(String methodName, Object instance, Object
p1, Object p2, Object p3, Object p4) // four parameters

So the common case of method call does not require the generation and
population of an Object array.

I am considering providing special case methods for single parameter
calls with primitive values to avoid the common need for boxing.

If I generate bytecodes on the fly (which Groovy does and I think
several other language implementations do) then I win with this
approach.

If I use reflection, which is what I currently do, then all my good
work is in vain as I have to box and marshal the parameters. I can use
tread local Object arrays or have the compiler hoist the array
creation out of loops to avoid having to keep creating arrays but
it's not simple and it does not reduce all the overhead.

It would be nice if the f reflection API has methods which I could
call which were in addition to the existing methods which allows me to
invoke via Method without using the object array

e.g.

invokeQuick(instance)
invokeQuick(instance, p1)
....

I think it might be of more general interest than just to dynamic
language implementers.

John Wilson

Brian Frank

unread,
Jun 8, 2007, 5:31:13 PM6/8/07
to JVM Languages

> Object invokeMethodQuick(String methodName, Object instance) // zero parameters
> Object invokeMethodQuick(String methodName, Object instance, Object
> p1) // one parameter
> ...
> Object invokeMethodQuick(String methodName, Object instance, Object
> p1, Object p2, Object p3, Object p4) // four parameters

I do more static type system work, but I use a similar technique in my
reflection APIs with up to 8 arguments:
Method.call0()
Method.call1(Obj)
Method.call2(Obj,Obj)
...

In functional code I generate such as a closure, this is quite
efficient. But when I need to map to the java.lang.reflect.Method
which is a fairly common case, then I have to take the Object[] array
hit. But if I understand Ken correctly, then this gets optimized
away?

With all the complications regarding boxing and unboxing, we choose to
go the always boxed route with heavy interning of classes like Int.
In a lot code the performance is still pretty close to normal Java.
Even in primitive intensive code such as a tokenizer it still is only
about six times slower than native Java written with primitives (I
find it funny that "native" usually means Java or C# to me rather than
C these days). It was quite liberating to unify the type system and
do away primitives.

Brian

John Rose

unread,
Jun 8, 2007, 5:36:40 PM6/8/07
to jvm-la...@googlegroups.com
On Jun 8, 2007, at 11:28 AM, John Wilson wrote:

It would be nice if the f reflection API has methods which I could

call which were in addition to the existing methods which allows me to

invoke via Method without using the object array


Here's way to manage this apart from invokedynamic/invokesignature:
Have each java.lang.reflect.Method implement a type-specialized interface
with a strongly-typed invoke method.  This can be done in Ken's code,
perhaps without JVM modifications.  The untyped Methods would
need to be replaced by Methods of specialized types.  But this might
disturb the API too much; Ken would know.

The BGGA closures proposal has the right schema of interfaces
to represent all possible calling signatures.

On Jun 8, 2007, at 10:54 AM, Kenneth Russell wrote:
I believe the core Java SE reflection implementation is as fast as it 
can get without changing the APIs or semantics. 

Given the the current JIT technology, the fact that Method.invoke
calls are non-dispatching leads to a bottleneck.  The problem is with
the type profile:  Method.invoke contains a large, polluted profile
which represents all reflective calls from all places in the system.

(That's a slight oversimplification, given that there's an extra
delegation step.  The JIT inlines the delegation step as if it's
not there.)

Method.invoke then dispatches (delegates) to a method-specific
handler, which is a megamorphic call site.  What the JIT would
prefer to see is a monomorphic call from the user to a specialized
subclass of Method, which then directly invokes the target
method.  That could be inlined away.  That would be a performance
benefit to having each java.lang.reflect.Method be a different
subclass, whether or not it implements a BGGA-type interface.

You can see the best-case performance if you run a micro-benchmark
with exactly one reflected method.  (Use "-server".)  In that case,
the type profile does not get polluted anywhere, and everything
can inline.  Use a public method (or setOverride) to avoid access
checking overheads.

(The bug 6565458 actually uses such a micro-benchmark.
Working on that bug, I studied the non-public paths and found an
unnecessary critical section; bug 6565585 tracks this.)

With escape analysis, the boxing/unboxing of arguments
could go away too, mostly.  But the boxing/unboxing
is always a drag on compilation.  Signature-specific
invocations will always be easier to optimize.
("Always" = "foreseeable future", actually.)

Another way to handle the polluted type profile is to
split the type profile at inline points in a profiling compilation.
Hotspot's tiered system will eventually do this.  But it's hard.

The invokedynamic/invokesignature instruction should probably
interoperate with java.lang.reflect.Method.  That would allow
a signature-specific alternative to Method.invoke.

Finally, I agree that an invokespecial variant of Hotspot's
reflection should be prototyped and tried.  (See my earlier
mention of setSpecial; I guess it's worth the effort,
even though reflection is a clunky API.)

-- John

Kenneth Russell

unread,
Jun 8, 2007, 6:29:28 PM6/8/07
to jvm-la...@googlegroups.com
Brian Frank wrote:
>
>> Object invokeMethodQuick(String methodName, Object instance) // zero parameters
>> Object invokeMethodQuick(String methodName, Object instance, Object
>> p1) // one parameter
>> ...
>> Object invokeMethodQuick(String methodName, Object instance, Object
>> p1, Object p2, Object p3, Object p4) // four parameters
>
> I do more static type system work, but I use a similar technique in my
> reflection APIs with up to 8 arguments:
> Method.call0()
> Method.call1(Obj)
> Method.call2(Obj,Obj)
> ...
>
> In functional code I generate such as a closure, this is quite
> efficient. But when I need to map to the java.lang.reflect.Method
> which is a fairly common case, then I have to take the Object[] array
> hit. But if I understand Ken correctly, then this gets optimized
> away?

Optimizations that John Rose added to C2 after the bytecode-based
reflection was introduced can constant fold away the loads from the
Object[] so that the outgoing arguments go directly to the points of use
in the callee without reloading them from main memory. The unnecessary
allocation of the Object[] itself, and potentially even of the boxing
objects for primitive types, etc. is still an issue. Escape analysis in
the HotSpot server compiler, which is in progress, will solve this
problem in this JVM implementation.

-Ken

Kenneth Russell

unread,
Jun 8, 2007, 6:32:55 PM6/8/07
to jvm-la...@googlegroups.com
John Rose wrote:
> On Jun 8, 2007, at 11:28 AM, John Wilson wrote:
>
>> It would be nice if the f reflection API has methods which I could
>>
>> call which were in addition to the existing methods which allows me to
>>
>> invoke via Method without using the object array
>>
>
> Here's way to manage this apart from invokedynamic/invokesignature:
> Have each java.lang.reflect.Method implement a type-specialized interface
> with a strongly-typed invoke method. This can be done in Ken's code,
> perhaps without JVM modifications. The untyped Methods would
> need to be replaced by Methods of specialized types. But this might
> disturb the API too much; Ken would know.

If we made java.lang.reflect.Method non-final (very carefully, to ensure
no security risks) I think this would be feasible. One could then
downcast a Method to an implementation of the type-specialized interface.

> The BGGA closures proposal has the right schema of interfaces
> to represent all possible calling signatures.

Yes. There would be a good unification possible here.

-Ken

John Rose

unread,
Jun 8, 2007, 6:44:52 PM6/8/07
to jvm-la...@googlegroups.com
On Jun 8, 2007, at 3:32 PM, Kenneth Russell wrote:

If we made java.lang.reflect.Method non-final (very carefully, to ensure 

no security risks) I think this would be feasible. One could then 

downcast a Method to an implementation of the type-specialized interface.


Given that the proposed subclass is part of a magic module which can
invoke arbitrary private entry points, we could make the constructor
of Method be private, and still call it (via invokespecial) from the
subclasses we make.  That would allow only the magic module to
subclass it.  Perhaps that would be secure enough?

Someone should prototype this...

-- John

Kenneth Russell

unread,
Jun 8, 2007, 6:49:27 PM6/8/07
to jvm-la...@googlegroups.com

Sounds like the right approach.

> Someone should prototype this...

Anyone up for some OpenJDK hacking?

-Ken

John Wilson

unread,
Jun 9, 2007, 12:02:03 PM6/9/07
to jvm-la...@googlegroups.com
On 6/8/07, Kenneth Russell <Kenneth...@sun.com> wrote:
>

This sounds very interesting but I'm not quite sure I have followed
the thread properly:)

Let me see if I have this straight:

You are proposing that the object returned when introspecting for
methods should be a subclass of java.reflection.Method.

We can downcast this object to this subclass which exposes more
methods which gives us a way of making the call using the actual
method signature of the target method.

To use this I would downcast the Object and make the call directly.

e.g. if I was trying to call protected int foo(int a, MyClass b, byte
c) I could do

int i = (SomeGeneratedClassName)myMethod(1, new My,Class(), 'x');

Where myMethod is an instance of java.reflection,Method and
SomeGeneratedClassName would be systematically derived from the types
of the parameters and the return type.

Have I got that right?

If so I think this would be *very* useful.

John Wilson

Kenneth Russell

unread,
Jun 11, 2007, 2:48:15 PM6/11/07
to jvm-la...@googlegroups.com

Yes, that's right. If you read the BGGA Closures proposal they already
have a suggested naming convention for the generated class names which
would be ideal for use in this context.

-Ken

John Wilson

unread,
Jun 12, 2007, 2:42:39 AM6/12/07
to jvm-la...@googlegroups.com
On 6/11/07, Kenneth Russell <Kenneth...@sun.com> wrote:

> >
> > Have I got that right?
>
> Yes, that's right. If you read the BGGA Closures proposal they already
> have a suggested naming convention for the generated class names which
> would be ideal for use in this context.

Ken,

That's great.

In my case I'd be generating a wrapper class round this object on the
fly. So I'd get the name from the Class object for the Method. This
means I don't need to worry about how the class name is generated.

How useful is this to other implementers? Jochen, Charlie, Samuele,
others any comments on this?

John Wilson

John Wilson

unread,
Jun 14, 2007, 6:02:02 AM6/14/07
to jvm-la...@googlegroups.com
Ken,

It appears to me that there would be problems if the Method instance
was always a superclass of this custom class. This would mean that
many new classes would be generated even if the reflection user was
not interested in fast dispatch.

Perhaps having a "Method getFastMethod()" on Method to return the
instance which could be downcasted would be a good idea. Or do you
have some other way of solving this problem?

BTW I have been looking into reflection performance with various JREs.
I have a Fibonacci benchmark which hammers method call pretty
effectively. JRE 1.6 is by far the fastest when using the client JVm.
However using -server makes a huge difference to performance,
unfortunately there does not yet seem to be a 1.6 server JVM.

1.5 client: 20.4 secs server: 11.8 secs
1.6 client: 19.2 secs
So, until we get a 1.6 server JVM it would seem that 1.5 -server is
the best environment to run NG programs.

Has anybody done any measurements on other dynamic languages to
determine the optimal JVM choice.


John Wilson

Kenneth Russell

unread,
Jun 14, 2007, 12:34:56 PM6/14/07
to jvm-la...@googlegroups.com
John Wilson wrote:
> Ken,
>
> It appears to me that there would be problems if the Method instance
> was always a superclass of this custom class. This would mean that
> many new classes would be generated even if the reflection user was
> not interested in fast dispatch.
>
> Perhaps having a "Method getFastMethod()" on Method to return the
> instance which could be downcasted would be a good idea. Or do you
> have some other way of solving this problem?

I don't see this being a big problem. The new classes will be
canonicalized per erased type signature as per the BGGA proposal, so
once you've generated the subclasses for the common signatures, you
won't have much class loading going on.

> BTW I have been looking into reflection performance with various JREs.
> I have a Fibonacci benchmark which hammers method call pretty
> effectively. JRE 1.6 is by far the fastest when using the client JVm.
> However using -server makes a huge difference to performance,
> unfortunately there does not yet seem to be a 1.6 server JVM.
>
> 1.5 client: 20.4 secs server: 11.8 secs
> 1.6 client: 19.2 secs
> So, until we get a 1.6 server JVM it would seem that 1.5 -server is
> the best environment to run NG programs.

I don't know what you mean. Sun's JDK 1.6 ships with the Java HotSpot
server VM. The JRE has never shipped with the server JVM.

-Ken

John Wilson

unread,
Jun 14, 2007, 1:25:56 PM6/14/07
to jvm-la...@googlegroups.com
On 6/14/07, Kenneth Russell <Kenneth...@sun.com> wrote:
>
> John Wilson wrote:
> > Ken,
> >
> > It appears to me that there would be problems if the Method instance
> > was always a superclass of this custom class. This would mean that
> > many new classes would be generated even if the reflection user was
> > not interested in fast dispatch.
> >
> > Perhaps having a "Method getFastMethod()" on Method to return the
> > instance which could be downcasted would be a good idea. Or do you
> > have some other way of solving this problem?
>
> I don't see this being a big problem. The new classes will be
> canonicalized per erased type signature as per the BGGA proposal, so
> once you've generated the subclasses for the common signatures, you
> won't have much class loading going on.

That's OK by me.

>
> > BTW I have been looking into reflection performance with various JREs.
> > I have a Fibonacci benchmark which hammers method call pretty
> > effectively. JRE 1.6 is by far the fastest when using the client JVm.
> > However using -server makes a huge difference to performance,
> > unfortunately there does not yet seem to be a 1.6 server JVM.
> >
> > 1.5 client: 20.4 secs server: 11.8 secs
> > 1.6 client: 19.2 secs
> > So, until we get a 1.6 server JVM it would seem that 1.5 -server is
> > the best environment to run NG programs.
>
> I don't know what you mean. Sun's JDK 1.6 ships with the Java HotSpot
> server VM. The JRE has never shipped with the server JVM.


Ah! I was using the JRE by mistake!

The 1.6 server JVM gives me a time of 10.6 seconds. That's just 53
times slower than pure Java on the same JVM. Considering that this is
a purely dynamic dispatch via reflection that's an astonishingly good
number.

The extension to reflection API that John and you have proposed will
help even more.


John Wilson

Charles Oliver Nutter

unread,
Jun 27, 2007, 4:04:32 PM6/27/07
to jvm-la...@googlegroups.com

In general we've tried to avoid or limit use of reflection entirely in
JRuby. It's still there and used when in restricted contexts like
applets (funny that reflection is the "less restricted" option here, but
the alternative is our generation of adapter methods/classes for
everything). If it were possible to get back to reflection being "as
fast" as generating direct invoking adapters, we'd gladly go back, but
for now it seems that almost all the best optimizations will ony be
effective on current JVMs by generating specialized methods with
specialized signatures, either ahead-of-time or as appropriate at
runtime. JRuby currently does it only ahead-of-time, and does not
specialize for arities or types. I'm going to look at doing such in the
compiler, rather than going through the pain of doing it by hand
anywhere, ever.

Despite the clunkiness of reflection, it seems like a reasonable window
in the future to making arbitrary method dispatch easier to swallow, so
I think this would have some merit to prototype and play with. However
I'm also interested (perhaps more interested) in techniques that will
work today on current JVMs.

Don't get me wrong...both discussions should continue to happen here.
But with JRuby and other impls still supporting 1.4 users, we have a
long way to go to depending on theoretical Java 7 features.

- Charlie

Charles Oliver Nutter

unread,
Jun 27, 2007, 4:14:55 PM6/27/07
to jvm-la...@googlegroups.com
John Wilson wrote:
> 1.5 client: 20.4 secs server: 11.8 secs
> 1.6 client: 19.2 secs
> So, until we get a 1.6 server JVM it would seem that 1.5 -server is
> the best environment to run NG programs.
>
> Has anybody done any measurements on other dynamic languages to
> determine the optimal JVM choice.

Java 6 server VM is considerably better for JRuby than any other. JRuby
under Java 6 server VM beats C Ruby consistently and definitively for
fib and other simple numerical algorithms.

(numbers are longest/shortest for 8 runs)
JRuby Java 5 client: 2.789/2.401
JRuby Java 5 server: 2.06/1.52
JRuby Java 6 client: 2.6/2.358
JRuby Java 6 server: 2.308/1.135
Ruby 1.8.6: 1.75

Ruby 1.9 is much faster, but it includes specialized bytecodes for
fixnum operations that don't speed up general application performance
very much. In general, Ruby 1.9 is much faster than all others for
microbenchmarks, and about the same for general apps.

Ruby 1.9: 0.38

- Charlie

John Wilson

unread,
Jun 28, 2007, 9:50:28 AM6/28/07
to jvm-la...@googlegroups.com

Thanks for that.

I'm seeing a very similar pattern.

These are the numbers for three versions of Fib. The first is pure
Java, the second is an Ng class implementation the third is Ng using a
recursive closure.
The Ng class implementation has to do method selection and then calls
via reflection whilst the Ng Closure implementation does not have to
do method selection (as a Closure only has one callable method) and
the call is made directly. The numbers I quote are relative to the
fastest Java time (the fastest Java time is 188 milliseconds the
fastest Ng Class time is 9,672 milliseconds and the fastest Ng
Closure time is 4,452 milliseconds.

The micro benchmarks calculate fib(10) the "warm up" the JVM before
doing a timed calculation of fib(35).

1.5 client: Java 1.4, Ng Class 115, Ng Closure 71
1.5 server: Java 1, Ng Class 66, Ng Closure 35
1.6 client: Java 1.4, Ng Class 100, Ng Closure 66
1.5 server: Java 1.1, Ng Class 51, Ng Closure 24

Both Ng Class and Closure method dispatch are fully dynamic (i.e. the
programmer can catch these calls at run time via the MetaClass and can
dynamically change the behaviour whist the program is running).

At first sight looks like using refection is about twice as slow as
direct invocation. However that ignores the fact that the Class
implementation requires method selection. I would guess that 50% of
the extra time is spent selecting the method. So I would expect to see
about a 25% improvement in invocation speed if I compiled the call.

I think the 1.6 server JVM does incredibly well here. I would not have
believed that a relatively unoptimised MetaClass implementation could
achieve a recursive Fib implementation only 25 times slower than pure
Java.


John Wilson

Reply all
Reply to author
Forward
0 new messages