Tuesday August 15, 2006
Calling Conventions - part 2
Well by now you've probably given up hope I'd ever finish the story of
calling conventions and why -Xbatch works differently in Java SE 6.0.
What with a couple of weeks of vacation and catching up a month just
flew by. Time to finish up.
As I said earlier in the previous release of Hotspot we used to have
adapter frame whenever we called between (jit) compiled code and
interpreted code or the reverse. In the 6.0 release we no longer have
adapter frames. Now if you've been paying attention (which is hard
given how infrequently I blog) you'd remember that we clearly must have
to transform parameters on these transition paths so how does it
happen? Well I said we no longer have adapter frames
not that we no longer have adapters. We still have the adapter code
they now don't leave a frame around for the stack walkers to see. This
is good because the more frame types we have the more testing for
various types we have in the code and so less is better.
Now in 6.0 because we are also working toward a tiered compilation
system we moved the generation of adapter code out of the compilers and
now they are generated as needed by some simple signature based shared
code. What's different is how they have to go about massaging the
parameters. Here's a picture:
![]() |
So we see that in this case the arguments were massaged by
extending the frame of the caller and not by introducing a new frame
that the adapter controls. As a result when we are doing stack walking
the stack pointer that is reported for the compiled frame is SP(1)' and not SP(1).
Now this extension causes problem because the compiler reports all of
its usage of stack based locations as offsets from SP(1) and without
some extra magic we'd look in the wrong stack locations for these
compiler variables but we solved this problem long ago and that isn't
the issue here. |
With no frame left behind we can no longer simply unwind. Well we could unwind but it certainly isn't simple. So seemingly our choice is to call the c2i adapter again. This would in fact work but it has the potential of growing the stack without limit in extreme, unrealistic situations. Well the jvm has to continue functioning in those situations and crashing by running out of stack space is not a good idea. Now another choice is to somehow do this transition in place with the stack extension we already have. That is doable and in fact the licensee that first did framelesss adapters did just that. This worked for the architecture in question which was register rich but for something like x86 it was not practical. So instead we came up with a new invariant. "If you reach the interpreter, you will interpret". So the infinite c2i/i2c chain can never occur. One c2i and you're done.
Now in most situations (without -Xbatch) this is really like saying you just missed seeing the compiled code being installed in the old system since you lost the race. Except for the case of -Xbatch. With that mode we'd reach the interpeter and if a compile was triggered we'd wait until it completed and then run compiled. So -Xbatch in effect always let you win that race. In the new system that would violate our invariant and so while we wait for the compile to complete we don't get to execute the code on that particular invocation event. We'd execute it on each susbsequent call to the method so preformance isn't truly impacted, but it can show a difference in behavior in comparison to older jvm's.
Aug 15 2006, 12:55:32 PM EDT Permalink
Comments are closed for this entry.
