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.
On 6/5/07, Brian Frank <briansfr...@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.
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 wrote: > On 6/5/07, Brian Frank <briansfr...@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.
> 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).
>> 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.
> 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.
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 :)
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.)
> 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.)
> 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.
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.
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.
On 6/8/07, Brian Frank <briansfr...@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.
> 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.
John Wilson wrote: > On 6/8/07, Brian Frank <briansfr...@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.
> John Wilson wrote: [snip] > 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.
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
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
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
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.
> 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.)
> 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.
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.
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?
John Rose wrote: > 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?
> John Rose wrote: > > 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?
> Sounds like the right approach.
> > Someone should prototype this...
> Anyone up for some OpenJDK hacking?
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.
John Wilson wrote: > On 6/8/07, Kenneth Russell <Kenneth.Russ...@sun.com> wrote: >> John Rose wrote: >>> 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? >> Sounds like the right approach.
>>> Someone should prototype this... >> Anyone up for some OpenJDK hacking?
> 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?
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.
On 6/11/07, Kenneth Russell <Kenneth.Russ...@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?
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.
> 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.