summaryrefslogtreecommitdiff
path: root/variable.c
AgeCommit message (Collapse)Author
59 min.Make setting and accessing class ivars lock-freeHEADmasterJean Boussier
Now that class fields have been deletated to a T_IMEMO/class_fields when we're in multi-ractor mode, we can read and write class instance variable in an atomic way using Read-Copy-Update (RCU). Note when in multi-ractor mode, we always use RCU. In theory we don't need to, instead if we ensured the field is written before the shape is updated it would be safe. Benchmark: ```ruby Warning[:experimental] = false class Foo @foo = 1 @bar = 2 @baz = 3 @egg = 4 @spam = 5 class << self attr_reader :foo, :bar, :baz, :egg, :spam end end ractors = 8.times.map do Ractor.new do 1_000_000.times do Foo.bar + Foo.baz * Foo.egg - Foo.spam end end end if Ractor.method_defined?(:value) ractors.each(&:value) else ractors.each(&:take) end ``` This branch vs Ruby 3.4: ```bash $ hyperfine -w 1 'ruby --disable-all ../test.rb' './miniruby ../test.rb' Benchmark 1: ruby --disable-all ../test.rb Time (mean ± σ): 3.162 s ± 0.071 s [User: 2.783 s, System: 10.809 s] Range (min … max): 3.093 s … 3.337 s 10 runs Benchmark 2: ./miniruby ../test.rb Time (mean ± σ): 208.7 ms ± 4.6 ms [User: 889.7 ms, System: 6.9 ms] Range (min … max): 202.8 ms … 222.0 ms 14 runs Summary ./miniruby ../test.rb ran 15.15 ± 0.47 times faster than ruby --disable-all ../test.rb ``` Notes: Merged: https://github.com/ruby/ruby/pull/13594
2 hoursFix class instance variable inside namespacesJean Boussier
Now that classes fields are delegated to an object with its own shape_id, we no longer need to mark all classes as TOO_COMPLEX. Notes: Merged: https://github.com/ruby/ruby/pull/13595
8 hoursTurn `rb_classext_t.fields` into a T_IMEMO/class_fieldsJean Boussier
This behave almost exactly as a T_OBJECT, the layout is entirely compatible. This aims to solve two problems. First, it solves the problem of namspaced classes having a single `shape_id`. Now each namespaced classext has an object that can hold the namespace specific shape. Second, it open the door to later make class instance variable writes atomics, hence be able to read class variables without locking the VM. In the future, in multi-ractor mode, we can do the write on a copy of the `fields_obj` and then atomically swap it. Considerations: - Right now the `RClass` shape_id is always synchronized, but with namespace we should likely mark classes that have multiple namespace with a specific shape flag. Notes: Merged: https://github.com/ruby/ruby/pull/13411
23 hoursRefactor the last references to `rb_shape_t`Jean Boussier
The type isn't opaque because Ruby isn't often compiled with LTO, so for optimization purpose it's better to allow as much inlining as possible. However ideally only `shape.c` and `shape.h` should deal with the actual struct, and everything else should just deal with opaque `shape_id_t`. Notes: Merged: https://github.com/ruby/ruby/pull/13586
3 daysGet rid of `gen_fields_tbl.fields_count`Jean Boussier
This data is redundant because the shape already contains both the length and capacity of the object's fields. So it both waste space and create the possibility of a desync between the two. We also do not need to initialize everything to Qundef, this seem to be a left-over from pre-shape instance variables. Notes: Merged: https://github.com/ruby/ruby/pull/13561
5 daysGet rid of SHAPE_T_OBJECTJean Boussier
Now that we have the `heap_index` in shape flags we no longer need `T_OBJECT` shapes. Notes: Merged: https://github.com/ruby/ruby/pull/13556
5 daysshape.c: ensure heap_index is consistent for complex shapesJean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13556
7 daysRefactor raw accesses to rb_shape_t.capacityJean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13524
7 daysSuppress warnings by gcc-13 with `-Og`Nobuyoshi Nakada
7 daysGet rid of `rb_shape_t.flags`Jean Boussier
Now all flags are only in the `shape_id_t`, and can all be checked without needing to dereference a pointer. Notes: Merged: https://github.com/ruby/ruby/pull/13515
8 daysGet rid of TOO_COMPLEX shape typeJean Boussier
Instead it's now a `shape_id` flag. This allows to check if an object is complex without having to chase the `rb_shape_t` pointer. Notes: Merged: https://github.com/ruby/ruby/pull/13511
8 daysAdd missing lock in `rb_ivar_defined`Jean Boussier
If called on a class, we should acquire the lock. Notes: Merged: https://github.com/ruby/ruby/pull/13502
8 daysGet rid of frozen shapes.Jean Boussier
Instead `shape_id_t` higher bits contain flags, and the first one tells whether the shape is frozen. This has multiple benefits: - Can check if a shape is frozen with a single bit check instead of dereferencing a pointer. - Guarantees it is always possible to transition to frozen. - This allow reclaiming `FL_FREEZE` (not done yet). The downside is you have to be careful to preserve these flags when transitioning. Notes: Merged: https://github.com/ruby/ruby/pull/13289
2025-05-27Rename `rb_shape_id_canonical_p` -> `rb_shape_canonical_p`Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13450
2025-05-27Rename `rb_shape_set_shape_id` in `rb_obj_set_shape_id`Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13450
2025-05-27Refactor `rb_shape_too_complex_p` to take a `shape_id_t`.Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13450
2025-05-27Refactor `rb_obj_shape` out.Jean Boussier
It still exists but only in `shape.c`. Notes: Merged: https://github.com/ruby/ruby/pull/13450
2025-05-27Refactor `rb_shape_get_iv_index` to take a `shape_id_t`Jean Boussier
Further reduce exposure of `rb_shape_t`. Notes: Merged: https://github.com/ruby/ruby/pull/13450
2025-05-27Get rid of `rb_shape_canonical_p`Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13448
2025-05-27Refactor `rb_shape_rebuild_shape` to stop exposing `rb_shape_t`Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13448
2025-05-26Add shape_id to RBasic under 32 bitJohn Hawthorn
This makes `RBobject` `4B` larger on 32 bit systems but simplifies the implementation a lot. [Feature #21353] Co-authored-by: Jean Boussier <[email protected]> Notes: Merged: https://github.com/ruby/ruby/pull/13341
2025-05-25Use RB_VM_LOCKINGNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/13439
2025-05-23Add missing lock for `Module#remove_instance_variable`Jean Boussier
We must take a lock to ensure another ractor isn't reading the ivars while we're moving them. Notes: Merged: https://github.com/ruby/ruby/pull/13426
2025-05-23Refactor `rb_shape_transition_remove_ivar`Jean Boussier
Move the fields management logic in `rb_ivar_delete`, and keep shape managment logic in `rb_shape_transition_remove_ivar`. Notes: Merged: https://github.com/ruby/ruby/pull/13426
2025-05-23lock vm around `rb_free_generic_ivar`Luke Gruber
Currently, this can be reproduced by: r = Ractor.new do a = [1, 2, 3] a.object_id a.dup # this frees the generic ivar for `object_id` on the copied object :done end r.take In debug builds, this hits an assertion failure without this fix. Notes: Merged: https://github.com/ruby/ruby/pull/13401
2025-05-21Use shape_id for determining "too complex"Aaron Patterson
Using `rb_shape_obj_too_complex_p` looks up the shape, but we already have the shape id. This avoids looking up the shape twice. Notes: Merged: https://github.com/ruby/ruby/pull/13373
2025-05-16rb_copy_generic_ivar: reset shape_id when no ivar are presentJean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13350
2025-05-13variable.c: Refactor rb_obj_field_* to take shape_id_tJean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13314
2025-05-11Add missing gc_mark in `autoload_const_mark`Jean Boussier
If we're referencing the namespace object we have to mark it.
2025-05-11Unexpectedly miss-fixed macro during rebaseSatoshi Tagomori
2025-05-11Follow the code style about elseSatoshi Tagomori
2025-05-11namespace on readSatoshi Tagomori
2025-05-10Refactor `rb_obj_field_get` to handle complex shapesJean Boussier
This allow to get or set fields without having to worry about the shape type. Notes: Merged: https://github.com/ruby/ruby/pull/13297
2025-05-10Rename `rb_field_get` -> `rb_obj_field_get`Jean Boussier
To be consistent with `rb_obj_field_set`. Notes: Merged: https://github.com/ruby/ruby/pull/13297
2025-05-09Rename `RB_OBJ_SHAPE` -> `rb_obj_shape`Jean Boussier
As well as `RB_OBJ_SHAPE_ID` -> `rb_obj_shape_id` and `RSHAPE` is now a simple alias for `rb_shape_lookup`. I tried to turn all these into `static inline` but I'm having trouble with `RUBY_EXTERN rb_shape_tree_t *rb_shape_tree_ptr;` not being exposed as I'd expect. Notes: Merged: https://github.com/ruby/ruby/pull/13283
2025-05-09Get rid of `rb_shape_get_parent`.Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13283
2025-05-09Rename `rb_shape_get_shape_id` -> `RB_OBJ_SHAPE_ID`Jean Boussier
And `rb_shape_get_shape` -> `RB_OBJ_SHAPE`. Notes: Merged: https://github.com/ruby/ruby/pull/13283
2025-05-09Refactor `rb_shape_get_next` to return an IDJean Boussier
Also rename it, and change parameters to be consistent with other transition functions. Notes: Merged: https://github.com/ruby/ruby/pull/13283
2025-05-09Refactor `rb_shape_transition_shape_remove_ivar` to not take a shape pointerJean Boussier
It's more consistent with other transition functions. Notes: Merged: https://github.com/ruby/ruby/pull/13283
2025-05-09Rename `rb_shape_obj_too_complex` -> `rb_shape_obj_too_complex_p`Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13283
2025-05-09Refactor `rb_shape_transition_too_complex` to return an ID.Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13283
2025-05-09Refactor `rb_shape_transition_frozen` to return a `shape_id`.Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13283
2025-05-09Rename `rb_shape_get_shape_by_id` -> `RSHAPE`Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13283
2025-05-08Fix -Wreturn-typeTakashi Kokubun
../variable.c: In function ‘iterate_over_shapes_with_callback’: ../variable.c:2189:1: warning: control reaches end of non-void function [-Wreturn-type] 2189 | } | ^
2025-05-08variable.c: Fix compilation warningsJean Boussier
``` variable.c: In function ‘iterate_over_shapes_with_callback’: variable.c:2188:1: warning: control reaches end of non-void function [-Wreturn-type] 2188 | } | ^ variable.c: In function ‘rb_field_get’: variable.c:1322:43: warning: ‘fields_tbl’ may be used uninitialized [-Wmaybe-uninitialized] 1322 | return fields_tbl->as.shape.fields[attr_index]; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~ variable.c:1319:32: note: ‘fields_tbl’ was declared here 1319 | struct gen_fields_tbl *fields_tbl; | ```
2025-05-08Move `object_id` in object fields.Jean Boussier
And get rid of the `obj_to_id_tbl` It's no longer needed, the `object_id` is now stored inline in the object alongside instance variables. We still need the inverse table in case `_id2ref` is invoked, but we lazily build it by walking the heap if that happens. The `object_id` concern is also no longer a GC implementation concern, but a generic implementation. Co-Authored-By: Matt Valentine-House <[email protected]> Notes: Merged: https://github.com/ruby/ruby/pull/13159
2025-05-08Refactor OBJ_TOO_COMPLEX_SHAPE_ID to not be referenced outside shape.hJean Boussier
Also refactor checks for `->type == SHAPE_OBJ_TOO_COMPLEX`. Notes: Merged: https://github.com/ruby/ruby/pull/13159
2025-05-08Rename `ivptr` -> `fields`, `next_iv_index` -> `next_field_index`Jean Boussier
Ivars will longer be the only thing stored inline via shapes, so keeping the `iv_index` and `ivptr` names would be confusing. Instance variables won't be the only thing stored inline via shapes, so keeping the `ivptr` name would be confusing. `field` encompass anything that can be stored in a VALUE array. Similarly, `gen_ivtbl` becomes `gen_fields_tbl`. Notes: Merged: https://github.com/ruby/ruby/pull/13159
2025-05-05variable.c: Fix too_complex shape initializationJean Boussier
`SHAPE_OBJ_TOO_COMPLEX` is a `shape_type` not a `shape_id_t`. Notes: Merged: https://github.com/ruby/ruby/pull/13257
2025-05-05Improve style consistency of `rb_shape_t *`Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13257