mirror of
https://github.com/ruby/ruby.git
synced 2026-07-30 15:41:06 +08:00
jmp_ptr_bytes() reserves room for a patchable jump -- it sets page_end_reserve and bounds conditional jump width. A single `b` suffices when every branch in the code region is in imm26 range; otherwise it reserves 5 instructions for an absolute load-address plus br. The range test was `virtual_region_size() / 4`, but two instructions in an S-byte region are at most S-4 bytes apart. At exactly 128MiB, S/4 is 2^25 while the widest imm26 offset is 2^25-1, so the check gave up one instruction early and took the 5-instruction fallback -- despite the comment right above it saying <= 128 should work. That boundary is the default. exec_mem_size falls back to mem_size in CodegenGlobals::init and mem_size defaults to 128MiB, so every arm64 run without an explicit --yjit-exec-mem-size reserved 20 bytes per patchable jump where 4 would do. On a branch-heavy method that is the difference between 1336 and 956 bytes of inline code. Test (S-4)/4 instead. The decision moves into a small jmp_ptr_bytes_for_region() so a unit test can pin both sides of the boundary without allocating a region that large. --yjit-exec-mem-size=129 still takes the fallback, as before. Checked with `make yjit-check` on arm64 macOS and on Linux/Graviton 4: 374 cargo tests, all bootstraptest at --yjit-call-threshold=1, and test_yjit.rb (142 tests, 0 failures). Since the default size is the boundary case, the whole suite ran on the tightened reservation.