summaryrefslogtreecommitdiff
path: root/shape.c
AgeCommit message (Collapse)Author
6 daysRename `imemo_class_fields` -> `imemo_fields`Jean Boussier
Notes: Merged: https://.com/ruby/ruby/pull/13626
8 daysFix typo in error message for shape_id verificationydah
Notes: Merged: https://.com/ruby/ruby/pull/13621
9 daysGet rid of FL_EXIVARJean Boussier
Now that the shape_id gives us all the same information, it's no longer needed. Notes: Merged: https://.com/ruby/ruby/pull/13612
9 daysUse the `shape_id` rather than `FL_EXIVAR`Jean Boussier
We still keep setting `FL_EXIVAR` so that `rb_shape_verify_consistency` can detect discrepancies. Notes: Merged: https://.com/ruby/ruby/pull/13612
9 daysEnforce consistency between shape_id and FL_EXIVARJean Boussier
The FL_EXIVAR is a bit redundant with the shape_id. Now that the `shape_id` is embedded in all objects on all archs, we can cheaply check if an object has any fields with a simple bitmask. Notes: Merged: https://.com/ruby/ruby/pull/13612
10 daysSuppress unused-variable warningNobuyoshi Nakada
10 daysAdd SHAPE_ID_HAS_IVAR_MASK for quick ivar checkJean Boussier
This allow checking if an object has ivars with just a shape_id mask. Notes: Merged: https://.com/ruby/ruby/pull/13606
10 daysSuppress unused-variable warningNobuyoshi Nakada
10 daysshape.c: cleanup unused IDsJean Boussier
id_frozen and id_t_object are no longer used. id_object_id no longer need to be exposed. Notes: Merged: https://.com/ruby/ruby/pull/13605
11 daysAllocate `rb_shape_tree` staticallyJean Boussier
There is no point allocating it during init, it adds a useless indirection. Notes: Merged: https://.com/ruby/ruby/pull/13596
11 daysGet rid of GET_SHAPE_TREE()Jean Boussier
It's a useless indirection. Notes: Merged: https://.com/ruby/ruby/pull/13596
11 daysGet rid of `rb_shape_lookup`Jean Boussier
Notes: Merged: https://.com/ruby/ruby/pull/13596
11 daysshape.h: make RSHAPE static inlineJean Boussier
Since the shape_tree_ptr is `extern` it should be possible to fully inline `RSHAPE`. Notes: Merged: https://.com/ruby/ruby/pull/13596
11 daysFix 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://.com/ruby/ruby/pull/13595
11 daysTurn `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://.com/ruby/ruby/pull/13411
12 daysRefactor 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://.com/ruby/ruby/pull/13586
12 daysshape.c: Fix rb_bug call to use correct format for size_tJean Boussier
Notes: Merged: https://.com/ruby/ruby/pull/13583
13 daysFix RubyVM::Shape.transition_treeÉtienne Barrié
Notes: Merged: https://.com/ruby/ruby/pull/13578
2025-06-07Stop pinning shape edgesJean Boussier
Now that `rb_shape_traverse_from_new_root` has been eliminated there's no longer any reason to pin these objects, because we no longer need to traverse shapes downward during compaction. Notes: Merged: https://.com/ruby/ruby/pull/13556
2025-06-07Simplify `rb_gc_rebuild_shape`Jean Boussier
Now that there no longer multiple shape roots, all we need to do when moving an object from one slot to the other is to update the `heap_index` part of the shape_id. Since this never need to create a shape transition, it will always work and never result in a complex shape. Notes: Merged: https://.com/ruby/ruby/pull/13556
2025-06-07Get rid of rb_shape_t.heap_idJean Boussier
Notes: Merged: https://.com/ruby/ruby/pull/13556
2025-06-07Get 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://.com/ruby/ruby/pull/13556
2025-06-07shape.c: assert we're not returning INVALID_SHAPE_ID.Jean Boussier
Notes: Merged: https://.com/ruby/ruby/pull/13556
2025-06-07shape.c: ensure heap_index is consistent for complex shapesJean Boussier
Notes: Merged: https://.com/ruby/ruby/pull/13556
2025-06-07Replicate `heap_index` in shape_id flags.Jean Boussier
This is preparation to getting rid of `T_OBJECT` transitions. By first only replicating the information it's easier to ensure consistency. Notes: Merged: https://.com/ruby/ruby/pull/13556
2025-06-06Add missing lock around `redblack_cache_ancestors`Jean Boussier
This used to be protected because all shape code was under a lock, but now that the shape tree is lock-free we still need to lock around the red-black cache. Co-Authored-By: Luke Gruber <[email protected]> Notes: Merged: https://.com/ruby/ruby/pull/13552
2025-06-06shape.c: match capacity growth with T_OBJECT embedded sizesJean Boussier
This helps with getting with of `SHAPE_T_OBJECT`, by ensuring that transitions will have capacities that match the next embed size. Notes: Merged: https://.com/ruby/ruby/pull/13548
2025-06-06shape.c: Fix improperly named routineJean Boussier
Meant to be `transition_complex` not `transition_frozen`.
2025-06-05Refactor raw accesses to rb_shape_t.capacityJean Boussier
Notes: Merged: https://.com/ruby/ruby/pull/13524
2025-06-05Fix comment about debugging shapesÉtienne Barrié
This method was moved to RubyVM::Shape in 913979bede2a1b79109fa2072352882560d55fe0.
2025-06-05Get 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://.com/ruby/ruby/pull/13515
2025-06-04Get 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://.com/ruby/ruby/pull/13511
2025-06-04shape.c: fix off by one error in `shape_tree_mark`Jean Boussier
Notes: Merged: https://.com/ruby/ruby/pull/13289
2025-06-04Get 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://.com/ruby/ruby/pull/13289
2025-06-02Pin shape->edgesJean Boussier
Notes: Merged: https://.com/ruby/ruby/pull/13441
2025-06-02shape.c: Implement a lock-free version of get_next_shape_internalJean Boussier
Whenever we run into an inline cache miss when we try to set an ivar, we may need to take the global lock, just to be able to lookup inside `shape->edges`. To solve that, when we're in multi-ractor mode, we can treat the `shape->edges` as immutable. When we need to add a new edge, we first copy the table, and then replace it with CAS. This increases memory allocations, however we expect that creating new transitions becomes increasingly rare over time. ```ruby class A def initialize(bool) @a = 1 if bool @b = 2 else @c = 3 end end def test @d = 4 end end def bench(iterations) i = iterations while i > 0 A.new(true).test A.new(false).test i -= 1 end end if ARGV.first == "ractor" ractors = 8.times.map do Ractor.new do bench(20_000_000 / 8) end end ractors.each(&:take) else bench(20_000_000) end ``` The above benchmark takes 27 seconds in Ractor mode on Ruby 3.4, and only 1.7s with this branch. Co-Authored-By: Étienne Barrié <[email protected]> Notes: Merged: https://.com/ruby/ruby/pull/13441
2025-05-27Rename `rb_shape_frozen_shape_p` -> `shape_frozen_p`Jean Boussier
Notes: Merged: https://.com/ruby/ruby/pull/13450
2025-05-27Refactor `rb_shape_too_complex_p` to take a `shape_id_t`.Jean Boussier
Notes: Merged: https://.com/ruby/ruby/pull/13450
2025-05-27Refactor `rb_shape_has_object_id`Jean Boussier
Now takes a `shape_id_t` and the version that takes a `rb_shape_t *` is private. Notes: Merged: https://.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://.com/ruby/ruby/pull/13450
2025-05-27Get rid of rb_shape_set_shapeJean Boussier
Notes: Merged: https://.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://.com/ruby/ruby/pull/13450
2025-05-27Get rid of `rb_shape_id(rb_shape_t *)`Jean Boussier
We should avoid conversions from `rb_shape_t *` into `shape_id_t` outside of `shape.c` as the short term goal is to have `shape_id_t` contain tags. Notes: Merged: https://.com/ruby/ruby/pull/13448
2025-05-27Refactor `rb_shape_rebuild_shape` to stop exposing `rb_shape_t`Jean Boussier
Notes: Merged: https://.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://.com/ruby/ruby/pull/13341
2025-05-25Use RB_VM_LOCKINGNobuyoshi Nakada
Notes: Merged: https://.com/ruby/ruby/pull/13439
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://.com/ruby/ruby/pull/13426
2025-05-13variable.c: Refactor rb_obj_field_* to take shape_id_tJean Boussier
Notes: Merged: https://.com/ruby/ruby/pull/13314
2025-05-11Allow T_CLASS and generic types to be too_complexJean Boussier
The intial complex shape implementation never allowed objects other than T_OBJECT to become too complex, unless we run out of shapes. I don't see any reason to prevent that. Ref: https://.com/ruby/ruby/pull/6931 Notes: Merged: https://.com/ruby/ruby/pull/13301
2025-05-11namespace on readSatoshi Tagomori