Every now and then (see ticket 117 for a current example), an issue
pops up where we fail class file verification with a stack
inconsistency error. The problem is that in some specific cases, it's
impossible to accumulate function call argument values on the stack:
the JVM clears out the stack in these cases.
Next to storing values on the stack, the JVM offers local variables.
These don't get cleared out. Historically, we have solved the problem
by 'rewriting' the code being compiled in a way that made it store its
values in local variables. This rewriting happens in pass1 of the
compiler, based on the outcome of a the 'safety scanning function'
UNSAFE-P.
However, this function is overeager (will classify too many cases as
unsafe) and it needs to be manually added to all cases which may end
up being problematic in pass2.
My proposal is now to add infrastructure to pass2 to handle the
situation: Some blocks of code need to be marked as "collecting
function call arguments". Then, upon the compilation of each argument,
the new infrastructure would analyse the form being compiled. If that
form will contain 'unsafe' bits, the compiler will automatically
switch collection of function call arguments to local variables
instead of on the stack.
My idea would be to add a macro called WITH-STACK-PARAMETER-COLLECTION
and an accompanying COMPILE-STACK-PARAMETER. The macro would set up
some special variables for the COMPILE-STACK-PARAMETER to inspect and
set. At the end of the macro, code will be emitted to make sure all
the values are correctly loaded on the stack, just as if they had
always been there.
The pass1 form rewriting could be eliminated and our decision rules
about what's 'unsafe' and what's not would be completely correct,
instead of "overeager, but at least not missing any cases" [the latter
it obviously does, since pass1 needs to estimate what pass2 will be
compiling].
Any comments?
Regards,
Erik.