Skip to content

Commit 94c19f8

Browse files
authored
Merge pull request #297 from fglock/fix/range-operator-asm-crash
Fix ASM frame crash when range operator RHS is a constant sub
2 parents b50be6d + c742d95 commit 94c19f8

1 file changed

Lines changed: 25 additions & 3 deletions

File tree

src/main/java/org/perlonjava/backend/jvm/EmitOperator.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -541,9 +541,31 @@ static void handleGlobBuiltin(EmitterVisitor emitterVisitor, OperatorNode node)
541541

542542
// Handles the 'range' operator, which creates a range of values.
543543
static void handleRangeOperator(EmitterVisitor emitterVisitor, BinaryOperatorNode node) {
544-
// Accept both left and right operands in SCALAR context.
545-
node.left.accept(emitterVisitor.with(RuntimeContextType.SCALAR));
546-
node.right.accept(emitterVisitor.with(RuntimeContextType.SCALAR));
544+
// Spill the left operand before evaluating the right side so non-local control flow
545+
// propagation can't jump to returnLabel with an extra value on the JVM operand stack.
546+
if (ENABLE_SPILL_BINARY_LHS) {
547+
MethodVisitor mv = emitterVisitor.ctx.mv;
548+
node.left.accept(emitterVisitor.with(RuntimeContextType.SCALAR));
549+
550+
int leftSlot = emitterVisitor.ctx.javaClassInfo.acquireSpillSlot();
551+
boolean pooled = leftSlot >= 0;
552+
if (!pooled) {
553+
leftSlot = emitterVisitor.ctx.symbolTable.allocateLocalVariable();
554+
}
555+
mv.visitVarInsn(Opcodes.ASTORE, leftSlot);
556+
557+
node.right.accept(emitterVisitor.with(RuntimeContextType.SCALAR));
558+
559+
mv.visitVarInsn(Opcodes.ALOAD, leftSlot);
560+
mv.visitInsn(Opcodes.SWAP);
561+
562+
if (pooled) {
563+
emitterVisitor.ctx.javaClassInfo.releaseSpillSlot();
564+
}
565+
} else {
566+
node.left.accept(emitterVisitor.with(RuntimeContextType.SCALAR));
567+
node.right.accept(emitterVisitor.with(RuntimeContextType.SCALAR));
568+
}
547569
emitOperator(node, emitterVisitor);
548570
}
549571

0 commit comments

Comments
 (0)