Merged
Conversation
1cf15df to
5cc39e8
Compare
This was referenced Nov 21, 2025
dabf18d to
17bc1d6
Compare
This adds specialized RubyFixnum subtypes for byte, short, int, and long, making RubyFixnum abstract. All allocations of a Fixnum are boxed using the most compact size. This drastically reduces the memory requirements for non-64-bit fixnums and likely improves allocation rate due to the smaller object and reduced overhead from zeroing.
The fixnum specialization triggered a bug in hash calculation where something like [257,1] could hash differently depending on when during execution it was calculated. The specific case was in resolv.rb, which sets up a hash of integer pairs pointing at the Class object associated with that DNS code. Later accesses hashed the given pair differently and ended up replacing the earlier entry. The source of this problem is not entirely clear to me, but it was fixed by ensuring that we never construct a cacheable fixnum value and always use the cached values. I suspect this is a flaw in the design of the safeRecurse logic, which uses an IdentityHashMap when invoking `hash` on nested elements, but I cannot explain how having two different fixnum instances could trigger this problem. There are other issues with safeRecurse that, when fixed, would also work around this problem (see jruby#9086) but it is at least clear that the fixnum specialization must be "absolute"; in other words, we must always use the cached instances for the supported range (to ensure they retain identity) and always use the same fixnum type for a given value range (so we don't end up with two fixnums of the same value but different class). These problems do not affect CRuby because fixnums are idempotent due to their use of tagged pointers; there can never be two fixnum objects because they are never objects.
There's no particular value in checking the exact type here, so just confirm that it's a RubyFixnum-adjacent type.
The change here is based on two ideas: * Manually-inlined range checks for each level in each factory method is error-prone and hard to update (e.g. if we change how fixnum caching works) It also fixes an inability to set the fixnum cache size larger than short range or smaller than byte range by restoring the cache range checks to both integer and byte paths. This may be reexamined for jruby#9087.
Current object layout has 1 byte of waste for ByteFixnum, not really saving us anything by having another polymorphic type. We can revisit this in the future.
17bc1d6 to
2cb43af
Compare
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.
This adds specialized RubyFixnum subtypes for byte, short, int, and long, making RubyFixnum abstract. All allocations of a Fixnum are boxed using the most compact size.
This drastically reduces the memory requirements for non-64-bit fixnums and likely improves allocation rate due to the smaller object and reduced overhead from zeroing.