summaryrefslogtreecommitdiff
path: root/vm_method.c
Commit message (Collapse)AuthorAgeFilesLines
* RJIT: Stop allowing leaked globals rjit_*Takashi Kokubun2023-03-081-1/+1
|
* s/mjit/rjit/Takashi Kokubun2023-03-061-6/+6
|
* Stop exporting symbols for MJITTakashi Kokubun2023-03-061-12/+11
|
* Invalidate blocks on global constant changesTakashi Kokubun2023-03-051-0/+1
|
* Implement method callTakashi Kokubun2023-03-051-0/+5
|
* Fix broken rebaseTakashi Kokubun2023-03-051-4/+0
|
* Move `attached_object` into `rb_classext_struct`Jean Boussier2023-02-161-1/+4
| | | | | | Given that signleton classes don't have an allocator, we can re-use these bytes to store the attached object in `rb_classext_struct` without making it larger.
* Encapsulate RCLASS_ATTACHED_OBJECTJean Boussier2023-02-151-2/+1
| | | | | | | | | Right now the attached object is stored as an instance variable and all the call sites that either get or set it have to know how it's stored. It's preferable to hide this implementation detail behind accessors so that it is easier to change how it's stored.
* fix `unused variables` warningKoichi Sasada2023-01-131-3/+4
| | | | Now `ccs` is not needed there.
* Fix write barrier order for `klass` to `cme` edgeAlan Wu2023-01-121-2/+1
| | | | | | | | | | | | | | | | | | | | Previously, the following crashes with `CFLAGS=-DRGENGC_CHECK_MODE=2 -DRUBY_DEBUG=1 -fno-inline`: $ ./miniruby -e 'GC.stress = true; Marshal.dump({})' It crashes with a write barrier (WB) miss assertion on an edge from the `Hash` class object to a newly allocated negative method entry. This is due to usages of vm_ccs_create() running the WB too early, before the method entry is inserted into the cc table, so before the reference edge is established. The insertion can trigger GC and promote the class object, so running the WB after the insertion is necessary. Move the insertion into vm_ccs_create() and run the WB after the insertion. Discovered on CI: http://ci.rvm.jp/results/trunk-asserts@ruby-sp2-docker/4391770
* MJIT: Cancel all on disastrous situations (#7019)Takashi Kokubun2022-12-241-0/+5
| | | | | | | | | | I noticed this while running test_yjit with --mjit-call-threshold=1, which redefines `Integer#<`. When Ruby is monkey-patched, MJIT itself could be broken. Similarly, Ruby scripts could break MJIT in many different ways. I prepared the same set of hooks as YJIT so that we could possibly override it and disable it on those moments. Every constant under RubyVM::MJIT is private and thus it's an unsupported behavior though.
* Use consistent style [ci skip]Nobuyoshi Nakada2022-12-021-2/+4
|
* Module#remove_method: Check frozen on the right objectJean byroot Boussier2022-12-011-1/+1
| | | | | | | | | | | Previously, the frozen check happened on `RCLASS_ORIGIN(self)`, which can return an iclass. The frozen check is supposed to respond to objects that users can call methods on while iclasses are hidden from users. Other mutation methods like Module#{define_method,alias_method,public} don't do this. Check frozen status on the module itself. Fixes [Bug #19164] and [Bug #19166]. Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
* Using UNDEF_P macroS-H-GAMELINKS2022-11-161-2/+2
|
* YJIT: Invalidate redefined methods only through cme (#6734)Takashi Kokubun2022-11-151-2/+5
| | | | | Co-authored-by: Alan Wu <alansi.xingwu@shopify.com> Co-authored-by: Alan Wu <alansi.xingwu@shopify.com>
* Rework vm_core to use `int first_lineno` struct member.Samuel Williams2022-09-261-1/+1
|
* type pun rb_f_notimplement卜部昌平2022-09-211-2/+2
| | | | | | Other functions are already type-punned elsewhere. rb_f_notimplement is the only exceptional function that appear literally. We have to take care of it by hand.
* YJIT: Implement specialized respond_to? (#6363)John Hawthorn2022-09-141-1/+15
| | | | | | | | | | | * Add rb_callable_method_entry_or_negative * YJIT: Implement specialized respond_to? This implements a specialized respond_to? in YJIT. * Update yjit/src/codegen.rs Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
* Expand tabs [ci skip]Takashi Kokubun2022-07-211-419/+419
| | | | [Misc #18891]
* Fix nested bmethod TracePoint and memory leakAlan Wu2022-06-101-1/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | df317151a5b4e0c5a30fcc321a9dc6abad63f7ed removed the code to free rb_hook_list_t, so repeated targeting of the same bmethod started to leak the hook list. You can observe how the maximum memory use scales with input size in the following script with `/usr/bin/time -v`. ```ruby o = Object.new o.define_singleton_method(:foo) {} trace = TracePoint.new(:return) {} bmethod = o.method(:foo) ARGV.first.to_i.times { trace.enable(target:bmethod){} } 4.times {GC.start} ``` After this change the maximum doesn't grow as quickly. To plug the leak, check whether the hook list is already allocated when enabling the targeting TracePoint for the bmethod. This fix also allows multiple TracePoints to target the same bmethod, similar to other valid TracePoint targets. Finally, free the rb_hook_list_t struct when freeing the method definition it lives on. Freeing in the GC is a good way to avoid lifetime problems similar to the one fixed in df31715. [Bug #18031]
* Remove unnecessary module flag, add module assertions to other module flagsJemma Issroff2022-05-231-1/+1
|
* Rust YJITAlan Wu2022-04-271-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In December 2021, we opened an [issue] to solicit feedback regarding the porting of the YJIT codebase from C99 to Rust. There were some reservations, but this project was given the go ahead by Ruby core developers and Matz. Since then, we have successfully completed the port of YJIT to Rust. The new Rust version of YJIT has reached parity with the C version, in that it passes all the CRuby tests, is able to run all of the YJIT benchmarks, and performs similarly to the C version (because it works the same way and largely generates the same machine code). We've even incorporated some design improvements, such as a more fine-grained constant invalidation mechanism which we expect will make a big difference in Ruby on Rails applications. Because we want to be careful, YJIT is guarded behind a configure option: ```shell ./configure --enable-yjit # Build YJIT in release mode ./configure --enable-yjit=dev # Build YJIT in dev/debug mode ``` By default, YJIT does not get compiled and cargo/rustc is not required. If YJIT is built in dev mode, then `cargo` is used to fetch development dependencies, but when building in release, `cargo` is not required, only `rustc`. At the moment YJIT requires Rust 1.60.0 or newer. The YJIT command-line options remain mostly unchanged, and more details about the build process are documented in `doc/yjit/yjit.md`. The CI tests have been updated and do not take any more resources than before. The development history of the Rust port is available at the following commit for interested parties: https://github.com/Shopify/ruby/commit/1fd9573d8b4b65219f1c2407f30a0a60e537f8be Our hope is that Rust YJIT will be compiled and included as a part of system packages and compiled binaries of the Ruby 3.2 release. We do not anticipate any major problems as Rust is well supported on every platform which YJIT supports, but to make sure that this process works smoothly, we would like to reach out to those who take care of building systems packages before the 3.2 release is shipped and resolve any issues that may come up. [issue]: https://bugs.ruby-lang.org/issues/18481 Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com> Co-authored-by: Noah Gibbs <the.codefolio.guy@gmail.com> Co-authored-by: Kevin Newton <kddnewton@gmail.com>
* Fix strict aliasing issue with call to rb_id_table_lookup()Alan Wu2022-04-251-2/+3
| | | Previously, GCC 11 with -O2 LTO issues -Wmaybe-uninitialized here.
* Get rid of type-punning pointer castsNobuyoshi Nakada2022-04-071-1/+2
|
* RubyVM.stat constant cache metrics (#5766)Kevin Newton2022-04-051-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | Before the new constant cache behavior, caches were invalidated by a single global variable. You could inspect the value of this variable with RubyVM.stat(:global_constant_state). This was mostly useful to verify the behavior of the VM or to test constant loading like in Rails. With the new constant cache behavior, we introduced RubyVM.stat(:constant_cache) which returned a hash with symbol keys and integer values that represented the number of live constant caches associated with the given symbol. Additionally, we removed the old RubyVM.stat(:global_constant_state). This was proven to be not very useful, so it doesn't help you diagnose constant loading issues. So, instead we added the global constant state back into the RubyVM output. However, that number can be misleading as now when you invalidate something like `Foo::Bar::Baz` you're actually invalidating 3 different lists of inline caches. This commit attempts to get the best of both worlds. We remove RubyVM.stat(:global_constant_state) like we did originally, as it doesn't have the same semantic meaning and it could be confusing going forward. Instead we add RubyVM.stat(:constant_cache_invalidations) and RubyVM.stat(:constant_cache_misses). These two metrics should provide enough information to diagnose any constant loading issues, as well as provide a replacement for the old global constant state.
* Bring back RubyVM.stat(:global_constant_state)Kevin Newton2022-04-041-0/+1
| | | | This was removed as part of [Feature #18589]. But some applications were relying on this behavior. So bringing this back to make it better for backward compatibility going forward.
* Finer-grained constant cache invalidation (take 2)Kevin Newton2022-04-011-2/+18
| | | | | | | | | | | | | | | | | | | | | | | | This commit reintroduces finer-grained constant cache invalidation. After 8008fb7 got merged, it was causing issues on token-threaded builds (such as on Windows). The issue was that when you're iterating through instruction sequences and using the translator functions to get back the instruction structs, you're either using `rb_vm_insn_null_translator` or `rb_vm_insn_addr2insn2` depending if it's a direct-threading build. `rb_vm_insn_addr2insn2` does some normalization to always return to you the non-trace version of whatever instruction you're looking at. `rb_vm_insn_null_translator` does not do that normalization. This means that when you're looping through the instructions if you're trying to do an opcode comparison, it can change depending on the type of threading that you're using. This can be very confusing. So, this commit creates a new translator function `rb_vm_insn_normalizing_translator` to always return the non-trace version so that opcode comparisons don't have to worry about different configurations. [Feature #18589]
* Revert "Finer-grained inline constant cache invalidation"Nobuyoshi Nakada2022-03-251-18/+2
| | | | | | | | | | | | This reverts commits for [Feature #18589]: * 8008fb7352abc6fba433b99bf20763cf0d4adb38 "Update formatting per feedback" * 8f6eaca2e19828e92ecdb28b0fe693d606a03f96 "Delete ID from constant cache table if it becomes empty on ISEQ free" * 629908586b4bead1103267652f8b96b1083573a8 "Finer-grained inline constant cache invalidation" MSWin builds on AppVeyor have been crashing since the merger.
* Finer-grained inline constant cache invalidationKevin Newton2022-03-241-2/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Current behavior - caches depend on a global counter. All constant mutations cause caches to be invalidated. ```ruby class A B = 1 end def foo A::B # inline cache depends on global counter end foo # populate inline cache foo # hit inline cache C = 1 # global counter increments, all caches are invalidated foo # misses inline cache due to `C = 1` ``` Proposed behavior - caches depend on name components. Only constant mutations with corresponding names will invalidate the cache. ```ruby class A B = 1 end def foo A::B # inline cache depends constants named "A" and "B" end foo # populate inline cache foo # hit inline cache C = 1 # caches that depend on the name "C" are invalidated foo # hits inline cache because IC only depends on "A" and "B" ``` Examples of breaking the new cache: ```ruby module C # Breaks `foo` cache because "A" constant is set and the cache in foo depends # on "A" and "B" class A; end end B = 1 ``` We expect the new cache scheme to be invalidated less often because names aren't frequently reused. With the cache being invalidated less, we can rely on its stability more to keep our constant references fast and reduce the need to throw away generated code in YJIT.
* Add ISEQ_BODY macroPeter Zhu2022-03-241-13/+13
| | | | | | Use ISEQ_BODY macro to get the rb_iseq_constant_body of the ISeq. Using this macro will make it easier for us to change the allocation strategy of rb_iseq_constant_body when using Variable Width Allocation.
* Fix visibility of alias of zsuper methodsJeremy Evans2022-03-101-0/+1
| | | | | | This was broken by 71c746379d5872e250d90ae45c585760afaf9516. Fixes [Bug #18600]
* vm_method.c: avoid signature mismatch in rb_f_notimplement callYuta Saito2022-03-021-3/+16
| | | | | | | | | | | | | | `rb_f_notimplement` has a similar signature with arity=-1, but it has an extra marker argument to distinguish it from other methods in compile-time type check in rb_define_method. This trick is introduced to override a given arity to be -1 since https://github.com/ruby/ruby/commit/9ef51b0b89a10c8c401cb9f2337e47a25be72cbe However, the trailing extra argument introduces a signature mismatch between caller and callee expectation. This patch adds rb_f_notimplement_internal, which has canonical arity=-1 signature, and makes rb_define_method family to inserts a method entry with rb_f_notimplement_internal instead of rb_f_notimplement.
* Fix memory leak at the same named alias [Bug #18516]Nobuyoshi Nakada2022-01-271-1/+8
| | | | | | | | When aliasing a method to the same name method, set a separate bit flag on that method definition, instead of the reference count increment. Although this kind of alias has no actual effect at runtime, is used as the hack to suppress the method re-definition warning.
* Negative RBOOL usageNobuyoshi Nakada2022-01-011-1/+1
|
* undef `rb_vm_lookup_overloaded_cme()`Koichi Sasada2021-12-231-1/+2
| | | | | | | | | | | | | | Some callable method entries (cme) can be a key of `overloaded_cme_table` and the keys should be pinned because the table is numtable (VALUE is a key). Before the patch GC checks the cme is in `overloaded_cme_table` by looking up the table, but it needs VM locking. It works well in normal GC marking because it is protected by the VM lock, but it doesn't work on `rb_objspace_reachable_objects_from` because it doesn't use VM lock. Now, the number of target cmes are small enough, I decide to pin down all possible cmes instead of using looking up the table.
* make `overloaded_cme_table` truly weak key mapKoichi Sasada2021-12-211-23/+15
| | | | | | | | | | | | | `overloaded_cme_table` keeps cme -> monly_cme pairs to manage corresponding `monly_cme` for `cme`. The lifetime of the `monly_cme` should be longer than `monly_cme`, but the previous patch losts the reference to the living `monly_cme`. Now `overloaded_cme_table` values are always root (keys are only weak reference), it means `monly_cme` does not freed until corresponding `cme` is invalidated. To make managing easy, move `overloaded_cme_table` to `rb_vm_t`.
* `mandatory_only_cme` should not be in `def`Koichi Sasada2021-12-211-14/+119
| | | | | | | | | | | | | | | | | | | | | | | | `def` (`rb_method_definition_t`) is shared by multiple callable method entries (cme, `rb_callable_method_entry_t`). There are two issues: * old -> young reference: `cme1->def->mandatory_only_cme = monly_cme` if `cme1` is young and `monly_cme` is young, there is no problem. Howevr, another old `cme2` can refer `def`, in this case, old `cme2` points young `monly_cme` and it violates gengc assumption. * cme can have different `defined_class` but `monly_cme` only has one `defined_class`. It does not make sense and `monly_cme` should be created for a cme (not `def`). To solve these issues, this patch allocates `monly_cme` per `cme`. `cme` does not have another room to store a pointer to the `monly_cme`, so this patch introduces `overloaded_cme_table`, which is weak key map `[cme] -> [monly_cme]`. `def::body::iseqptr::monly_cme` is deleted. The first issue is reported by Alan Wu.
* optimize `Struct` getter/setterKoichi Sasada2021-11-191-1/+4
| | | | | Introduce new optimized method type `OPTIMIZED_METHOD_TYPE_STRUCT_AREF/ASET` with index information.
* `rb_method_optimized_t` for further extensionKoichi Sasada2021-11-191-3/+12
| | | | | Now `rb_method_optimized_t optimized` field is added to represent optimized method type.
* Update documentation for Module#{private,public,protected,module_function}Jeremy Evans2021-11-181-14/+27
| | | | Also, update NEWS for this change and the Kernel#load change.
* Make Module#{public,private,protected,module_function} return argumentsJeremy Evans2021-11-181-5/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | Previously, each of these methods returned self, but it is more useful to return arguments, to allow for simpler method decorators, such as: ```ruby cached private def foo; some_long_calculation; end ``` Where cached sets up caching for the method. For each of these methods, the following behavior is used: 1) No arguments returns nil 2) Single argument is returned 3) Multiple arguments are returned as an array The single argument case is really the case we are trying to optimize for, for the same reason that def was changed to return a symbol for the method. Idea and initial patch from Herwin Quarantainenet. Implements [Feature #12495]
* Fix crash when clearing method cache for builtin methodPeter Zhu2021-11-171-1/+1
| | | | | | | | Builtin methods do not always have their mandatory_only_cme created (it is only created when called with only mandatory parameters), so it could be null. If we try to clear the cme, it will crash because it is null. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
* `Primitive.mandatory_only?` for fast pathKoichi Sasada2021-11-151-3/+41
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Compare with the C methods, A built-in methods written in Ruby is slower if only mandatory parameters are given because it needs to check the argumens and fill default values for optional and keyword parameters (C methods can check the number of parameters with `argc`, so there are no overhead). Passing mandatory arguments are common (optional arguments are exceptional, in many cases) so it is important to provide the fast path for such common cases. `Primitive.mandatory_only?` is a special builtin function used with `if` expression like that: ```ruby def self.at(time, subsec = false, unit = :microsecond, in: nil) if Primitive.mandatory_only? Primitive.time_s_at1(time) else Primitive.time_s_at(time, subsec, unit, Primitive.arg!(:in)) end end ``` and it makes two ISeq, ``` def self.at(time, subsec = false, unit = :microsecond, in: nil) Primitive.time_s_at(time, subsec, unit, Primitive.arg!(:in)) end def self.at(time) Primitive.time_s_at1(time) end ``` and (2) is pointed by (1). Note that `Primitive.mandatory_only?` should be used only in a condition of an `if` statement and the `if` statement should be equal to the methdo body (you can not put any expression before and after the `if` statement). A method entry with `mandatory_only?` (`Time.at` on the above case) is marked as `iseq_overload`. When the method will be dispatch only with mandatory arguments (`Time.at(0)` for example), make another method entry with ISeq (2) as mandatory only method entry and it will be cached in an inline method cache. The idea is similar discussed in https://bugs.ruby-lang.org/issues/16254 but it only checks mandatory parameters or more, because many cases only mandatory parameters are given. If we find other cases (optional or keyword parameters are used frequently and it hurts performance), we can extend the feature.
* Partial revert of ceebc7fc98dAaron Patterson2021-10-201-12/+0
| | | | | | | I'm looking through the places where YJIT needs notifications. It looks like these changes to gc.c and vm_callinfo.h have become unnecessary since 84ab77ba592. This commit just makes the diff against upstream smaller, but otherwise shouldn't change any behavior.
* Get rid of dependency on rb_call_cacheAlan Wu2021-10-201-2/+6
|
* Yet Another Ruby JIT!Jose Narvaez2021-10-201-4/+4
| | | | Renaming uJIT to YJIT. AKA s/ujit/yjit/g.
* add a callback for when method cache changesAaron Patterson2021-10-201-0/+1
|
* Refactor uJIT code into more files for readabilityMaxime Chevalier-Boisvert2021-10-201-1/+1
|
* MicroJIT: generate less code for CFUNCsAlan Wu2021-10-201-0/+15
| | | | | | | | Added UJIT_CHECK_MODE. Set to 1 to double check method dispatch in generated code. It's surprising to me that we need to watch both cc and cme. There might be opportunities to simplify there.
* Fix typo in static function nameJeremy Evans2021-10-011-3/+3
|