perf(stable-api): inline encoding_get for MRI stable versions#730
Merged
Conversation
Avoid the dylib call to rb_enc_get_index for the common case by reading the encoding index directly from RBasic.flags. The inline index is stored in bits RUBY_ENCODING_SHIFT..+7 (= FL_USHIFT+10..+17). Only when the inline slot equals RUBY_ENCODING_INLINE_MAX (0x7f) — meaning the real index is stored out-of-line via an ivar — do we fall back to rb_enc_get_index. Matches CRuby's ENCODING_GET inline function semantics exactly. Tested parity with compiled C shim on ASCII/UTF-8. The C shim (compiled.c) and TruffleRuby's compiled-only path are unchanged — both continue to use ENCODING_GET macro or rb_enc_get_index respectively, since TruffleRuby's RBasic does not expose flags.
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.
Summary
Follow-up to #681. The initial implementation of
encoding_getdelegates to the exportedrb_enc_get_indexfunction on all calls — but for the vast majority of objects (any encoding with index < 0x7f, which covers ASCII, UTF-8, US-ASCII, and all commonly used encodings), the encoding index is stored inline inRBasic.flagsand can be read with no function call.This PR restores the fast path: read the index directly from flags, and only fall back to
rb_enc_get_indexwhen the inline slot reads asRUBY_ENCODING_INLINE_MAX (0x7f), which is the sentinel that CRuby uses to signal "look at the ivar instead."Semantics are unchanged — parity-tested against the compiled C shim.
Changes
crates/rb-sys/src/stable_api/ruby_{2_7,3_0,3_1,3_2,3_3,3_4,4_0}.rs— inline flag read + sentinel fallback.compiled.c/compiled.rs: C side already usesENCODING_GETmacro when defined, and TruffleRuby keeps itsrb_enc_get_indexfallback (noRBasic.flagsexposed).Test plan
test_encoding_get_ascii_string,test_encoding_get_utf8_string)🤖 Generated with Claude Code