summaryrefslogtreecommitdiff
path: root/yjit
AgeCommit message (Collapse)Author
2025-01-30YJIT: Explicitly specify C ABI to fix a nightly Rust warningAlan Wu
2025-01-29YJIT: A64: Remove assert that trips when OOM at page boundaryAlan Wu
With a well-timed OOM around a page switch in the backend, it can return RetryOnNextPage twice and crash due to the assert. (More places can signal OOM now since VirtualMem tracks Rust malloc heap size for --yjit-mem-size.) Return error in these cases instead of crashing. Fixes: https://github.com/Shopify/ruby/issues/566 Notes: Merged: https://github.com/ruby/ruby/pull/12668
2025-01-28YJIT: Initialize locals in ISeqs defined with `...` (#12660)Alan Wu
* YJIT: Fix indentation [ci skip] Fixes: cdf33ed5f37f9649c482c3ba1d245f0d80ac01ce * YJIT: Initialize locals in ISeqs defined with `...` Previously, callers of forwardable ISeqs moved the stack pointer up without writing to the stack. If there happens to be a stale value in the area skipped over, it could crash due to "try to mark T_NONE". Also, the uninitialized local variables were observable through `binding`. Initialize the locals to nil. [Bug #21021] Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2025-01-10YJIT: Rename send_iseq_forwarding->send_forwardingAlan Wu
It's in gen_send_general(), so nothing specifically to do with iseqs. Notes: Merged: https://github.com/ruby/ruby/pull/12550
2025-01-10Make rb_vm_insns_count a thread local variableAaron Patterson
`rb_vm_insns_count` is a global variable used for reporting YJIT statistics. It is a counter that tallies the number of interpreter instructions that have been executed, this way we can approximate how much time we're spending in YJIT compared to the interpreter. Unfortunately keeping this statistic means that every instruction executed in the interpreter loop must increment the counter. Normally this isn't a problem, but in multi-threaded situations (when Ractors are used), incrementing this counter can become quite costly due to page caching issues. Additionally, since there is no locking when incrementing this global, the count can't really make sense in a multi-threaded environment. This commit changes `rb_vm_insns_count` to a thread local. That way each Ractor has it's own copy of the counter and incrementing the counter becomes quite cheap. Of course this means that in multi-threaded situations, the value doesn't really make sense (but it didn't make sense before because of the lack of locking). The counter is used for YJIT statistics, and since YJIT is basically disabled when Ractors are in use, I don't think we care about inaccuracies (for the time being). We can revisit this counter when we give YJIT multi-threading support, but for the time being this commit restores multi-threaded performance. To test this, I used the benchmark in [Bug #20489]. Here is the performance on Ruby 3.2: ``` $ time RUBY_MAX_CPU=12 ./miniruby -v ../test.rb 8 8 ruby 3.2.0 (2022-12-25 revision a528908271) [x86_64-linux] [0...1, 1...2, 2...3, 3...4, 4...5, 5...6, 6...7, 7...8] ../test.rb:43: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. ________________________________________________________ Executed in 2.53 secs fish external usr time 19.86 secs 370.00 micros 19.86 secs sys time 0.02 secs 320.00 micros 0.02 secs ``` We can see the regression in performance on the master branch: ``` $ time RUBY_MAX_CPU=12 ./miniruby -v ../test.rb 8 8 ruby 3.5.0dev (2025-01-10T16:22:26Z master 4a2702dafb) +PRISM [x86_64-linux] [0...1, 1...2, 2...3, 3...4, 4...5, 5...6, 6...7, 7...8] ../test.rb:43: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. ________________________________________________________ Executed in 24.87 secs fish external usr time 195.55 secs 0.00 micros 195.55 secs sys time 0.00 secs 716.00 micros 0.00 secs ``` Here are the stats after this commit: ``` $ time RUBY_MAX_CPU=12 ./miniruby -v ../test.rb 8 8 ruby 3.5.0dev (2025-01-10T20:37:06Z tl 3ef0432779) +PRISM [x86_64-linux] [0...1, 1...2, 2...3, 3...4, 4...5, 5...6, 6...7, 7...8] ../test.rb:43: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. ________________________________________________________ Executed in 2.46 secs fish external usr time 19.34 secs 381.00 micros 19.34 secs sys time 0.01 secs 321.00 micros 0.01 secs ``` [Bug #20489] Notes: Merged: https://github.com/ruby/ruby/pull/12549
2025-01-08YJIT: Filter `&` calls from specialized C method codegenAlan Wu
Evident with the crash reported in [Bug #20997], the C replacement codegen functions aren't authored to handle block arguments (nor should they because the extra code from the complexity defeats optimization). Filter sites with VM_CALL_ARGS_BLOCKARG. Notes: Merged: https://github.com/ruby/ruby/pull/12536
2025-01-04YJIT: Fix crash when yielding keyword argumentsAlan Wu
Previously, the code for dropping surplus arguments when yielding into blocks erroneously attempted to drop keyword arguments when there is in fact no surplus arguments. Fix the condition and test that supplying the exact number of keyword arguments as require compiles without fallback. Notes: Merged: https://github.com/ruby/ruby/pull/12499
2024-12-23YJIT: Return None if entry block compilation fails (#12445)Takashi Kokubun
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2024-12-17YJIT: Load registers on JIT entry to reuse blocks (#12355)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-12-13YJIT: Speculate block arg for `c_func_method(&nil)` calls (#12326)Alan Wu
A good amount of call sites always pass nil as block argument, but the nil doesn't show up in the context. Put a runtime guard for those cases to handle it. Particular relevant for the `ruby-lsp` benchmark in `yjit-bench`. Up to a 2% speedup across headline benchmarks. Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Co-authored-by: Kevin Menard <kevin@nirvdrum.com> Co-authored-by: Randy Stauner <randy.stauner@shopify.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-12-12YJIT: Allow then-unknown `static_mut_refs` on older Rusts [ci skip]Alan Wu
2024-12-11YJIT: Fix unread field lint in release buildsAlan Wu
``` warning: fields `blue_begin` and `blue_end` are never read ``` Notes: Merged: https://github.com/ruby/ruby/pull/12310
2024-12-11YJIT: Disable static_mut_refs for nowAlan Wu
Notes: Merged: https://github.com/ruby/ruby/pull/12310
2024-12-11YJIT: Use the correct size constantAlan Wu
Notes: Merged: https://github.com/ruby/ruby/pull/12310
2024-12-09YJIT: Add a comment about a lazy frame callTakashi Kokubun
jit_prepare_lazy_frame_call is a complicated trick and comes with memory overhead. Every use of the function should come with justification.
2024-12-09YJIT: Spill/load argument registers to reuse blocks (#12287)Takashi Kokubun
* YJIT: Spill/load argument registers to reuse blocks * Mention the immediate function name * Explain the context behind spill/load operations Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2024-12-09YJIT: Only enable disassembly colors for tty (#12283)Max Bernstein
* YJIT: Use fully-qualified name for OPTIONS in get_options! * YJIT: Only enable disassembly colors for tty Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-12-04YJIT: Generate specialized code for Symbol for objtostring (#12247)Maximillian Polhill
* YJIT: Generate specialized code for Symbol for objtostring Co-authored-by: John Hawthorn <john@hawthorn.email> * Update yjit/src/codegen.rs --------- Co-authored-by: John Hawthorn <john@hawthorn.email> Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-12-04YJIT: track time since initialization (#12263)Maxime Chevalier-Boisvert
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-11-29YJIT: Avoid std::ffi::CString with rb_intern2() during bootAlan Wu
Fewer allocations on boot, too. Suggested-by: https://github.com/ruby/ruby/pull/12217 Notes: Merged: https://github.com/ruby/ruby/pull/12220
2024-11-28YJIT: Add missing prepare before calling str_dupJohn Hawthorn
Notes: Merged: https://github.com/ruby/ruby/pull/12202
2024-11-26YJIT: Implement opt_reverse insn (#12175)Randy Stauner
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-11-26Optimize instructions when creating an array just to call `include?` (#12123)Randy Stauner
* Add opt_duparray_send insn to skip the allocation on `#include?` If the method isn't going to modify the array we don't need to copy it. This avoids the allocation / array copy for things like `[:a, :b].include?(x)`. This adds a BOP for include? and tracks redefinition for it on Array. Co-authored-by: Andrew Novoselac <andrew.novoselac@shopify.com> * YJIT: Implement opt_duparray_send include_p Co-authored-by: Andrew Novoselac <andrew.novoselac@shopify.com> * Update opt_newarray_send to support simple forms of include?(arg) Similar to opt_duparray_send but for non-static arrays. * YJIT: Implement opt_newarray_send include_p --------- Co-authored-by: Andrew Novoselac <andrew.novoselac@shopify.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-11-25YJIT: fix small typo in command line options help (#12167)Maxime Chevalier-Boisvert
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-11-20YJIT: Make compilation_failure a default stat (#12128)Alan Wu
It's good to monitor compilation failures. Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-11-20YJIT: Refactor to forward jump_to_next_insn() return valueAlan Wu
It's more concise this way and since `return Some(EndBlock)` is the only correct answer, no point repeating it everywhere. Notes: Merged: https://github.com/ruby/ruby/pull/12124
2024-11-20YJIT: Abandon block when gen_outlined_exit() failsAlan Wu
When CodeBlock::set_page fails (part of next_page(), see their docs for exact conditions), it can cause gen_outlined_exit() to fail while there is still plenty of memory available. Previously, this can have YJIT running incomplete code due to taking the early return in end_block_with_jump() that manifested as crashes with SIGILL. Add and use a wrapper with error handling. Notes: Merged: https://github.com/ruby/ruby/pull/12124
2024-11-14YJIT: Specialize String#dup (#12090)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-11-14YJIT: Specialize Integer#pred (#12082)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-11-13YJIT: Add inline_block_count stat (#12081)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-11-13YJIT: Specialize `String#[]` (`String#slice`) with fixnum arguments (#12069)Randy Stauner
* YJIT: Specialize `String#[]` (`String#slice`) with fixnum arguments String#[] is in the top few C calls of several YJIT benchmarks: liquid-compile rubocop mail sudoku This speeds up these benchmarks by 1-2%. * YJIT: Try harder to get type info for `String#[]` In the large generated code of the mail gem the context doesn't have the type info. In that case if we peek at the stack and add a guard we can still apply the specialization and it speeds up the mail benchmark by 5%. Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Co-authored-by: Takashi Kokubun (k0kubun) <takashikkbn@gmail.com> --------- Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Co-authored-by: Takashi Kokubun (k0kubun) <takashikkbn@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-11-13Mark strings returned by Symbol#to_s as chilled (#12065)Jean byroot Boussier
* Use FL_USER0 for ELTS_SHARED This makes space in RString for two bits for chilled strings. * Mark strings returned by `Symbol#to_s` as chilled [Feature #20350] `STR_CHILLED` now spans on two user flags. If one bit is set it marks a chilled string literal, if it's the other it marks a `Symbol#to_s` chilled string. Since it's not possible, and doesn't make much sense to include debug info when `--debug-frozen-string-literal` is set, we can't include allocation source, but we can safely include the symbol name in the warning message, making it much easier to find the source of the issue. Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com> --------- Co-authored-by: Étienne Barrié <etienne.barrie@gmail.com> Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2024-11-11Fix false-positive memory leak using Valgrind in YJIT (#12057)Peter Zhu
When we run with RUBY_FREE_AT_EXIT, there's a false-positive memory leak reported in YJIT because the METHOD_CODEGEN_TABLE is never freed. This commit adds rb_yjit_free_at_exit that is called at shutdown when RUBY_FREE_AT_EXIT is set. Reported memory leak: ==699816== 1,104 bytes in 1 blocks are possibly lost in loss record 1 of 1 ==699816== at 0x484680F: malloc (vg_replace_malloc.c:446) ==699816== by 0x155B3E: UnknownInlinedFun (unix.rs:14) ==699816== by 0x155B3E: UnknownInlinedFun (stats.rs:36) ==699816== by 0x155B3E: UnknownInlinedFun (stats.rs:27) ==699816== by 0x155B3E: alloc (alloc.rs:98) ==699816== by 0x155B3E: alloc_impl (alloc.rs:181) ==699816== by 0x155B3E: allocate (alloc.rs:241) ==699816== by 0x155B3E: do_alloc<alloc::alloc::Global> (alloc.rs:15) ==699816== by 0x155B3E: new_uninitialized<alloc::alloc::Global> (mod.rs:1750) ==699816== by 0x155B3E: fallible_with_capacity<alloc::alloc::Global> (mod.rs:1788) ==699816== by 0x155B3E: prepare_resize<alloc::alloc::Global> (mod.rs:2864) ==699816== by 0x155B3E: resize_inner<alloc::alloc::Global> (mod.rs:3060) ==699816== by 0x155B3E: reserve_rehash_inner<alloc::alloc::Global> (mod.rs:2950) ==699816== by 0x155B3E: hashbrown::raw::RawTable<T,A>::reserve_rehash (mod.rs:1231) ==699816== by 0x5BC39F: UnknownInlinedFun (mod.rs:1179) ==699816== by 0x5BC39F: find_or_find_insert_slot<(usize, fn(&mut yjit::codegen::JITState, &mut yjit::backend::ir::Assembler, *const yjit::cruby::autogened::rb_callinfo, *const yjit::cruby::autogened::rb_callable_method_entry_struct, core::option::Option<yjit::codegen::BlockHandler>, i32, core::option::Option<yjit::cruby::VALUE>) -> bool), alloc::alloc::Global, hashbrown::map::equivalent_key::{closure_env#0}<usize, usize, fn(&mut yjit::codegen::JITState, &mut yjit::backend::ir::Assembler, *const yjit::cruby::autogened::rb_callinfo, *const yjit::cruby::autogened::rb_callable_method_entry_struct, core::option::Option<yjit::codegen::BlockHandler>, i32, core::option::Option<yjit::cruby::VALUE>) -> bool>, hashbrown::map::make_hasher::{closure_env#0}<usize, fn(&mut yjit::codegen::JITState, &mut yjit::backend::ir::Assembler, *const yjit::cruby::autogened::rb_callinfo, *const yjit::cruby::autogened::rb_callable_method_entry_struct, core::option::Option<yjit::codegen::BlockHandler>, i32, core::option::Option<yjit::cruby::VALUE>) -> bool, std::hash::random::RandomState>> (mod.rs:1413) ==699816== by 0x5BC39F: hashbrown::map::HashMap<K,V,S,A>::insert (map.rs:1754) ==699816== by 0x57C5C6: insert<usize, fn(&mut yjit::codegen::JITState, &mut yjit::backend::ir::Assembler, *const yjit::cruby::autogened::rb_callinfo, *const yjit::cruby::autogened::rb_callable_method_entry_struct, core::option::Option<yjit::codegen::BlockHandler>, i32, core::option::Option<yjit::cruby::VALUE>) -> bool, std::hash::random::RandomState> (map.rs:1104) ==699816== by 0x57C5C6: yjit::codegen::reg_method_codegen (codegen.rs:10521) ==699816== by 0x57C295: yjit::codegen::yjit_reg_method_codegen_fns (codegen.rs:10464) ==699816== by 0x5C6B07: rb_yjit_init (yjit.rs:40) ==699816== by 0x393723: ruby_opt_init (ruby.c:1820) ==699816== by 0x393723: ruby_opt_init (ruby.c:1767) ==699816== by 0x3957D4: prism_script (ruby.c:2215) ==699816== by 0x3957D4: process_options (ruby.c:2538) ==699816== by 0x396065: ruby_process_options (ruby.c:3166) ==699816== by 0x236E56: ruby_options (eval.c:117) ==699816== by 0x15BAED: rb_main (main.c:43) ==699816== by 0x15BAED: main (main.c:62) After this patch, there are no more memory leaks reported when running RUBY_FREE_AT_EXIT with Valgrind on an empty Ruby script: $ RUBY_FREE_AT_EXIT=1 valgrind --leak-check=full ruby -e "" ... ==700357== HEAP SUMMARY: ==700357== in use at exit: 0 bytes in 0 blocks ==700357== total heap usage: 36,559 allocs, 36,559 frees, 6,064,783 bytes allocated ==700357== ==700357== All heap blocks were freed -- no leaks are possible Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-11-08YJIT: Always abandon the block when gen_branch() or defer_compilation() failsAlan Wu
In [1], we started checking for gen_branch failures, but I made two crucial mistakes. One, defer_compilation() had the same issue as gen_branch() but wasn't checked. Two, returning None from a codegen function does not throw away the block. Checking how gen_single_block() handles codegen functions, you can see that None terminates the block with an exit, but does not overall return an Err. This handling is fine for unimplemented instructions, for example, but incorrect in case gen_branch() fails. The missing branch essentially corrupts the block; adding more code after a missing branch doesn't correct the code. Always abandon the block when defer_compilation() or gen_branch() fails. [1]: cb661d7d82984cdb54485ea3f4af01ac21960882 Fixup: [1] Notes: Merged: https://github.com/ruby/ruby/pull/12035 Merged-By: XrXr
2024-11-08YJIT: Pass panic message to rb_bug()Alan Wu
So that the Rust panic message is forwarded to the RUBY_CRASH_REPORT system, instead of only the static "YJIT panicked" message done so previously. This helps with triaging crashes since it's easier than trying to parse stderr output. Sample: <internal:yjit_hook>:2: [BUG] YJIT: panicked at src/codegen.rs:1197:5: explicit panic ... Notes: Merged: https://github.com/ruby/ruby/pull/12027
2024-11-06Ignore return value of `into_raw_fd`Nobuyoshi Nakada
Fix as the compiler orders: ``` warning: unused return value of `into_raw_fd` that must be used --> ../src/yjit/src/disasm.rs:123:21 | 123 | file.into_raw_fd(); // keep the fd open | ^^^^^^^^^^^^^^^^^^ | = note: losing the raw file descriptor may leak resources = note: `#[warn(unused_must_use)]` on by default help: use `let _ = ...` to ignore the resulting value | 123 | let _ = file.into_raw_fd(); // keep the fd open | +++++++ warning: unused return value of `into_raw_fd` that must be used --> ../src/yjit/src/log.rs:84:21 | 84 | file.into_raw_fd(); // keep the fd open | ^^^^^^^^^^^^^^^^^^ | = note: losing the raw file descriptor may leak resources help: use `let _ = ...` to ignore the resulting value | 84 | let _ = file.into_raw_fd(); // keep the fd open | +++++++ ``` Notes: Merged: https://github.com/ruby/ruby/pull/12009
2024-11-04YJIT: Replace Array#each only when YJIT is enabled (#11955)Takashi Kokubun
* YJIT: Replace Array#each only when YJIT is enabled * Add comments about BUILTIN_ATTR_C_TRACE * Make Ruby Array#each available with --yjit as well * Fix all paths that expect a C location * Use method_basic_definition_p to detect patches * Copy a comment about C_TRACE flag to compilers * Rephrase a comment about add_yjit_hook * Give METHOD_ENTRY_BASIC flag to Array#each * Add --yjit-c-builtin option * Allow inconsistent source_location in test-spec * Refactor a check of BUILTIN_ATTR_C_TRACE * Set METHOD_ENTRY_BASIC without touching vm->running Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-10-23YJIT: Make PendingBranch::set_target `must_use` [ci skip]Alan Wu
2024-10-23YJIT: Check when gen_branch() failsAlan Wu
We got some core dumps in the wild where a PendingBranch had everything as None, leading to a panic unwrapping in PendingBranch::into_branch(). This happened while compiling a `branchif`. It seems that the only way this can happen is when core::gen_branch() fails, but not due to OOM. We wouldn't have reach into_branch() when OOM, and the only way to not leave markers that would've set the branch's start_addr to some value in gen_branch() is for set_target() to fail, causing an early return. Unfortunately, it's hard to tell the exact sequence of events that led to this situation, but regardless, the dumps show us that we should check for errors in gen_branch(). Because gen_branch() is used deep in the stack during compilation (e.g. guard_known_class() -> jit_chain_guard() -> gen_branch()), it'd be bad for compile speed to propagate the error everywhere, not to mention the massive patch required. Opt for a flag checked near the end of compilation. Notes: Merged: https://github.com/ruby/ruby/pull/11938 Merged-By: XrXr
2024-10-23YJIT: Count compiled_branch_count when branch is finalized [ci skip]Alan Wu
2024-10-22Rewrite Numeric#dup and Numeric#+@ in Ruby (#11933)Takashi Kokubun
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2024-10-22YJIT: Implement specialization for no-op `{Kernel,Numeric}#dup`Alan Wu
Type information in the context for no additional work! This is the `if (special_object_p(obj)) return obj;` path in rb_obj_dup() and for Numeric#dup, it's always the identity function. Notes: Merged: https://github.com/ruby/ruby/pull/11926
2024-10-21YJIT: Rename method substitution functions and improve docs (+1) (#11919)Alan Wu
* YJIT: Fill in commented-out assertion * YJIT: Rename yjit_reg_method() and add links in docs Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-10-18YJIT: Allow shareable consts in multi-ractor mode (#11917)John Hawthorn
* Update yjit-bindgen deps * YJIT: Allow shareable consts in multi-ractor mode * Update yjit/src/codegen.rs Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> --------- Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-10-17YJIT: In stats, group by resolved C method nameAlan Wu
Previously, in the "Top-N most frequent C calls" section of --yjit-stats output, we printed the class name of the receiver, not the method owner. This meant that calls on subclass instances that land on the same method showed up as different entires. Similarly, method called using an alias showed up as different entries from other aliases. Group by the resolved method instead. Test program: 1.itself; [].itself; true.inspect; true.to_s Before: Top-4 most frequent C calls (80.0% of C calls): 1 (20.0%): Integer#itself 1 (20.0%): TrueClass#to_s 1 (20.0%): TrueClass#inspect 1 (20.0%): Array#itself After: Top-2 most frequent C calls (80.0% of C calls): 2 (40.0%): Kernel#itself 2 (40.0%): TrueClass#to_s Notes: Merged: https://github.com/ruby/ruby/pull/11913
2024-10-17YJIT: Add compilation log (#11818)Kevin Menard
* YJIT: Add `--yjit-compilation-log` flag to print out the compilation log at exit. * YJIT: Add an option to enable the compilation log at runtime. * YJIT: Fix a typo in the `IseqPayload` docs. * YJIT: Add stubs for getting the YJIT compilation log in memory. * YJIT: Add a compilation log based on a circular buffer to cap the log size. * YJIT: Allow specifying either a file or directory name for the YJIT compilation log. The compilation log will be populated as compilation events occur. If a directory is supplied, then a filename based on the PID will be used as the write target. If a file name is supplied instead, the log will be written to that file. * YJIT: Add JIT compilation of C function substitutions to the compilation log. * YJIT: Add compilation events to the circular buffer even if output is sent to a file. Previously, the two modes were treated as being exclusive of one another. However, it could be beneficial to log all events to a file while also allowing for direct access of the last N events via `RubyVM::YJIT.compilation_log`. * YJIT: Make timestamps the first element in the YJIT compilation log tuple. * YJIT: Stream log to stderr if `--yjit-compilation-log` is supplied without an argument. * YJIT: Eagerly compute compilation log messages to avoid hanging on to references that may GC. * YJIT: Log all compiled blocks, not just the method entry points. * YJIT: Remove all compilation events other than block compilation to slim down the log. * YJIT: Replace circular buffer iterator with a consuming loop. * YJIT: Support `--yjit-compilation-log=quiet` as a way to activate the in-memory log without printing it. Co-authored-by: Randy Stauner <randy.stauner@shopify.com> * YJIT: Promote the compilation log to being the one YJIT log. Co-authored-by: Randy Stauner <randy.stauner@shopify.com> * Update doc/yjit/yjit.md * Update doc/yjit/yjit.md --------- Co-authored-by: Randy Stauner <randy.stauner@shopify.com> Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-10-11Fix spellingJohn Bampton
Notes: Merged: https://github.com/ruby/ruby/pull/11882 Merged-By: XrXr
2024-10-08YJIT: Fastpath for Module#name (#11819)Alan Wu
Module#name shows up as a top C method callee in lobsters so probably common enough. It's also easy to substitute thanks to rb_mod_name() already having no GC yield points. klass = BasicObject 50_000_000.times { klass.name } Benchmark 1: /.rubies/post/bin/ruby --yjit mod_name.rb Time (mean ± σ): 1.433 s ± 0.010 s [User: 1.410 s, System: 0.010 s] Range (min … max): 1.421 s … 1.449 s 10 runs Benchmark 2: /.rubies/mstr/bin/ruby --yjit mod_name.rb Time (mean ± σ): 1.491 s ± 0.012 s [User: 1.468 s, System: 0.010 s] Range (min … max): 1.470 s … 1.511 s 10 runs Summary /.rubies/post/bin/ruby --yjit mod_name.rb ran 1.04 ± 0.01 times faster than /.rubies/mstr/bin/ruby --yjit mod_name.rb
2024-10-07YJIT: Add --yjit-mem-size option (#11810)Takashi Kokubun
* YJIT: Add --yjit-mem-size option * Improve --help * s/the region/this virtual memory region/ Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> --------- Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-10-03Rename size_pool -> heapMatt Valentine-House
Now that we've inlined the eden_heap into the size_pool, we should rename the size_pool to heap. So that Ruby contains multiple heaps, with different sized objects. The term heap as a collection of memory pages is more in memory management nomenclature, whereas size_pool was a name chosen out of necessity during the development of the Variable Width Allocation features of Ruby. The concept of size pools was introduced in order to facilitate different sized objects (other than the default 40 bytes). They wrapped the eden heap and the tomb heap, and some related state, and provided a reasonably simple way of duplicating all related concerns, to provide multiple pools that all shared the same structure but held different objects. Since then various changes have happend in Ruby's memory layout: * The concept of tomb heaps has been replaced by a global free pages list, with each page having it's slot size reconfigured at the point when it is resurrected * the eden heap has been inlined into the size pool itself, so that now the size pool directly controls the free_pages list, the sweeping page, the compaction cursor and the other state that was previously being managed by the eden heap. Now that there is no need for a heap wrapper, we should refer to the collection of pages containing Ruby objects as a heap again rather than a size pool Notes: Merged: https://github.com/ruby/ruby/pull/11771