225 Commits
Author SHA1 Message Date
Max Bernstein b43e66d3b3 YJIT: Pass class and shape ID directly instead of object 2025-12-03 16:59:05 -05:00
Max Bernstein f167073324 Move imemo fields check out of shape_get_next
Not every caller (for example, YJIT) actually needs to pass the object.
YJIT (and, in the future, ZJIT) only need to pass the class.
2025-12-03 16:59:05 -05:00
Max BernsteinandAaron Patterson 612a66805f Remove spurious obj != klass check in shape_get_next
This should never be true. I added an `rb_bug` in case it was and it
wasn't true in any of btest or test-all.

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2025-12-03 16:59:05 -05:00
Jean Boussier 8c3909935e Handle NEWOBJ tracepoints settings fields
[Bug #21710]

- struct.c: `struct_alloc`

It is possible for a `NEWOBJ` tracepoint call back to write fields
into a newly allocated object before `struct_alloc` had the time
to set the `RSTRUCT_GEN_FIELDS` flags and such.

Hence we can't blindly initialize the `fields_obj` reference to `0`
we first need to check no fields were added yet.

- object.c: `rb_class_allocate_instance`

Similarly, if a `NEWOBJ` tracepoint tries to set fields on the object,
the `shape_id` must already be set, as it's required on T_OBJECT to
know where to write fields.

`NEWOBJ_OF` had to be refactored to accept a `shape_id`.
2025-12-03 08:14:56 +01:00
Satoshi Tagomori d2a587c791 renaming internal data structures and functions from namespace to box 2025-11-07 13:14:54 +09:00
Jean Boussier 05fc01188a rb_ivar_delete: allow complex transition
`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-28 15:21:05 +02:00
Jean Boussier 5257e1298c Replace ROBJECT_EMBED by ROBJECT_HEAP
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-27 12:41:07 +02:00
Jean Boussier 14bdf4b57d Ensure T_OBJECT and T_IMEMO/fields have identical layout 2025-08-26 13:44:59 +02:00
Étienne Barrié b0c80c2be8 Remove unused SPECIAL_CONST_SHAPE_ID
Its usage was removed in 306d50811d.
2025-08-21 17:41:39 +02:00
Max Bernstein 306d50811d Don't allow looking at the shape ID of immediates (#14266)
It only makes sense for heap objects.
2025-08-18 18:58:38 -04:00
John HawthornandAaron Patterson 7d2b724e08 Add missing writebarrier on complex obj dup
When we dup a complex object we need to issue a writebarrier_remember
on the new object. This was caught by wbcheck inside the rubygems test
suite.

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2025-08-18 11:59:58 -07:00
Jean Boussier 10aa4134d4 imemo_fields: store owner object in RBasic.klass
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-13 19:53:18 +02:00
Jean Boussier 559d9e1f67 Convert VM/shape_tree to use rb_gc_mark_and_move
The `p->field = rb_gc_location(p->field)` isn't ideal because it means all
references are rewritten on compaction, regardless of whether the referenced
object has moved. This isn't good for caches nor for Copy-on-Write.

`rb_gc_mark_and_move` avoid needless writes, and most of the time allow to
have a single function for both marking and updating references.
2025-08-07 21:00:00 +02:00
Jean BoussierandPeter Zhu 1064c63643 Fix rb_shape_transition_object_id transition to TOO_COMPLEX
If `get_next_shape_internal` fail to return a shape, we must
transitiont to a complex shape. `shape_transition_object_id`
mistakenly didn't.

Co-Authored-By: Peter Zhu <peter@peterzhu.ca>
2025-08-01 12:39:14 +02:00
John Hawthorn 54f28c1db9 Avoid concurrently overflowing of shape_id
Previously it was possible for two atomic increments of next_shape_id
running concurrently to overflow MAX_SHAPE_ID. For this reason we need
to do the test atomically with the allocation in shape_alloc returning
NULL.

This avoids overflowing next_shape_id by repeatedly attempting a CAS.
Alternatively we could have allowed incrementing past MAX_SHAPE_ID and
then clamping in rb_shapes_count, but this seems simpler.
2025-07-09 10:38:04 -07:00
John Hawthorn cfc006d410 Always use atomics to get the shape count
When sharing between threads we need both atomic reads and writes. We
probably didn't need to use this in some cases (where we weren't running
in multi-ractor mode) but I think it's best to be consistent.
2025-07-09 10:38:04 -07:00
John Hawthorn 5dfd86cf3f Fix off-by-one in shape_tree_mark/shape_tree_compact
This was using < so subtract one from the last shape id would have us
miss the last inserted shape. I think this is unlikely to have caused
issues because I don't think the newest shape will ever have edges.

We do need to use `- 1` because otherwise RSHAPE wraps around and
returns the root shape.
2025-07-09 10:38:04 -07:00
John Hawthorn 12b0ce3875 Remove unused src param from rb_shape_copy_fields 2025-07-04 14:54:49 -07:00
Jean Boussier 242343ff80 variable.c: Refactor generic_field_set / generic_ivar_set
These two functions are very similar, they can share most of their
logic.
2025-06-26 16:25:57 +02:00
Peter Zhu aed7a95f9d Move RUBY_ATOMIC_VALUE_LOAD to ruby_atomic.h
Deduplicates RUBY_ATOMIC_VALUE_LOAD by moving it to ruby_atomic.h.
2025-06-25 13:04:25 -04:00
Jean Boussier b284987651 Cleanup and document shape_id_t layout 2025-06-24 16:19:16 +01:00
Jean Boussier 45a2c95d0f Reduce exposure of FL_FREEZE
The `FL_FREEZE` flag is redundant with `SHAPE_ID_FL_FROZEN`, so
ideally it should be eliminated in favor of the later.

Doing so would eliminate the risk of desync between the two, but
also solve the problem of the frozen status being global in namespace
context (See Bug #21330).
2025-06-24 11:29:39 +01:00
Jean Boussier fb68721f63 Rename imemo_class_fields -> imemo_fields 2025-06-17 15:28:05 +02:00
ydah 2d96400c26 Fix typo in error message for shape_id verification 2025-06-15 22:35:50 +09:00
Jean Boussier 15084fbc3c Get rid of FL_EXIVAR
Now that the shape_id gives us all the same information, it's no
longer needed.
2025-06-13 23:50:30 +02:00
Jean Boussier 6dbe24fe56 Use the shape_id rather than FL_EXIVAR
We still keep setting `FL_EXIVAR` so that `rb_shape_verify_consistency`
can detect discrepancies.
2025-06-13 23:50:30 +02:00
Jean Boussier b51078f82e Enforce consistency between shape_id and FL_EXIVAR
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.
2025-06-13 23:50:30 +02:00
Nobuyoshi Nakada f2d7c6afee Suppress unused-variable warning 2025-06-13 22:24:09 +02:00
Jean Boussier a99d941cac Add SHAPE_ID_HAS_IVAR_MASK for quick ivar check
This allow checking if an object has ivars with just a shape_id
mask.
2025-06-13 19:46:29 +02:00
Nobuyoshi Nakada 1d11e1be13 Suppress unused-variable warning 2025-06-13 21:09:20 +09:00
Jean Boussier 071aa02a4a shape.c: cleanup unused IDs
id_frozen and id_t_object are no longer used.
id_object_id no longer need to be exposed.
2025-06-13 12:03:22 +02:00
Jean Boussier 7c22330cd2 Allocate rb_shape_tree statically
There is no point allocating it during init, it adds
a useless indirection.
2025-06-12 17:08:22 +02:00
Jean Boussier de4b910381 Get rid of GET_SHAPE_TREE()
It's a useless indirection.
2025-06-12 17:08:22 +02:00
Jean Boussier e070d93573 Get rid of rb_shape_lookup 2025-06-12 17:08:22 +02:00
Jean Boussier 0292b702c4 shape.h: make RSHAPE static inline
Since the shape_tree_ptr is `extern` it should be possible to
fully inline `RSHAPE`.
2025-06-12 17:08:22 +02:00
Jean Boussier 8b5ac5abf2 Fix class instance variable inside namespaces
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.
2025-06-12 13:43:29 +02:00
Jean Boussier 3abdd4241f Turn rb_classext_t.fields into a T_IMEMO/class_fields
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.
2025-06-12 07:58:16 +02:00
Jean Boussier 95201299fd Refactor the last references to rb_shape_t
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`.
2025-06-11 16:38:38 +02:00
Jean Boussier c2f2ac7db3 shape.c: Fix rb_bug call to use correct format for size_t 2025-06-11 10:10:04 +02:00
Étienne Barrié c54e96d651 Fix RubyVM::Shape.transition_tree 2025-06-10 19:37:03 +02:00
Jean Boussier 7d8695e02f Stop pinning shape edges
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.
2025-06-07 18:30:44 +02:00
Jean Boussier a640723d31 Simplify rb_gc_rebuild_shape
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.
2025-06-07 18:30:44 +02:00
Jean Boussier 191f6e3b87 Get rid of rb_shape_t.heap_id 2025-06-07 18:30:44 +02:00
Jean Boussier 6eb0cd8df7 Get rid of SHAPE_T_OBJECT
Now that we have the `heap_index` in shape flags we no longer
need `T_OBJECT` shapes.
2025-06-07 18:30:44 +02:00
Jean Boussier 2de67d424f shape.c: assert we're not returning INVALID_SHAPE_ID. 2025-06-07 18:30:44 +02:00
Jean Boussier 8c4e368dcf shape.c: ensure heap_index is consistent for complex shapes 2025-06-07 18:30:44 +02:00
Jean Boussier 689ec51146 Replicate heap_index in shape_id flags.
This is preparation to getting rid of `T_OBJECT` transitions.
By first only replicating the information it's easier to ensure
consistency.
2025-06-07 18:30:44 +02:00
Jean BoussierandLuke Gruber 90ba2f4e1c Add missing lock around redblack_cache_ancestors
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 <luke.gruber@shopify.com>
2025-06-06 23:07:22 +02:00
Jean Boussier 2b810ac595 shape.c: match capacity growth with T_OBJECT embedded sizes
This helps with getting with of `SHAPE_T_OBJECT`, by ensuring
that transitions will have capacities that match the next embed size.
2025-06-06 13:37:03 +02:00
Jean Boussier 3883c38979 shape.c: Fix improperly named routine
Meant to be `transition_complex` not `transition_frozen`.
2025-06-06 11:43:51 +02:00