@@ -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