summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
AgeCommit message (Collapse)Author
2022-11-10Remove numiv from RObjectJemma Issroff
Since object shapes store the capacity of an object, we no longer need the numiv field on RObjects. This gives us one extra slot which we can use to give embedded objects one more instance variable (for a total of 3 ivs). This commit removes the concept of numiv from RObject. Notes: Merged: https://github.com/ruby/ruby/pull/6699
2022-11-10Transition shape when object's capacity changesJemma Issroff
This commit adds a `capacity` field to shapes, and adds shape transitions whenever an object's capacity changes. Objects which are allocated out of a bigger size pool will also make a transition from the root shape to the shape with the correct capacity for their size pool when they are allocated. This commit will allow us to remove numiv from objects completely, and will also mean we can guarantee that if two objects share shapes, their IVs are in the same positions (an embedded and extended object cannot share shapes). This will enable us to implement ivar sets in YJIT using object shapes. Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/6699
2022-10-31Implement object shapes for T_CLASS and T_MODULE (#6637)John Hawthorn
* Avoid RCLASS_IV_TBL in marshal.c * Avoid RCLASS_IV_TBL for class names * Avoid RCLASS_IV_TBL for autoload * Avoid RCLASS_IV_TBL for class variables * Avoid copying RCLASS_IV_TBL onto ICLASSes * Use object shapes for Class and Module IVs Notes: Merged-By: jhawthorn <john@hawthorn.email>
2022-10-20push dummy frame for loading processKoichi Sasada
This patch pushes dummy frames when loading code for the profiling purpose. The following methods push a dummy frame: * `Kernel#require` * `Kernel#load` * `RubyVM::InstructionSequence.compile_file` * `RubyVM::InstructionSequence.load_from_binary` https://bugs.ruby-lang.org/issues/18559 Notes: Merged: https://github.com/ruby/ruby/pull/6572
2022-10-15More precisely iterate over Object instance variablesAaron Patterson
Shapes provides us with an (almost) exact count of instance variables. We only need to check for Qundef when an IV has been "undefined" Prefer to use ROBJECT_IV_COUNT when iterating IVs Notes: Merged: https://github.com/ruby/ruby/pull/6555
2022-10-12Initialize shape attr index also in non-markable CCNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/6532
2022-10-12Adjust indents [ci skip]Nobuyoshi Nakada
2022-10-12Do not read cached_id from callcache on stackYusuke Endoh
The inline cache is initialized by vm_cc_attr_index_set only when vm_cc_markable(cc). However, vm_getivar attempted to read the cache even if the cc is not vm_cc_markable. This caused a condition that depends on uninitialized value. Here is an output of valgrind: ``` ==10483== Conditional jump or move depends on uninitialised value(s) ==10483== at 0x4C1D60: vm_getivar (vm_insnhelper.c:1171) ==10483== by 0x4C1D60: vm_call_ivar (vm_insnhelper.c:3257) ==10483== by 0x4E8E48: vm_call_symbol (vm_insnhelper.c:3481) ==10483== by 0x4EAD8C: vm_sendish (vm_insnhelper.c:5035) ==10483== by 0x4C62B2: vm_exec_core (insns.def:820) ==10483== by 0x4DD519: rb_vm_exec (vm.c:0) ==10483== by 0x4F00B3: invoke_block (vm.c:1417) ==10483== by 0x4F00B3: invoke_iseq_block_from_c (vm.c:1473) ==10483== by 0x4F00B3: invoke_block_from_c_bh (vm.c:1491) ==10483== by 0x4D42B6: rb_yield (vm_eval.c:0) ==10483== by 0x259128: rb_ary_each (array.c:2733) ==10483== by 0x4E8730: vm_call_cfunc_with_frame (vm_insnhelper.c:3227) ==10483== by 0x4EAD8C: vm_sendish (vm_insnhelper.c:5035) ==10483== by 0x4C6254: vm_exec_core (insns.def:801) ==10483== by 0x4DD519: rb_vm_exec (vm.c:0) ==10483== ``` In fact, the CI on FreeBSD 12 started failing since ad63b668e22e21c352b852f3119ae98a7acf99f1. ``` gmake[1]: Entering directory '/usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby' /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:924:in `complete': undefined method `complete' for nil:NilClass (NoMethodError) from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1816:in `block in visit' from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1815:in `reverse_each' from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1815:in `visit' from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1847:in `block in complete' from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1846:in `catch' from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1846:in `complete' from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1640:in `block in parse_in_order' from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1632:in `catch' from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1632:in `parse_in_order' from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1626:in `order!' from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1732:in `permute!' from /usr/home/chkbuild/chkbuild/tmp/build/20221011T163003Z/ruby/lib/optparse.rb:1757:in `parse!' from ./ext/extmk.rb:359:in `parse_args' from ./ext/extmk.rb:396:in `<main>' ``` This change adds a guard to read the cache only when vm_cc_markable(cc). It might be better to initialize the cache as INVALID_SHAPE_ID when the cc is not vm_cc_markable. Notes: Merged: https://github.com/ruby/ruby/pull/6530
2022-10-11Make inline cache reads / writes atomic with object shapesJemma Issroff
Prior to this commit, we were reading and writing ivar index and shape ID in inline caches in two separate instructions when getting and setting ivars. This meant there was a race condition with ractors and these caches where one ractor could change a value in the cache while another was still reading from it. This commit instead reads and writes shape ID and ivar index to inline caches atomically so there is no longer a race condition. Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org> Co-Authored-By: John Hawthorn <john@hawthorn.email>
2022-10-11Revert "Revert "This commit implements the Object Shapes technique in CRuby.""Jemma Issroff
This reverts commit 9a6803c90b817f70389cae10d60b50ad752da48f.
2022-10-01Use the dedicated function to check arityNobuyoshi Nakada
2022-10-01Add macros for assertionsNobuyoshi Nakada
2022-09-30Revert "This commit implements the Object Shapes technique in CRuby."Aaron Patterson
This reverts commit 68bc9e2e97d12f80df0d113e284864e225f771c2.
2022-09-30Only assert ractor_shareable is consistent on ivar_set for T_OBJECTJemma Issroff
Before d594a5a8bd0756f65c078fcf5ce0098250cba141, we were only asserting that the value on an ivar_get was ractor_sharable if the object was a T_OBJECT and also ractor shareable. We should still be doing this check only if the object is a T_OBJECT and ractor shareable Notes: Merged: https://github.com/ruby/ruby/pull/6477
2022-09-28This commit implements the Object Shapes technique in CRuby.Jemma Issroff
Object Shapes is used for accessing instance variables and representing the "frozenness" of objects. Object instances have a "shape" and the shape represents some attributes of the object (currently which instance variables are set and the "frozenness"). Shapes form a tree data structure, and when a new instance variable is set on an object, that object "transitions" to a new shape in the shape tree. Each shape has an ID that is used for caching. The shape structure is independent of class, so objects of different types can have the same shape. For example: ```ruby class Foo def initialize # Starts with shape id 0 @a = 1 # transitions to shape id 1 @b = 1 # transitions to shape id 2 end end class Bar def initialize # Starts with shape id 0 @a = 1 # transitions to shape id 1 @b = 1 # transitions to shape id 2 end end foo = Foo.new # `foo` has shape id 2 bar = Bar.new # `bar` has shape id 2 ``` Both `foo` and `bar` instances have the same shape because they both set instance variables of the same name in the same order. This technique can help to improve inline cache hits as well as generate more efficient machine code in JIT compilers. This commit also adds some methods for debugging shapes on objects. See `RubyVM::Shape` for more details. For more context on Object Shapes, see [Feature: #18776] Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org> Co-Authored-By: Eileen M. Uchitelle <eileencodes@gmail.com> Co-Authored-By: John Hawthorn <john@hawthorn.email>
2022-09-26Revert this until we can figure out WB issues or remove shapes from GCAaron Patterson
Revert "* expand tabs. [ci skip]" This reverts commit 830b5b5c351c5c6efa5ad461ae4ec5085e5f0275. Revert "This commit implements the Object Shapes technique in CRuby." This reverts commit 9ddfd2ca004d1952be79cf1b84c52c79a55978f4.
2022-09-26This commit implements the Object Shapes technique in CRuby.Jemma Issroff
Object Shapes is used for accessing instance variables and representing the "frozenness" of objects. Object instances have a "shape" and the shape represents some attributes of the object (currently which instance variables are set and the "frozenness"). Shapes form a tree data structure, and when a new instance variable is set on an object, that object "transitions" to a new shape in the shape tree. Each shape has an ID that is used for caching. The shape structure is independent of class, so objects of different types can have the same shape. For example: ```ruby class Foo def initialize # Starts with shape id 0 @a = 1 # transitions to shape id 1 @b = 1 # transitions to shape id 2 end end class Bar def initialize # Starts with shape id 0 @a = 1 # transitions to shape id 1 @b = 1 # transitions to shape id 2 end end foo = Foo.new # `foo` has shape id 2 bar = Bar.new # `bar` has shape id 2 ``` Both `foo` and `bar` instances have the same shape because they both set instance variables of the same name in the same order. This technique can help to improve inline cache hits as well as generate more efficient machine code in JIT compilers. This commit also adds some methods for debugging shapes on objects. See `RubyVM::Shape` for more details. For more context on Object Shapes, see [Feature: #18776] Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org> Co-Authored-By: Eileen M. Uchitelle <eileencodes@gmail.com> Co-Authored-By: John Hawthorn <john@hawthorn.email> Notes: Merged: https://github.com/ruby/ruby/pull/6386
2022-09-21vm_method_cfunc_is: get rid of ANYARGS卜部昌平
ANYARGS-ed function prototypes are basically prohibited in C23. Use __attribute__((__transparent_union__)) instead. Notes: Merged: https://github.com/ruby/ruby/pull/6358
2022-09-21cref_replace_with_duplicated_cref_each_frame: returns a pointer卜部昌平
Why use FALSE here? Notes: Merged: https://github.com/ruby/ruby/pull/6358
2022-09-21vm_insnhelper.c: add casts卜部昌平
Why they have not been at the first place? Siblings have proper casts. Notes: Merged: https://github.com/ruby/ruby/pull/6358
2022-09-08vm_objtostring: skip method lookup for T_STRING receiversJean Boussier
We don't need it, and in string interpolation context that's the common case. Notes: Merged: https://github.com/ruby/ruby/pull/6334
2022-09-01New constant caching insn: opt_getconstant_pathJohn Hawthorn
Previously YARV bytecode implemented constant caching by having a pair of instructions, opt_getinlinecache and opt_setinlinecache, wrapping a series of getconstant calls (with putobject providing supporting arguments). This commit replaces that pattern with a new instruction, opt_getconstant_path, handling both getting/setting the inline cache and fetching the constant on a cache miss. This is implemented by storing the full constant path as a null-terminated array of IDs inside of the IC structure. idNULL is used to signal an absolute constant reference. $ ./miniruby --dump=insns -e '::Foo::Bar::Baz' == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,13)> (catch: FALSE) 0000 opt_getconstant_path <ic:0 ::Foo::Bar::Baz> ( 1)[Li] 0002 leave The motivation for this is that we had increasingly found the need to disassemble the instructions between the opt_getinlinecache and opt_setinlinecache in order to determine the constant we are fetching, or otherwise store metadata. This disassembly was done: * In opt_setinlinecache, to register the IC against the constant names it is using for granular invalidation. * In rb_iseq_free, to unregister the IC from the invalidation table. * In YJIT to find the position of a opt_getinlinecache instruction to invalidate it when the cache is populated * In YJIT to register the constant names being used for invalidation. With this change we no longe need disassemly for these (in fact rb_iseq_each is now unused), as the list of constant names being referenced is held in the IC. This should also make it possible to make more optimizations in the future. This may also reduce the size of iseqs, as previously each segment required 32 bytes (on 64-bit platforms) for each constant segment. This implementation only stores one ID per-segment. There should be no significant performance change between this and the previous implementation. Previously opt_getinlinecache was a "leaf" instruction, but it included a jump (almost always to a separate cache line). Now opt_getconstant_path is a non-leaf (it may raise/autoload/call const_missing) but it does not jump. These seem to even out. Notes: Merged: https://github.com/ruby/ruby/pull/6187
2022-08-29YJIT: Implement concatarray in yjit (https://github.com/Shopify/ruby/pull/405)Maple Ong
* Create code generation func * Make rb_vm_concat_array available to use in Rust * Map opcode to code gen func * Implement code gen for concatarray * Add test for concatarray * Use new asm backend * Add comment to C func wrapper
2022-08-25Fix private methods reported as protected when called via Symbol#to_procJean Boussier
Ref: bfa6a8ddc84fffe0aef5a0f91b417167e124dbbf Ref: [Bug #18826] Notes: Merged: https://github.com/ruby/ruby/pull/6284
2022-08-19Rename mjit_exec to jit_exec (#6262)Takashi Kokubun
* Rename mjit_exec to jit_exec * Rename mjit_exec_slowpath to mjit_check_iseq * Remove mjit_exec references from comments Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2022-08-19Repalce to NIL_P macroS-H-GAMELINKS
Notes: Merged: https://github.com/ruby/ruby/pull/6073
2022-08-10Only allow procs created by Symbol#to_proc to call public methodsJeremy Evans
Fixes [Bug #18826] Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/6018 Merged-By: jeremyevans <code@jeremyevans.net>
2022-08-04Fix inconsistency with opt_aref_withJohn Hawthorn
opt_aref_with is an optimized instruction for accessing a Hash using a non-frozen string key (ie. from a file without frozen_string_literal). It attempts to avoid allocating the string, and instead silently using a frozen string (hash string keys are always fstrings). Because this is just an optimization, it should be invisible to the user. However, previously this optimization was could be seen via hashes with default procs. For example, previously: h = Hash.new { |h, k| k.frozen? } str = "foo" h[str] # false h["foo"] # true when optimizations enabled This commit checks that the Hash doesn't have a default proc when using opt_aref_with. Notes: Merged: https://github.com/ruby/ruby/pull/6196
2022-07-27Adjust styles [ci skip]Nobuyoshi Nakada
2022-07-21Expand tabs [ci skip]Takashi Kokubun
[Misc #18891] Notes: Merged: https://github.com/ruby/ruby/pull/6094
2022-07-21Do not have class/module keywords look up ancestors of ObjectJeremy Evans
Fixes case where Object includes a module that defines a constant, then using class/module keyword to define the same constant on Object itself. Implements [Feature #18832] Notes: Merged: https://github.com/ruby/ruby/pull/6048
2022-07-18Extract vm_ic_entry API to mimic vm_cc behaviorJemma Issroff
Notes: Merged: https://github.com/ruby/ruby/pull/5978
2022-07-06vm_opt_ltlt: call rb_str_buf_append directly if RHS is a StringJean Boussier
`rb_str_concat` does a lot of type checking we can easily bypass. ``` | |compare-ruby|built-ruby| |:--------------|-----------:|---------:| |string_concat | 362.007k| 398.965k| | | -| 1.10x| ``` Notes: Merged: https://github.com/ruby/ruby/pull/6095
2022-07-03Fix empty call cache check for debug counterNobuyoshi Nakada
2022-06-30YJIT: Refactor gen_opt_mod (#6078)Dave Schwantes
Refactor gen_opt_mod in YJIT Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2022-06-21Allow method caching of protected FCALLsJohn Hawthorn
Notes: Merged: https://github.com/ruby/ruby/pull/5643
2022-06-21Don't check protected method ancestry on fcallJohn Hawthorn
If we are making an FCALL, we know we are calling a method on self. This is the same check made for private method visibility, so it should also guarantee we can call a protected method. Notes: Merged: https://github.com/ruby/ruby/pull/5643
2022-06-16Allow calling protected methods from refinementsJohn Hawthorn
Previously protected methods on refinements could never be called because they were seen as being "defined" on the hidden refinement ICLASS. This commit updates calling refined protected methods so that they are considered to be defined on the original class (the one being refined). This ended up using the same behaviour that was used to check whether a call to super was allowed, so I extracted that into a method. [Bug #18806] Notes: Merged: https://github.com/ruby/ruby/pull/5966
2022-05-30Fix use-after-free with interacting TracePointsAlan Wu
`vm_trace_hook()` runs global hooks before running local hooks. Previously, we read the local hook list before running the global hooks which led to use-after-free when a global hook frees the local hook list. A global hook can do this by disabling a local TracePoint, for example. Delay local hook list loading until after running the global hooks. Issue discovered by Jeremy Evans in GH-5862. [Bug #18730] Notes: Merged: https://github.com/ruby/ruby/pull/5865
2022-05-23Remove unnecessary module flag, add module assertions to other module flagsJemma Issroff
Notes: Merged: https://github.com/ruby/ruby/pull/5930
2022-04-27Rust YJITAlan Wu
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> Notes: Merged: https://github.com/ruby/ruby/pull/5826
2022-04-08sync `vm->constant_cache`Koichi Sasada
On multi-ractors, `vm->constant_cache` (and so on) can be accessed in parallel so we need to synchronize the accesses to them. http://rubyci.s3.amazonaws.com/centos7/ruby-master/log/20220407T213003Z.log.html.gz#btest Notes: Merged: https://github.com/ruby/ruby/pull/5779
2022-04-07Fix strict aliasing issueAlan Wu
`rb_id_table_lookup()` writes to a `VALUE`, which is definitely a distinct type from `st_table *`. With LTO, the compiler is allowed by N1256 §6.5p7 to remove the output parameter write via type-based alias analysis. See also: a0a8f2abf53 Notes: Merged: https://github.com/ruby/ruby/pull/5773
2022-04-01Finer-grained constant cache invalidation (take 2)Kevin Newton
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] Notes: Merged: https://github.com/ruby/ruby/pull/5716
2022-03-25Revert "Finer-grained inline constant cache invalidation"Nobuyoshi Nakada
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. Notes: Merged: https://github.com/ruby/ruby/pull/5715 Merged-By: nobu <nobu@ruby-lang.org>
2022-03-24Finer-grained inline constant cache invalidationKevin Newton
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. Notes: Merged: https://github.com/ruby/ruby/pull/5433
2022-03-24Add ISEQ_BODY macroPeter Zhu
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. Notes: Merged: https://github.com/ruby/ruby/pull/5698
2022-03-10Small optimization for the opt_and instructionAaron Patterson
This change eagerly performs a bitwise and on the parameters. If both parameters are fixnums, then the result value should also be a fixnum. We can just test the bit on the result and return if it's a fixnum. Otherwise return Qundef. Notes: Merged: https://github.com/ruby/ruby/pull/5629
2022-01-26Streamline cached attr reader / writer indexesJemma Issroff
This commit removes the need to increment and decrement the indexes used by vm_cc_attr_index getters and setters. It also introduces a vm_cc_attr_index_p predicate function, and a vm_cc_attr_index_initalize function. Notes: Merged: https://github.com/ruby/ruby/pull/5485
2022-01-01Negative RBOOL usageNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/5385