aboutsummaryrefslogtreecommitdiffstats
path: root/iseq.c
Commit message (Collapse)AuthorAgeFilesLines
...
* Free the IV table after estimationAaron Patterson2022-11-221-0/+2
| | | | | We need to make sure the name table is freed otherwise we have a memory leak.
* Increment max_iv_count on class based on number of set_iv in initialize (#6788)Jemma Issroff2022-11-221-0/+39
| | | | | | 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.
* Using UNDEF_P macroS-H-GAMELINKS2022-11-161-2/+2
|
* push dummy frame for loading processKoichi Sasada2022-10-201-0/+6
| | | | | | | | | | | | | 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
* Revert "Revert "This commit implements the Object Shapes technique in CRuby.""Jemma Issroff2022-10-111-12/+2
| | | | This reverts commit 9a6803c90b817f70389cae10d60b50ad752da48f.
* Revert "This commit implements the Object Shapes technique in CRuby."Aaron Patterson2022-09-301-2/+12
| | | | This reverts commit 68bc9e2e97d12f80df0d113e284864e225f771c2.
* Add `eval: true/false` flag to `Coverage.setup`.Samuel Williams2022-09-291-3/+5
|
* This commit implements the Object Shapes technique in CRuby.Jemma Issroff2022-09-281-12/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* Revert this until we can figure out WB issues or remove shapes from GCAaron Patterson2022-09-261-9/+7
| | | | | | | | | | Revert "* expand tabs. [ci skip]" This reverts commit 830b5b5c351c5c6efa5ad461ae4ec5085e5f0275. Revert "This commit implements the Object Shapes technique in CRuby." This reverts commit 9ddfd2ca004d1952be79cf1b84c52c79a55978f4.
* This commit implements the Object Shapes technique in CRuby.Jemma Issroff2022-09-261-7/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* Rework vm_core to use `int first_lineno` struct member.Samuel Williams2022-09-261-3/+3
|
* Rework `first_lineno` to be `int`.Samuel Williams2022-09-261-16/+15
|
* Extract common code for coverage setup.Samuel Williams2022-09-251-13/+19
|
* Enable coverage for eval.Samuel Williams2022-09-221-1/+12
|
* Remove rb_iseq_eachJohn Hawthorn2022-09-011-33/+0
|
* New constant caching insn: opt_getconstant_pathJohn Hawthorn2022-09-011-77/+63
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Convert catch_except_t to stdboolTakashi Kokubun2022-08-251-1/+1
| | | | | | | catch_excep_t is a field that exists for MJIT. In the process of rewriting MJIT in Ruby, I added API to convert 1/0 of _Bool to true/false, and it seemed confusing and hard to maintain if you don't use _Bool for *_p fields.
* Simplify around `USE_YJIT` macro (#6240)Nobuyoshi Nakada2022-08-151-3/+3
| | | | | | | | * Simplify around `USE_YJIT` macro - Use `USE_YJIT` macro only instead of `YJIT_BUILD`. - An intermediate macro `YJIT_SUPPORTED_P` is no longer used. * Bail out if YJIT is enabled on unsupported platforms
* Rename rb_ary_tmp_new to rb_ary_hidden_newPeter Zhu2022-07-261-2/+2
| | | | | | rb_ary_tmp_new suggests that the array is temporary in some way, but that's not true, it just creates an array that's hidden and not on the transient heap. This commit renames it to rb_ary_hidden_new.
* Add "rb_" prefixes to toplevel enum definitionsYusuke Endoh2022-07-221-10/+10
| | | | ... as per ko1's request.
* Expand tabs [ci skip]Takashi Kokubun2022-07-211-757/+757
| | | | [Misc #18891]
* Separate TS_IVC and TS_ICVARC in is_entries buffersJemma Issroff2022-07-181-4/+15
| | | | This allows us to treat cvar caches differently than ivar caches.
* Simplify BLSR codeNobuyoshi Nakada2022-07-081-1/+1
| | | | And suppress unary minus operator to unsigned type warnings by VC.
* Remove ISEQ_MARKABLE_ISEQ flagAaron Patterson2022-07-071-41/+41
| | | | | We don't need this flag anymore. We have all the info we need via the bitmap and the is_entries list.
* Use iseq bitmap when updating referencesAaron Patterson2022-06-291-88/+12
| | | | | This allows us to delete the disassembly code path for reference updating.
* Move function to `static inline` so we don't have leaked globalsAaron Patterson2022-06-291-20/+0
| | | | | This function shouldn't leak and is only needed during instruction assembly
* Fix ISeq dump / load in array casesAaron Patterson2022-06-291-2/+24
| | | | | | | | | | | We need to dump relative offsets for inline storage entries so that loading iseqs as an array works as well. This commit also has some minor refactoring to make computing relative ISE information easier. This should fix the iseq dump / load as array tests we're seeing fail in CI. Co-Authored-By: John Hawthorn <john@hawthorn.email>
* iseq.c: Use ntz_intptr for faster bitmap scanJean Boussier2022-06-251-16/+12
|
* Free bitmap buffer if it's not usedAaron Patterson2022-06-231-4/+6
| | | | | If the iseqs don't have any objects in them that need marking, then immediately free the bitmap buffer
* Flatten bitmap when there is only one elementAaron Patterson2022-06-231-18/+29
| | | | | We can avoid allocating a bitmap when the number of elements in the iseq is fewer than the size of an iseq_bits_t
* Speed up ISeq by marking via bitmaps and IC rearrangingAaron Patterson2022-06-231-9/+61
| | | | | | | | | | | | | | | | This commit adds a bitfield to the iseq body that stores offsets inside the iseq buffer that contain values we need to mark. We can use this bitfield to mark objects instead of disassembling the instructions. This commit also groups inline storage entries and adds a counter for each entry. This allows us to iterate and mark each entry without disassembling instructions Since we have a bitfield and grouped inline caches, we can mark all VALUE objects associated with instructions without actually disassembling the instructions at mark time. [Feature #18875] [ruby-core:109042]
* Reuse an interned stringNobuyoshi Nakada2022-06-171-3/+2
| | | | | | Repeating to intern the same string is just redundant, as interned strings for the same content are always the same object until it gets collected.
* Rust YJITAlan Wu2022-04-271-3/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* Adjust indent [ci skip]Nobuyoshi Nakada2022-04-021-29/+29
|
* Finer-grained constant cache invalidation (take 2)Kevin Newton2022-04-011-0/+114
| | | | | | | | | | | | | | | | | | | | | | | | 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-90/+0
| | | | | | | | | | | | 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.
* Delete ID from constant cache table if it becomes empty on ISEQ freeKevin Newton2022-03-241-0/+5
| | | | Co-authored-by: John Hawthorn <john@hawthorn.email>
* Finer-grained inline constant cache invalidationKevin Newton2022-03-241-0/+85
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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-52/+52
| | | | | | 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 indents [ci skip]Nobuyoshi Nakada2022-02-031-1/+1
|
* Treat TS_ICVARC cache as separate from TS_IVC cacheJemma Issroff2022-02-021-0/+3
|
* `rb_iseq_update_references()` cares `script_lines`Koichi Sasada2021-12-191-0/+1
| | | | | and it fixes compaction issue: http://rubyci.s3.amazonaws.com/freebsd12/ruby-master/log/20211218T203001Z.fail.html.gz
* `iseq_type_sym()` -> `iseq_type_id()`Koichi Sasada2021-12-191-40/+40
| | | | | `iseq_type_sym()` returns `ID` (surprisingly!) so rename it to `iseq_type_id()`.
* add `rb_iseq_type()` to return iseq type in SymbolKoichi Sasada2021-12-191-36/+53
| | | | It is shorthand `ISeq#to_a[9]`.
* fix local TP memory leakKoichi Sasada2021-12-151-3/+2
| | | | | | | It free `rb_hook_list_t` itself if needed. To recognize the need, this patch introduced `rb_hook_list_t::is_local` flag. This patch is succession of https://github.com/ruby/ruby/pull/4652
* Introduce an option "--dump=insns_without_opt" for debugging purposesYusuke Endoh2021-12-131-2/+2
|
* Rework tracing for blocks running as methodsAlan Wu2021-12-011-2/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The main impetus for this change is to fix [Bug #13392]. Previously, we fired the "return" TracePoint event after popping the stack frame for the block running as method (BMETHOD). This gave undesirable source location outputs as the return event normally fires right before the frame going away. The iseq for each block can run both as a block and as a method. To accommodate that, this commit makes vm_trace() fire call/return events for instructions that have b_call/b_return events attached when the iseq is running as a BMETHOD. The logic for rewriting to "trace_*" instruction is tweaked so that when the user listens to call/return events, instructions with b_call/b_return become trace variants. To continue to provide the return value for non-local returns done using the "return" or "break" keyword inside BMETHODs, the stack unwinding code is tweaked. b_return events now provide the same return value as return events for these non-local cases. A pre-existing test deemed not providing a return value for these b_return events as a limitation. This commit removes the checks for call/return TracePoint events that happen when calling into BMETHODs when no TracePoints are active. Technically, migrating just the return event is enough to fix the bug, but migrating both call and return removes our reliance on `VM_FRAME_FLAG_FINISH` and re-entering the interpreter when the caller is already in the interpreter.
* add `VM_CALLCACHE_ON_STACK`Koichi Sasada2021-11-171-6/+11
| | | | check if iseq refers to on stack CC (it shouldn't).
* `Primitive.mandatory_only?` for fast pathKoichi Sasada2021-11-151-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* need to mark script_linesKoichi Sasada2021-10-291-0/+1
|