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.