summaryrefslogtreecommitdiff
path: root/variable.c
AgeCommit message (Collapse)Author
2025-12-16Respect encoding of ID in exception messagesDaisuke Aritomo
2025-12-16Let Ractor::IsolationError report correct constant pathDaisuke Aritomo
Before this patch, Ractor::IsolationError reported an incorrect constant path when constant was found through `rb_const_get_0()`. In this code, Ractor::IsolationError reported illegal access against `M::TOPLEVEL`, where it should be `Object::TOPLEVEL`. ```ruby TOPLEVEL = [1] module M def self.f TOPLEVEL end end Ractor.new { M.f }.value ``` This was because `rb_const_get_0()` built the "path" part referring to the module/class passed to it in the first place. When a constant was found through recursive search upwards, the module/class which the constant was found should be reported. This patch fixes this issue by modifying rb_const_search() to take a VALUE pointer to be filled with the module/class where the constant was found. [Bug #21782]
2025-12-16Add the instance variable name and the module in Ractor::IsolationError (#15563)Étienne Barrié
2025-12-16Add the class variable and the class itself in Ractor::IsolationError (#15562)Étienne Barrié
2025-12-04Add `rb_eval_cmd_call_kw` to shortcutNobuyoshi Nakada
2025-12-03wb-protect autoload_constJohn Hawthorn
2025-12-03Rename `rb_obj_exivar_p` -> `rb_obj_gen_fields_p`Jean Boussier
The "EXIVAR" terminology has been replaced by "gen fields" AKA "generic fields". Exivar implies variable, but generic fields include more than just variables, e.g. `object_id`.
2025-11-26Error if deleting a nonexistent obj from genivJohn Hawthorn
I don't think this ever happened, but we should raise the same error we'd raise on lookup
2025-11-26Ensure we don't dereference fields_obj as QundefJohn Hawthorn
We rely on the GC to clear this when the GC is run on another EC than the cache.
2025-11-26Clear fields obj when removingJohn Hawthorn
This fixes a bug where the gen_fields_cache could become invalid when the last ivar was removed. Also adds more assertions.
2025-11-07renaming internal data structures and functions from namespace to boxSatoshi Tagomori
2025-11-07update referenced filenames from namespace to boxSatoshi Tagomori
2025-11-04Don't run global variable hook functions with VM lock held (#15053)Luke Gruber
We can't run arbitrary ruby code with the VM lock held.
2025-10-23use `SET_SHAREABLE`Koichi Sasada
to adopt strict shareable rule. * (basically) shareable objects only refer shareable objects * (exception) shareable objects can refere unshareable objects but should not leak reference to unshareable objects to Ruby world
2025-10-19Fix memory leak in rb_const_remove when using namespacePeter Zhu
We need to free the rb_const_entry_t we remove from the RCLASS_WRITABLE_CONST_TBL otherwise it will leak memory.
2025-10-14Split gvar space between root and main namespacesSatoshi Tagomori
2025-09-29Update current namespace management by using control frames and lexical contextsSatoshi Tagomori
to fix inconsistent and wrong current namespace detections. This includes: * Moving load_path and related things from rb_vm_t to rb_namespace_t to simplify accessing those values via namespace (instead of accessing either vm or ns) * Initializing root_namespace earlier and consolidate builtin_namespace into root_namespace * Adding VM_FRAME_FLAG_NS_REQUIRE for checkpoints to detect a namespace to load/require files * Removing implicit refinements in the root namespace which was used to determine the namespace to be loaded (replaced by VM_FRAME_FLAG_NS_REQUIRE) * Removing namespaces from rb_proc_t because its namespace can be identified by lexical context * Starting to use ep[VM_ENV_DATA_INDEX_SPECVAL] to store the current namespace when the frame type is MAGIC_TOP or MAGIC_CLASS (block handlers don't exist in this case)
2025-09-09Fix global variable counter for aliasPeter Zhu
If we alias two variable multiple times, for example like this: alias $foo $bar alias $foo $bar Then we will increment the counter for entry2->var->counter each time, which is not correct because we are not adding more references to entry2->var. This reports as a memory leak in RUBY_FREE_AT_EXIT because entry2->var->counter will never reach 0 and thus will never be freed.
2025-09-09Fix undefined behaviour in rb_alias_variablePeter Zhu
entry1 is allocated using xmalloc (through ALLOC), which returns undefined memory. We never set the ractor_local field, so the value is undefined.
2025-08-29YJIT: rb_ivar_get_at skip ractor checksJean Boussier
Using `assume_single_ractor_mode` we can skip all ractor safety checks if we're in single ractor mode. ``` compare-ruby: ruby 3.5.0dev (2025-08-27T14:58:58Z merge-vm-setivar-d.. 5b749d8e53) +YJIT +PRISM [arm64-darwin24] built-ruby: ruby 3.5.0dev (2025-08-28T21:23:38Z yjit-get-exivar 3cc21b76d4) +YJIT +PRISM [arm64-darwin24] | |compare-ruby|built-ruby| |:--------------------------|-----------:|---------:| |vm_ivar_get_on_obj | 975.981| 975.772| | | 1.00x| -| |vm_ivar_get_on_class | 136.214| 470.912| | | -| 3.46x| |vm_ivar_get_on_generic | 148.315| 299.122| | | -| 2.02x| ```
2025-08-29YJIT: getinstancevariable cache indexes for types other than T_OBJECTJean Boussier
While accessing the ivars of other types is too complicated to realistically generate the ASM for it, we can at least provide the ivar index as to not have to lookup the shape tree every time. ``` compare-ruby: ruby 3.5.0dev (2025-08-27T14:58:58Z merge-vm-setivar-d.. 5b749d8e53) +YJIT +PRISM [arm64-darwin24] built-ruby: ruby 3.5.0dev (2025-08-28T17:58:32Z yjit-get-exivar efaa8c9b09) +YJIT +PRISM [arm64-darwin24] | |compare-ruby|built-ruby| |:--------------------------|-----------:|---------:| |vm_ivar_get_on_obj | 930.458| 936.865| | | -| 1.01x| |vm_ivar_get_on_class | 134.471| 431.622| | | -| 3.21x| |vm_ivar_get_on_generic | 146.679| 284.408| | | -| 1.94x| ``` Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
2025-08-28rb_ivar_delete: also re-embed T_IMEMO/fieldsJean Boussier
Right now JITs don't generate any code to access ivar on types other than T_OBJECT, but they might soon, so we must ensure two IMEMO/fields can't have the same `shape_id` but diffent embed/heap status.
2025-08-28rb_ivar_delete: allow complex transitionJean Boussier
`rb_ivar_delete` would force a new shape to be created. And in the case of a shape exhaustion, it wouldn't handle T_CLASS/T_MODULE correctly.
2025-08-28Populate ivar caches for types other than T_OBJECTJean Boussier
`vm_setinstancevariable` had a codepath to try to match the inline cache for types other than T_OBJECT, but the cache population path in `vm_setivar_slowpath` was exclusive to T_OBJECT, so `vm_setivar_default` would never match anything. This commit improves `vm_setivar_slowpath` so that it is capable of filling the cache for all types, and adds a `vm_setivar_class` codepath for `T_CLASS` and `T_MODULE`. `vm_setivar`, `vm_setivar_default` and `vm_setivar_class` could be unified, but based on the very explicit `NOINLINE` I assume they were split to minimize codesize. ``` compare-ruby: ruby 3.5.0dev (2025-08-27T14:58:58Z merge-vm-setivar-d.. 5b749d8e53) +PRISM [arm64-darwin24] built-ruby: ruby 3.5.0dev (2025-08-27T16:30:31Z setivar-cache-gene.. 4fe78ff296) +PRISM [arm64-darwin24] | |compare-ruby|built-ruby| |:------------------------|-----------:|---------:| |vm_ivar_set_on_instance | 161.809| 164.688| | | -| 1.02x| |vm_ivar_set_on_generic | 58.769| 115.638| | | -| 1.97x| |vm_ivar_set_on_class | 70.034| 141.042| | | -| 2.01x| ```
2025-08-27Replace ROBJECT_EMBED by ROBJECT_HEAPJean Boussier
The embed layout is way more common than the heap one, especially since WVA. I think it makes for more readable code to inverse the flag.
2025-08-26Fix uninitialized next_shape_id (#14348)Takashi Kokubun
2025-08-26rb_obj_field_get: unify codepathsJean Boussier
Now that T_OBJECT and T_IMEMO/fields have identical layout a lot more codepaths can be shared.
2025-08-26rb_ivar_lookup: unify codepathsJean Boussier
Now that T_OBJECT and T_IMEMO/fields have identical layout a lot more codepaths can be shared.
2025-08-26Ensure T_OBJECT and T_IMEMO/fields have identical layoutJean Boussier
2025-08-25Refactor class_fields_ivar_set to use generic_shape_ivarJean Boussier
2025-08-25Refactor rb_obj_ivar_set to delegate to obj_field_setJean Boussier
2025-08-25Refactor rb_obj_ivar_set to use generic_shape_ivarJean Boussier
2025-08-25Get rid of rb_obj_set_shape_idJean Boussier
Now that the shape_id has been unified across all types this helper function doesn't do much over `RBASIC_SET_SHAPE_ID`. It still check if the write is needed, but it doesn't seem useful in places where it's used.
2025-08-25Refactor rb_obj_ivar_setJean Boussier
With the recent changes to shapes and variables `general_ivar_set` no longer make sense and is just extra complexity. Trying to have a unified logic for all 3 types of objects made sense, but also made the code way more complex. We should definitely try to share more code between the 3 paths though, but that can be done with functions like `generic_shape_ivar`.
2025-08-25Get rid of obj_ivar_set_transition_too_complexJean Boussier
2025-08-21variable.c: handle cleared fields_obj in genfields cacheJean Boussier
[Bug #21547] Followup: https://github.com/ruby/ruby/pull/14201 When adding an instance variable and the IMEMO/fields need to be larger, we allocate a new one and clear the old one. Since the old one may still be in other ec's cache, on a hit we must check the IMEMO/fields isn't a stale one.
2025-08-13Implement `gen_fields_tbl` cacheJean Boussier
There is a high likelyhood that `rb_obj_fields` is called consecutively for the same object. If we keep a cache of the last IMEMO/fields we interacted with, we can save having to lookup the `gen_fields_tbl`, synchronize the VM lock, etc. On yjit-bench's, I instrumented the hit rate of this cache at: - `shipit`: 38%, with 111k hits. - `lobsters`: 59%, with 367k hits. - `rubocop`: 100% with only 300 hits. I also ran a micro-benchmark which shows that ivar access is: - 1.25x faster when the cache is hit in single ractor mode. - 2x faster when the cache is hit in multi ractor mode. - 1.06x slower when the cache miss in single ractor mode. - 1.01x slower when the cache miss in multi ractor mode. ```yml prelude: | class GenIvar < Array def initialize(...) super @iv = 1 end attr_reader :iv end a = GenIvar.new b = GenIvar.new benchmark: hit: a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; a.iv; miss: a.iv; b.iv; a.iv; b.iv; a.iv; b.iv; a.iv; b.iv; a.iv; b.iv; a.iv; b.iv; a.iv; b.iv; a.iv; b.iv; a.iv; b.iv; a.iv; b.iv; ``` Single ractor: ``` compare-ruby: ruby 3.5.0dev (2025-08-12T02:14:57Z master 428937a536) +YJIT +PRISM [arm64-darwin24] built-ruby: ruby 3.5.0dev (2025-08-12T09:25:35Z gen-fields-cache 9456c35893) +YJIT +PRISM [arm64-darwin24] warming up.. | |compare-ruby|built-ruby| |:-----|-----------:|---------:| |hit | 4.090M| 5.121M| | | -| 1.25x| |miss | 3.756M| 3.534M| | | 1.06x| -| ``` Multi-ractor: ``` compare-ruby: ruby 3.5.0dev (2025-08-12T02:14:57Z master 428937a536) +YJIT +PRISM [arm64-darwin24] built-ruby: ruby 3.5.0dev (2025-08-12T09:25:35Z gen-fields-cache 9456c35893) +YJIT +PRISM [arm64-darwin24] warming up.. | |compare-ruby|built-ruby| |:-----|-----------:|---------:| |hit | 2.205M| 4.460M| | | -| 2.02x| |miss | 2.117M| 2.094M| | | 1.01x| -| ```
2025-08-13imemo_fields: store owner object in RBasic.klassJean Boussier
It is much more convenient than storing the klass, especially when dealing with `object_id` as it allows to update the id2ref table without having to dereference the owner, which may be garbage at that point.
2025-08-12RTypedData: keep direct reference to IMEMO/fieldsJean Boussier
Similar to f3206cc79bec2fd852e81ec56de59f0a67ab32b7 but for TypedData. It's quite common for TypedData objects to have a mix of reference in their struct and some ivars. Since we do happen to have 8B free in the RtypedData struct, we could use it to keep a direct reference to the IMEMO/fields saving having to synchronize the VM and lookup the `gen_fields_tbl` on every ivar access. For old school Data classes however, we don't have free space, but this API is soft-deprecated and no longer very common.
2025-08-12Use rb_gc_mark_and_move for autoload_dataPeter Zhu
2025-08-12Use rb_gc_mark_and_move for autoload_constPeter Zhu
2025-08-06Struct: keep direct reference to IMEMO/fields when space allowsJean Boussier
It's not rare for structs to have additional ivars, hence are one of the most common, if not the most common type in the `gen_fields_tbl`. This can cause Ractor contention, but even in single ractor mode means having to do a hash lookup to access the ivars, and increase GC work. Instead, unless the struct is perfectly right sized, we can store a reference to the associated IMEMO/fields object right after the last struct member. ``` compare-ruby: ruby 3.5.0dev (2025-08-06T12:50:36Z struct-ivar-fields-2 9a30d141a1) +PRISM [arm64-darwin24] built-ruby: ruby 3.5.0dev (2025-08-06T12:57:59Z struct-ivar-fields-2 2ff3ec237f) +PRISM [arm64-darwin24] warming up..... | |compare-ruby|built-ruby| |:---------------------|-----------:|---------:| |member_reader | 590.317k| 579.246k| | | 1.02x| -| |member_writer | 543.963k| 527.104k| | | 1.03x| -| |member_reader_method | 213.540k| 213.004k| | | 1.00x| -| |member_writer_method | 192.657k| 191.491k| | | 1.01x| -| |ivar_reader | 403.993k| 569.915k| | | -| 1.41x| ``` Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2025-08-06variable.c: refactor accesses to the generic_fields_tblJean Boussier
All accesses to `generic_fields_tbl_` are now encapsulated inside: - `rb_obj_fields` - `rb_obj_set_fields` - `rb_obj_replace_fields`
2025-08-01variable.c: Fix `rb_ivar_foreach` to not yield `object_id` of complex objectsJean Boussier
Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2025-07-31Also include shape type in assertAlan Wu
The assert also fails on interpreter-only runs: https://github.com/ruby/ruby/actions/runs/16658231740/job/47148610283
2025-07-31Print shape id when a flaky shapes assert failsAlan Wu
This has been failing intermittently during `test_marshal_with_ivar_and_id` for ZJIT and YJIT builds. https://github.com/ruby/ruby/actions/runs/16655987271/job/47140970602 https://github.com/ruby/ruby/actions/runs/16656119252/job/47141409113
2025-07-21Ractor: lock around global variable get/setLuke Gruber
There's a global id_table `rb_global_tbl` that needs a lock (I used VM lock). In the future, we might use a lock-free rb_id_table if we create such a data structure. Reproduction script that might crash or behave strangely: ```ruby 100.times do Ractor.new do 1_000_000.times do $stderr $stdout $stdin $VERBOSE $stderr $stdout $stdin $VERBOSE $stderr $stdout $stdin $VERBOSE end end end $myglobal0 = nil; $myglobal1 = nil; # ... vim macros to the rescue $myglobal100000 = nil; ```
2025-07-14Fix an indent [ci skip]Nobuyoshi Nakada
2025-07-09Fix whitespace on some RB_VM_LOCKING callsJohn Hawthorn
2025-07-04Remove unused src param from rb_shape_copy_fieldsJohn Hawthorn