Bytecode generation crashes compiling $variable
Invalid bytecode is generated when the expression
$variable is compiled to bytecode. The error is masked (by executing the code in the interpreter) unless Java assertions are enabled.
Task E1 - transforming XSLT-SEF-compiler using the SEF file produced by compiling XSLT-SEF-compiler - crashes when bytecode generation is enabled.
#1 Updated by Michael Kay about 3 years ago
It seems that in the RetainedStaticContext, the defaultFunctionNamespace is null.
Solved that problem by initializing the
But we now get a CannotCompileException attempting to compile a tail-recursive call-template instruction.
#2 Updated by Michael Kay about 3 years ago
This is a consequence of the changes made for bug #4046, to permit bytecode generation for a reloaded package.
Whereas the original compilation avoids injecting BytecodeCandidates for a tail-recursive template, the package reloader is not so smart. In fact, it does not have the information to determine whether a template contains a tail call (other than by searching for it, perhaps).
#3 Updated by Michael Kay about 3 years ago
- Status changed from New to In Progress
We have a mechanism for marking a CannotCompileException as recoverable in cases like this; we should use it. The effect is that the compilation is silently abandoned and processing reverts to the interpreter.
This is working but the test case is now failing for unrelated reasons; I will leave the bug open until I can confirm that the issue is fixed.
#4 Updated by Michael Kay almost 3 years ago
Running the XSLT 3.0 tests using the XX compiler with -export:on and -bytecode:on, I get an NPE crash in -s:as -t:as-0601
java.lang.NullPointerException at com.saxonica.ee.bytecode.LetExpressionCompiler.compileToIterator(LetExpressionCompiler.java:141) at com.saxonica.ee.bytecode.util.CompilerService.compileToIterator(CompilerService.java:769) at com.saxonica.ee.bytecode.ChooseCompiler.compileToIterator(ChooseCompiler.java:42)
It seems that letExpr.getEvaluator() is returning null.
#5 Updated by Michael Kay almost 3 years ago
I don't know why the evaluator isn't set on this LetExpression. I added code to LetExpressionCompiler to make it more resilient (by using a default evaluator), but we now get invalid bytecode generated.
I've changed the exception handling for exceptions thrown by ga.endMethod() to use the same error handler used elsewhere (handleCodeGeneratorException()) - this aborts the run if Java assertions are enabled, but recovers (using interpreted code) otherwise.
Clearly this doesn't address the core issue.
#6 Updated by Michael Kay almost 3 years ago
Finally getting some diagnostics on the bytecode generation, though it's tough to analyse them.
The failure is in compiling the
f:typeCheck() function in type.xsl line 531.
DocumentInstrCompiler.compileToIterator() had potential to return an EmptySequence rather than a SequenceIterator; fixed this, but it didn't solve the problem.
I devised a new debugging technique to pin down the area of failure: when we fail to compile an expression, we then attempt to compile its operand expressions, and so on recursively, until we find the smallest expression that triggers the failure. This turned out to be the very simple filter expression
$diag.parts, and the faulty code was in FilterExpressionCompiler line 112 where it fails to duplicate a value before testing it for null.
With this change, the XSLT 3.0 test suite, using the XX compiler with bytecode enabled, is running to completion, reporting 338 test failures. Many of these are tests involving packages, which the XX compiler does not yet fully support.
#7 Updated by Michael Kay almost 3 years ago
- Subject changed from Bytecode generation crashes for XSLT-in-XSLT compiler when loaded from SEF file to Bytecode generation crashes compiling $variable
- Description updated (diff)
- Category set to Byte code generation
- Status changed from In Progress to Resolved
- Applies to branch trunk added
- Fix Committed on Branch 9.9, trunk added
Fixed by a patch to FfilterExpressionCompiler.
I have also improved the diagnostic analysis when DEBUG_BYTECODE is set and a VerifyError occurs. We now attempt to generate bytecode for the subexpressions of the failing expression, and so on recursively, eventually finding the smallest expression for which bytecode generation fails. The makes it much easier to identify where the incorrect code-generating code is to be found.
Please register to edit this issue