This page contains an archived post to the Design Forum (formerly called the Flexible Java Forum) made prior to February 25, 2002.
If you wish to participate in discussions, please visit the new
Artima Forums.
Message:
Some pseudocode
Posted by Bill Venners on 24 Jun 1998, 11:28 PM
Let me make another pass at this: > > Was the article just simplified from a technical perspective, > > or do we really not know more about how this method inlining > > would function? It doesn't make much sense to me because at best > > you'll still be left with a conditional branch in the code, one > > direction of which is a function call, and that doesn't seem much > > easier to optimize around than a method call. And it certainly > > seems slower in and of itself than it would be to just call a > > function indirectly (a single instruction even on the 6052, much > > less modern CPU architectures!) > > Basically you aren't optimizing the method call, because that is the atypical case. If you have something like this in bytecodes: interface Talkable { String talk(); } class BadCop { void makeThisTalk(Talkable suspect) { // We have ways... String confession; do { // do some bad cop stuff... confession = suspect.talk(); } while (confession.length() == 0); } }
At runtime Hotspot may discover that only one class of object is ever being passed to makeThisTalk(), let's say its class InnocentBystander. Assuming this bit of code is in the hotspot, what the optimizer could do with it is: class BadCop { void makeThisTalk(Talkable suspect) { // We have ways... String confession; do { // do some bad cop stuff... if (suspect's class is InnocentBystander) { Here, InnocentBystander's talk() method is inlined. There is no method invocation of the talk() method here. } else { confession = suspect.talk() } } while (confession.length() == 0); } }
OK, so the place where more optimization can go on is in the case where the suspect's class is actually InnocentBystander, not in the other case. But the point is that the reason you made this extra if block for InnocentBystander in the first place is because you observed that the Talkable being passed has so far always been of class InnocentBystander. This means that the fact that the method invocation part of this if/else (the else case) isn't much easier to optimize around doesn't matter, because its never being used. And apparently most instance method invocations turn out to be monomorphic like this in practice: there is only one class's implementation being called. And if hotspot notices that sometime later, that else clause is being used, because suddenly someone has started passing in instances of the GuiltyParty class, hotspot can rerun the optimizer on the method to get something like this: class BadCop { void makeThisTalk(Talkable suspect) { // We have ways... String confession; do { // do some bad cop stuff... if (suspect's class is InnocentBystander) { Here, InnocentBystander's talk() method is inlined. There is no method invocation of the talk() method here. } else if (suspect's class is GuiltyParty { Here, GuiltyParty's talk() method is inlined. There is no method invocation of the talk() method here. } else { confession = suspect.talk() } } while (confession.length() == 0); } }
So once again, if this code is in the hotpot, the VM can keep optimizing it according to how it is being used. Here it has managed to inline two different object's talk() methods and let the optimizer work on the inlined code. And by observation these are the only two implementations of talk() that matter at that point in the execution of the program. bv
Replies:
|