ruby: Handle Ruby JIT PC with JIT frame type (upstream prep)#37
Draft
ruby: Handle Ruby JIT PC with JIT frame type (upstream prep)#37
Conversation
c6ca0a4 to
cc382ef
Compare
dalehamel
commented
Apr 8, 2026
Member
Author
dalehamel
left a comment
There was a problem hiding this comment.
Review assisted by pair-review
dalehamel
commented
Apr 8, 2026
Member
Author
dalehamel
left a comment
There was a problem hiding this comment.
Review assisted by pair-review
dalehamel
commented
Apr 8, 2026
5831ed4 to
e151da4
Compare
…1337) Signed-off-by: Florian Lehner <florian.lehner@elastic.co> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Florian Lehner <florian.lehner@elastic.co>
41b4e54 to
ecf5e25
Compare
…1139) Signed-off-by: Florian Lehner <florian.lehner@elastic.co> Co-authored-by: Mattia Meleleo <melmat@tuta.io> Co-authored-by: Christos Kalkanis <christos.kalkanis@elastic.co> Co-authored-by: Roger Coll <roger.coll@elastic.co>
f82597d to
acebe8c
Compare
… cleanup - Extract JIT region detection into standalone findJITRegion() function that handles both prctl-labeled mappings (spanning full reserved area including holes) and heuristic fallback (first anonymous executable mapping) - Add comprehensive unit tests for JIT region detection: no mappings, file-backed only, labeled single/multiple, heuristic fallback, precedence - Fix Detach() to clean up PidInterpreterMapping prefixes (previously only deleted proc data, leaking eBPF map entries) - Remove dead code: m.Vaddr < jitMapping.Vaddr branch that could never be true since /proc/pid/maps is sorted by address
- Fix JIT region check to use >= for lower bound (half-open interval [start, end)) matching V8 and HotSpot conventions - Reuse map lookup value to avoid double hashing of RawMapping struct key - Wrap CalculatePrefixList error for better debugging - Log stale prefix deletion errors instead of silently discarding - Move prctl(PR_SET_VMA) named anonymous mapping support from process/process.go (was in PR #36 but is needed here for findJITRegion labeled detection) - Remove stale 'assume all anonymous' comment - Rebuild BPF blobs for >= fix
- Add 'Register LPM prefixes' comment to SynchronizeMappings loop - Extract in_jit bool variable from inline if condition for clarity - Improve JIT detection comments (read_ruby_frame and walk_ruby_stack) - Fix whitespace: add blank line after FRAMES_PER_WALK_RUBY_STACK define, normalize MAX_EP_CHECKS spacing - Rebuild BPF blobs
Ruby 3.4.7 with --yjit on arm64. Verifies that: - JIT code region is detected from anonymous executable mappings - A JIT frame is pushed for the YJIT-compiled code - Ruby VM frames (is_prime, sum_of_primes, loop) are properly unwound after the JIT frame On main, this coredump fails with native_no_pid_page_mapping because the profiler doesn't know how to handle the anonymous JIT mapping. Moduledata tar for CI upload: ~/coredump-uploads/ruby-yjit-moduledata.tar
Ruby 3.4.7 with --yjit on x86_64. Same verification as arm64 test: - JIT code region detected from anonymous executable mappings - JIT frame pushed for YJIT-compiled code - Full Ruby VM stack unwound (is_prime, sum_of_primes, loop) Moduledata tar: ~/coredump-uploads/ruby-yjit-amd64-moduledata.tar
On systems with CONFIG_ANON_VMA_NAME=y, Ruby labels its JIT memory region via prctl(PR_SET_VMA), giving it a path like '[anon:Ruby:rb_yjit_reserve_addr_space]'. Without this fix, IsFileBacked() returns true for these mappings (non-empty Path), causing IsAnonymous() to return false. This prevents the LPM prefix registration loop in SynchronizeMappings from registering JIT executable pages for eBPF dispatch. Add IsPrctlNamed() helper and exclude prctl-named mappings from IsFileBacked(), so they are correctly classified as anonymous.
Co-authored-by: Florian Lehner <florianl@users.noreply.github.com>
Adapt SynchronizeMappings to work with uint32 values instead of *uint32 pointers: since generations are no longer shared via pointer, both mappings and their prefixes must be updated independently each cycle. Use an isNew flag to only call UpdatePidInterpreterMapping for newly discovered mappings.
Address florianl's concern about unlimited growth: entries are pruned each SynchronizeMappings call via generation tracking, and the map size is bounded by the number of executable anonymous mappings per process.
Only push the JIT frame when trace->num_frames == 0 (leaf position), restoring the original behavior. Without this guard, when native frames were already unwound before the Ruby unwinder runs, the JIT frame was pushed deep in the stack instead of at the leaf, causing it to appear as the root frame in flamegraphs.
This reverts commit f88aaa3.
walk_ruby_stack is re-entered via tail calls to process more frames. On re-entry, in_jit was recomputed from record->state.pc which hasn't changed (non-FP path), causing the JIT frame to be pushed again on every tail call. Guard with !jit_detected so the JIT frame is only pushed once on the first entry.
acebe8c to
83ef589
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.
Rebased version of upstream PR open-telemetry#1102 for staging before upstream submission.
BPF blobs will need rebuilding.