Repository navigation
Push a range for every end when the begin is a Fixnum - #9833
Merged
Merged
Conversation
JVMVisitor#Range returned after the Fixnum begin branch even when the end was neither a Fixnum nor nil, so a range like (1..2.0) pushed nothing and left the stack one value short. Depending on the code around it, that showed up as a VerifyError or as an exception from ASM, and the method stayed interpreted. Return only from the branches that push something, so other ends fall through to the generic path. That path's AOT version called a RubyRange.newRange overload that doesn't exist, and ignored exclusive ranges, so it now calls newInclusiveRange or newExclusiveRange. A string end, as in (1.."3"), still doesn't compile, because of jruby#9822. Fixes jruby#9823
sferik
force-pushed
the
jit-fixnum-range
branch
from
October 19, 2026 23:49
4dbf4ac to
d2e9072
Compare
sferik
added a commit
to sferik/jruby
that referenced
this pull request
Oct 19, 2026
buildRange turned a string literal endpoint into a FrozenString with
the StrNode's file name, but Node#getFile always returns null. When
both endpoints were literals the file was never used, but a range like
"a"..x or ("a"..) visits the FrozenString on its own, which passes the
file to invokedynamic as a bootstrap argument, and ASM rejects null.
Those methods couldn't be JIT-compiled.
Use scope.getFile(), as every other FrozenString in the builder does.
Endless and beginless string ranges also go through the AOT fallback in
NormalValueCompiler#pushRange, which called a RubyRange.newRange
overload that doesn't exist. This includes the same fix for that as
jruby#9833, so the two merge cleanly in
either order.
Fixes jruby#9822
headius
approved these changes
Oct 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #9823.
JVMVisitor#Rangehas fast paths for a few literal range shapes. When the begin was aFixnum, it returned after checking for aFixnumornilend, even if the end was neither, so something like(1..2.0)pushed nothing and left the stack one value short. Depending on the surrounding code, that came out as aVerifyError, anArrayIndexOutOfBoundsExceptionor aNegativeArraySizeException, and the method stayed interpreted.Now it only returns from the branches that actually push a range, so any other end falls through to the generic path at the bottom, as
(1.0..10)already did.Testing that path in AOT mode turned up a second problem:
NormalValueCompiler#pushRangecalled aRubyRange.newRange(ThreadContext, IRubyObject, IRubyObject)overload that doesn't exist, in both branches, so it would have thrownNoSuchMethodErrorand ignored exclusive ranges anyway. It now callsnewInclusiveRangeornewExclusiveRange. The JIT usesIndyValueCompilerfor values even with invokedynamic off, so this only affected AOT-compiled code.The new spec covers Float, Rational and Bignum ends, and inclusive and exclusive ranges. It fails in JIT and AOT mode before this change and passes in all four modes after it. Ranges with a string end, like
(1.."3"), still don't compile, but that's #9822, which is a separate fix.