summaryrefslogtreecommitdiff
path: root/vm_core.h
AgeCommit message (Collapse)Author
2023-09-12Make Kernel#lambda raise when given non-literal blockAlan Wu
Previously, Kernel#lambda returned a non-lambda proc when given a non-literal block and issued a warning under the `:deprecated` category. With this change, Kernel#lambda will always return a lambda proc, if it returns without raising. Due to interactions with block passing optimizations, we previously had two separate code paths for detecting whether Kernel#lambda got a literal block. This change allows us to remove one path, the hack done with rb_control_frame_t::block_code introduced in 85a337f for supporting situations where Kernel#lambda returned a non-lambda proc. [Feature #19777] Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Notes: Merged: https://github.com/ruby/ruby/pull/8405
2023-08-17YJIT: implement side chain fallback for setlocal to avoid exiting (#8227)Maxime Chevalier-Boisvert
* YJIT: implement side chain fallback for setlocal to avoid exiting * Update yjit/src/codegen.rs Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> --------- Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-11Reorder bp_check and jit_return in cfpTakashi Kokubun
It's the actual cfp[6] in the default build, so it's confusing to say otherwise in the comment.
2023-08-08YJIT: Compile exception handlers (#8171)Takashi Kokubun
Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com> Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-07-31`calling->cd` instead of `calling->ci`Koichi Sasada
`struct rb_calling_info::cd` is introduced and `rb_calling_info::ci` is replaced with it to manipulate the inline cache of iseq while method invocation process. So that `ci` can be acessed with `calling->cd->ci`. It adds one indirection but it can be justified by the following points: 1) `vm_search_method_fastpath()` doesn't need `ci` and also `vm_call_iseq_setup_normal()` doesn't need `ci`. It means reducing `cd->ci` access in `vm_sendish()` can make it faster. 2) most of method types need to access `ci` once in theory so that 1 additional indirection doesn't matter. Notes: Merged: https://github.com/ruby/ruby/pull/8129
2023-07-27Clean up OPT_STACK_CACHING (#8132)Takashi Kokubun
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-07-18Fix off-by-one in comment [ci skip]Alan Wu
2023-07-17Remove __bp__ and speed-up bmethod calls (#8060)Alan Wu
Remove rb_control_frame_t::__bp__ and optimize bmethod calls This commit removes the __bp__ field from rb_control_frame_t. It was introduced to help MJIT, but since MJIT was replaced by RJIT, we can use vm_base_ptr() to compute it from the SP of the previous control frame instead. Removing the field avoids needing to set it up when pushing new frames. Simply removing __bp__ would cause crashes since RJIT and YJIT used a slightly different stack layout for bmethod calls than the interpreter. At the moment of the call, the two layouts looked as follows: ┌────────────┐ ┌────────────┐ │ frame_base │ │ frame_base │ ├────────────┤ ├────────────┤ │ ... │ │ ... │ ├────────────┤ ├────────────┤ │ args │ │ args │ ├────────────┤ └────────────┘<─prev_frame_sp │ receiver │ prev_frame_sp─>└────────────┘ RJIT & YJIT interpreter Essentially, vm_base_ptr() needs to compute the address to frame_base given prev_frame_sp in the diagrams. The presence of the receiver created an off-by-one situation. Make the interpreter use the layout the JITs use for iseq-to-iseq bmethod calls. Doing so removes unnecessary argument shifting and vm_exec_core() re-entry from the interpreter, yielding a speed improvement visible through `benchmark/vm_defined_method.yml`: patched: 7578743.1 i/s master: 4796596.3 i/s - 1.58x slower C-to-iseq bmethod calls now store one more VALUE than before, but that should have negligible impact on overall performance. Note that re-entering vm_exec_core() used to be necessary for firing TracePoint events, but that's no longer the case since 9121e57a5f50bc91bae48b3b91edb283bf96cb6b. Closes ruby/ruby#6428
2023-07-01Fallback `rb_iseq_complete`Nobuyoshi Nakada
For compilers that do not eliminate references to functions that are never called, such as SunC.
2023-06-30Compile code for lazy ISeq loding alwaysNobuyoshi Nakada
2023-05-15Remove explicit SIGCHLD handling. (#7816)Samuel Williams
* Remove unused SIGCHLD handling. * Remove unused `init_sigchld`. * Remove unnecessary `#define RUBY_SIGCHLD (0)`. * Remove unused `SIGCHLD_LOSSY`. Notes: Merged-By: ioquatix <samuel@codeotaku.com>
2023-04-26[Bug #19592] Fix ext/Setup supportAlan Wu
After [1], using ext/Setup to link some, but not all extensions failed during linking. I did not know about this option, and had assumed that only `--with-static-linked-ext` builds can include statically linked extensions. Include the support code for statically linked extensions in all configurations like before [1]. Initialize the table lazily to minimize footprint on builds that have no statically linked extensions. [1]: 790cf4b6d0475614afb127b416e87cfa39044d67 "Fix autoload status of statically linked extensions" Notes: Merged: https://github.com/ruby/ruby/pull/7729
2023-04-25Generalize cfunc large array splat fix to fix many additional cases raising ↵Jeremy Evans
SystemStackError Originally, when 2e7bceb34ea858649e1f975a934ce1894d1f06a6 fixed cfuncs to no longer use the VM stack for large array splats, it was thought to have fully fixed Bug #4040, since the issue was fixed for methods defined in Ruby (iseqs) back in Ruby 2.2. After additional research, I determined that same issue affects almost all types of method calls, not just iseq and cfunc calls. There were two main types of remaining issues, important cases (where large array splat should work) and pedantic cases (where large array splat raised SystemStackError instead of ArgumentError). Important cases: ```ruby define_method(:a){|*a|} a(*1380888.times) def b(*a); end send(:b, *1380888.times) :b.to_proc.call(self, *1380888.times) def d; yield(*1380888.times) end d(&method(:b)) def self.method_missing(*a); end not_a_method(*1380888.times) ``` Pedantic cases: ```ruby def a; end a(*1380888.times) def b(_); end b(*1380888.times) def c(_=nil); end c(*1380888.times) c = Class.new do attr_accessor :a alias b a= end.new c.a(*1380888.times) c.b(*1380888.times) c = Struct.new(:a) do alias b a= end.new c.a(*1380888.times) c.b(*1380888.times) ``` This patch fixes all usage of CALLER_SETUP_ARG with splatting a large number of arguments, and required similar fixes to use a temporary hidden array in three other cases where the VM would use the VM stack for handling a large number of arguments. However, it is possible there may be additional cases where splatting a large number of arguments still causes a SystemStackError. This has a measurable performance impact, as it requires additional checks for a large number of arguments in many additional cases. This change is fairly invasive, as there were many different VM functions that needed to be modified to support this. To avoid too much API change, I modified struct rb_calling_info to add a heap_argv member for storing the array, so I would not have to thread it through many functions. This struct is always stack allocated, which helps ensure sure GC doesn't collect it early. Because of how invasive the changes are, and how rarely large arrays are actually splatted in Ruby code, the existing test/spec suites are not great at testing for correct behavior. To try to find and fix all issues, I tested this in CI with VM_ARGC_STACK_MAX to -1, ensuring that a temporary array is used for all array splat method calls. This was very helpful in finding breaking cases, especially ones involving flagged keyword hashes. Fixes [Bug #4040] Co-authored-by: Jimmy Miller <jimmy.miller@shopify.com> Notes: Merged: https://github.com/ruby/ruby/pull/7522
2023-04-13Speed up rebuilding the loaded feature indexJeremy Evans
Rebuilding the loaded feature index slowed down with the bug fix for #17885 in 79a4484a072e9769b603e7b4fbdb15b1d7eccb15. The slowdown was extreme if realpath emulation was used, but even when not emulated, it could be about 10x slower. This adds loaded_features_realpath_map to rb_vm_struct. This is a hidden hash mapping loaded feature paths to realpaths. When rebuilding the loaded feature index, look at this hash to get cached realpath values, and skip calling rb_check_realpath if a cached value is found. Fixes [Bug #19246] Notes: Merged: https://github.com/ruby/ruby/pull/7699
2023-04-11Move `catch_except_p` to `compile_data`eileencodes
The `catch_except_p` flag is used for communicating between parent and child iseq's that a throw instruction was emitted. So for example if a child iseq has a throw in it and the parent wants to catch the throw, we use this flag to communicate to the parent iseq that a throw instruction was emitted. This flag is only useful at compile time, it only impacts the compilation process so it seems to be fine to move it from the iseq body to the compile_data struct. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/7652
2023-04-06Remove dependancy of vm_core.h on shape.hMatt Valentine-House
so that now shape can happily include gc.h Notes: Merged: https://github.com/ruby/ruby/pull/7393
2023-04-06Pull the shape tree out of the vm objectMatt Valentine-House
Notes: Merged: https://github.com/ruby/ruby/pull/7393
2023-04-04`rb_th_serial(th)` allows `th == NULL`Koichi Sasada
2023-03-31rename `rb_thread_t::locking_native_thread`Koichi Sasada
to `rb_thread_t::has_dedicated_nt` Notes: Merged: https://github.com/ruby/ruby/pull/7638
2023-03-30`rb_current_ractor_raw(b)`Koichi Sasada
`rb_current_ractor()` expects it has valid `ec` and `r`. `rb_current_ractor_raw()` with a parameter `false` allows to return NULL if `ec` is not available. Notes: Merged: https://github.com/ruby/ruby/pull/7617
2023-03-23`vm_call_single_noarg_inline_builtin`Koichi Sasada
If the iseq only contains `opt_invokebuiltin_delegate_leave` insn and the builtin-function (bf) is inline-able, the caller doesn't need to build a method frame. `vm_call_single_noarg_inline_builtin` is fast path for such cases. Notes: Merged: https://github.com/ruby/ruby/pull/7486
2023-03-16Refactor jit_func_t and jit_execTakashi Kokubun
I closed https://github.com/ruby/ruby/pull/7543, but part of the diff seems useful regardless, so I extracted it.
2023-03-15Move RB_VM_SAVE_MACHINE_CONTEXT to internal/thread.hMatt Valentine-House
Notes: Merged: https://github.com/ruby/ruby/pull/7465
2023-03-15Rename RB_GC_SAVE_MACHINE_CONTEXT -> RB_VM_SAVE_MACHINE_CONTEXTMatt Valentine-House
Notes: Merged: https://github.com/ruby/ruby/pull/7465
2023-03-15Move RB_GC_SAVE_MACHINE_CONTEXT to vm_core.hMatt Valentine-House
Notes: Merged: https://github.com/ruby/ruby/pull/7465
2023-03-15Remove SIGCHLD `waidpid`. (#7527)Samuel Williams
* Remove `waitpid_lock` and related code. * Remove un-necessary test. * Remove `rb_thread_sleep_interruptible` dead code. Notes: Merged-By: ioquatix <samuel@codeotaku.com>
2023-03-14YJIT: Introduce no_gc attribute (#7511)Takashi Kokubun
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-03-14Revert SIGCHLD changes to diagnose CI failures. (#7517)Samuel Williams
* Revert "Remove special handling of `SIGCHLD`. (#7482)" This reverts commit 44a0711eab7fbc71ac2c8ff489d8c53e97a8fe75. * Revert "Remove prototypes for functions that are no longer used. (#7497)" This reverts commit 4dce12bead3bfd91fd80b5e7195f7f540ffffacb. * Revert "Remove SIGCHLD `waidpid`. (#7476)" This reverts commit 1658e7d96696a656d9bd0a0c84c82cde86914ba2. * Fix change to rjit variable name. Notes: Merged-By: ioquatix <samuel@codeotaku.com>
2023-03-11Rename builtin attr :inline to :leafTakashi Kokubun
2023-03-11Support multiple attributes with Primitive.attr!Takashi Kokubun
2023-03-09Remove SIGCHLD `waidpid`. (#7476)Samuel Williams
* Remove `waitpid_lock` and related code. * Remove un-necessary test. * Remove `rb_thread_sleep_interruptible` dead code. Notes: Merged-By: ioquatix <samuel@codeotaku.com>
2023-03-07Allow enabling YJIT and RJIT independently (#7474)Takashi Kokubun
We used to require MJIT is supported when YJIT is supported. However, now that RJIT dropped some platforms that YJIT supports, it no longer makes sense. We should be able to enable only YJIT, and vice versa. Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-03-06s/mjit/rjit/Takashi Kokubun
Notes: Merged: https://github.com/ruby/ruby/pull/7462
2023-03-06s/MJIT/RJIT/Takashi Kokubun
Notes: Merged: https://github.com/ruby/ruby/pull/7462
2023-03-06Remove obsoleted MJIT_STATIC macroTakashi Kokubun
Notes: Merged: https://github.com/ruby/ruby/pull/7461
2023-03-06Stop exporting symbols for MJITTakashi Kokubun
Notes: Merged: https://github.com/ruby/ruby/pull/7459
2023-03-05Store MJIT blocks on each ISEQTakashi Kokubun
Notes: Merged: https://github.com/ruby/ruby/pull/7448
2023-03-05Refactor BranchStubTakashi Kokubun
2023-02-10use correct svar even if env is escapedKoichi Sasada
This patch is follo-up of 0a82bfe. Without this patch, if env is escaped (Proc'ed), strange svar can be touched. This patch tracks escaped env and use it. Notes: Merged: https://github.com/ruby/ruby/pull/7282
2023-01-20Make all of the references of iseq movablePeter Zhu
Notes: Merged: https://github.com/ruby/ruby/pull/7156
2023-01-17Avoid checking interrupt when loading iseqStan Lo
The interrupt check will unintentionally release the VM lock when loading an iseq. And this will cause issues with the `debug` gem's [`ObjectSpace.each_iseq` method](https://github.com/ruby/debug/blob/0fcfc28acae33ec1c08068fb7c33703cfa681fa7/ext/debug/iseq_collector.c#L61-L67), which wraps iseqs with a wrapper and exposes their internal states when they're actually not ready to be used. And when that happens, errors like this would occur and kill the `debug` gem's thread: ``` DEBUGGER: ReaderThreadError: uninitialized InstructionSequence ┃ DEBUGGER: Disconnected. ┃ ["/opt/rubies/ruby-3.2.0/lib/ruby/gems/3.2.0/gems/debug-1.7.1/lib/debug/breakpoint.rb:247:in `absolute_path'", ┃ "/opt/rubies/ruby-3.2.0/lib/ruby/gems/3.2.0/gems/debug-1.7.1/lib/debug/breakpoint.rb:247:in `block in iterate_iseq'", ┃ "/opt/rubies/ruby-3.2.0/lib/ruby/gems/3.2.0/gems/debug-1.7.1/lib/debug/breakpoint.rb:246:in `each_iseq'", ... ``` A way to reproduce the issue is to satisfy these conditions at the same time: 1. `debug` gem calling `ObjectSpace.each_iseq` (e.g. [activating a `LineBreakpoint`](https://github.com/ruby/debug/blob/0fcfc28acae33ec1c08068fb7c33703cfa681fa7/lib/debug/breakpoint.rb#L246)). 2. A large amount of iseq being loaded from another thread (possibly through the `bootsnap` gem). 3. 1 and 2 iterating through the same iseq(s) at the same time. Because this issue requires external dependencies and a rather complicated timing setup to reproduce, I wasn't able to write a test case for it. But here's some pseudo code to help reproduce it: ```rb require "debug/session" Thread.new do 100.times do ObjectSpace.each_iseq do |iseq| iseq.absolute_path end end end sleep 0.1 load_a_bunch_of_iseq possibly_through_bootsnap ``` [Bug #19348] Co-authored-by: Peter Zhu <peter@peterzhu.ca>
2023-01-13Do not use VM stack for splat arg on cfuncKoichi Sasada
On the cfunc methods, if a splat argument is given, all array elements are expanded on the VM stack and it can cause SystemStackError. The idea to avoid it is making a hidden array to contain all parameters and use this array as an argv. This patch is reviesed version of https://github.com/ruby/ruby/pull/6816 The main change is all changes are closed around calling cfunc logic. Fixes [Bug #4040] Co-authored-by: Jeremy Evans <code@jeremyevans.net> Notes: Merged: https://github.com/ruby/ruby/pull/7109
2022-12-08MJIT: Improve comments for JIT fields [ci skip]Takashi Kokubun
2022-12-08MJIT: Clarify jit_unit is only for MJITTakashi Kokubun
2022-12-06Set max_iv_count (used for object shapes) based on inline cachesJemma Issroff
With this change, we're storing the iv name on an inline cache on setinstancevariable instructions. This allows us to check the inline cache to count instance variables set in initialize and give us an estimate of iv capacity for an object. For the purpose of estimating the number of instance variables required for an object, we're assuming that all initialize methods will call `super`. This change allows us to estimate the number of instance variables required without disassembling instruction sequences. Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/6870
2022-12-06Move BOP macros to separate fileDaniel Colson
This commit moves ruby_basic_operators and the unredefined macros out of vm_core.h and into basic_operators.h so that we can use them more broadly in places where we currently use a method look up via `rb_method_basic_definition_p` (e.g. object.c, numeric.c, complex.c, enum.c, but also in internal/compar.h after introducing BOP_CMP and elsewhere if we introduce more BOPs) The most controversial part of this change is probably moving redefined_flag out of rb_vm_t. [vm_opt_method_def_table and vm_opt_mid_table](https://github.com/ruby/ruby/blob/9da2a5204f32a4f2ce135fddde2abb6e07d647e9/vm.c) are not part of rb_vm_t either, and I think this fits well with those. But more significantly it seems to result in one fewer instruction. For example: Before: ``` (lldb) disassemble -n vm_opt_str_freeze miniruby`vm_exec_core: miniruby[0x10028233e] <+14558>: movq 0x11a86b(%rip), %rax ; ruby_current_vm_ptr miniruby[0x100282345] <+14565>: testb $0x4, 0x242c(%rax) ``` After: ``` (lldb) disassemble -n vm_opt_str_freeze ruby`vm_exec_core: ruby[0x100280ebe] <+14510>: testb $0x4, 0x120147(%rip) ; ruby_vm_redefined_flag + 43 ``` Co-authored-by: John Hawthorn <jhawthorn@github.com>
2022-12-01Improve packing of iseq_constant_body structJohn Hawthorn
By moving the two bools into a packing gap above the mark_bits pointer/union we can save 8 bytes in the struct and avoid an extra cache line (328 bytes vs 320 bytes). Co-authored-by: Adam Hess <HParker@github.com> Notes: Merged: https://github.com/ruby/ruby/pull/6847
2022-12-01Introduce `Fiber#storage` for inheritable fiber-scoped variables. (#6612)Samuel Williams
Notes: Merged-By: ioquatix <samuel@codeotaku.com>
2022-11-25Fix autoload status of statically linked extensionsAlan Wu
Previously, for statically-linked extensions, we used `vm->loading_table` to delay calling the init function until the extensions are required. This caused the extensions to look like they are in the middle of being loaded even before they're required. (`rb_feature_p()` returned true with a loading path output.) Combined with autoload, queries like `defined?(CONST)` and `Module#autoload?` were confused by this and returned nil incorrectly. RubyGems uses `defined?` to detect if OpenSSL is available and failed when OpenSSL was available in builds using `--with-static-linked-ext`. Use a dedicated table for the init functions instead of adding them to the loading table. This lets us remove some logic from non-EXTSTATIC builds. [Bug #19115] Notes: Merged: https://github.com/ruby/ruby/pull/6756
2022-11-22Increment max_iv_count on class based on number of set_iv in initialize (#6788)Jemma Issroff
We can loosely predict the number of ivar sets on a class based on the number of iv set instructions in the initialize method. This should give us a more accurate estimate to use for initial size pool allocation, which should in turn give us more cache hits. Notes: Merged-By: maximecb <maximecb@ruby-lang.org>