ObjectSpace.dump writes the lengths with dump_append_sizet, because dump_append_ld takes a long and is also used for Fixnum values. The lengths are never negative, so the output does not change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit adds `jit_calls` and `jit_threshold_reached` to iseq dumps which
dumps the number of calls to the iseq and whether the iseq has been JIT
compiled or not, respectively.
Since the FREEOBJ internal event fires only for the main objspace (a
non-main Ractor's lock-free sweep must not run arbitrary C callbacks),
an object that dies in another Ractor leaves its allocation-tracing
entry behind, still marked living. When the allocator reuses that
address, newobj_i tripped its debug assertion; release builds already
recycle the entry. Drop the stale assertion.
This was latent but rare while a dead Ractor's pages waited for the
inheritor's next major GC; the previous commits return those pages to
the pool at death, which made it deterministic
(TestObjSpaceRactor#test_tracing_does_not_crash on assert builds).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
After the rlgc merge, this method and also ObjectSpace.shareable_objects_from_roots could
return foreign unshareables which violates Ractor containment.
Replace `tool/update-deps` with a Ruby source scanner so dependency
updates no longer require GNU make, a configured build, or compiler
preprocessor output.
Keep compact source mappings and scanner declarations in dependency
files, and expand complete rules into the build directory. Avoid the
temporary fixture headers required by the compiler-driven prototype.
Use the generated rules from GNU make, BSD make, and NMake builds.
Support out-of-tree and read-only source trees, and retain expanded
dependencies shipped in release archives when baseruby is unavailable.
Object tracing listens to the NEWOBJ hook to see all objects allocated
while it is active. Previously it also enabled a FREEOBJ tracepoint to
drop each object's record as the object was freed.
However the FREEOBJ tracepoint only fires while tracing is active. An
object recorded during tracing can be freed after tracing stops, and
that free was missed, leaving a stale record in object_table keyed by a
freed object. These dangling keys are unsafe during compaction, which
was previously mitigated with rb_gc_pointer_to_heap_p (which I'd like to
stop using). These dangling keys could also become incorrectly
associated with a new object allocated in its place.
Instead we can declare object_table's keys as weak references. The GC
then invokes our weak reference callback on every collection, whether or
not tracing is running, letting us reap the records of objects about to
be freed. This callback runs before the FREEOBJ hook, which makes the
FREEOBJ tracepoint unnecessary.
RHash isn't a good fit for storing `cdhash` as this force to allow
arbitrary hash types into RHash, which doesn't work with AR tables.
It also cause the cdhash to be larger than needed.
That API made sense before b00f280d4b
as finding a module name was costly, but it now is a very cheap
operation, and that function is now just an outdated alias.
[Bug #21952]
Solves the double-free or use after-free concern with boxes.
Now entries can safely be used for copy-on-write.
Also is likely necessary to make it save to read cvar from
secondary ractors, as allowed since: ab32c0e690
This adds "free_immediately: false" to the heap dump for any T_DATA
which doesn't specify RUBY_TYPED_FREE_IMMEDIATELY. These are the objects
which end up as T_ZOMBIE and will have their dfree callback deferred to
later when the program is running holding the GVL.
This is useful to include because there is more overhead to freeing
these objects, and it's worth knowing how many there are.
`File.join` is a hotspot for common libraries such as Zeitwerk
and Bootsnap. It has a fairly flexible signature, but 99% of
the time it's called with just two (or a small number of) UTF-8 strings.
If we optimistically optimize for that use case we can cut down a large
number of type and encoding checks, significantly speeding up the method.
The one remaining expensive check we could try to optimize is `str_null_check`.
Given it's common to use the same base string for joining, we could memoize it.
Also we could precompute it for literal strings.
```
compare-ruby: ruby 4.1.0dev (2026-01-17T14:40:03Z master 00a3b71eaf) +PRISM [arm64-darwin25]
built-ruby: ruby 4.1.0dev (2026-01-18T12:10:38Z spedup-file-join 069bab58d4) +PRISM [arm64-darwin25]
warming up....
| |compare-ruby|built-ruby|
|:-------------|-----------:|---------:|
|two_strings | 2.475M| 9.444M|
| | -| 3.82x|
|many_strings | 551.975k| 2.346M|
| | -| 4.25x|
|array | 514.946k| 522.034k|
| | -| 1.01x|
|mixed | 621.236k| 633.189k|
| | -| 1.02x|
```
allocation_info_tracer_compact_update_object_table_i deletes entries where
the key is no longer in the GC heap but did not free the allocation_info
causing the memory to be leaked.
`RSHAPE_PARENT` is error prone because it returns a raw untagged
shape_id.
To check if a shape is a direct parent of another, tags should be
discarded. So providing a comparison function is better than exposing
untagged ids.