| Age | Commit message (Collapse) | Author |
|
Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
|
|
|
|
|
|
This change separates the master box from the root box, as the single
master copy of boxes.
Before this change, the root box is the source of copies, and also
it runs builtin classes' code. Builtin code makes changes by
requiring files, thus the source of copies is mutable, be different
from the past one. This causes different internal states of boxes,
depending on when it is created.
After this change, all boxes are created from the master box, and
the master box never runs code, so it realizes the immutable source
of copies.
This also makes is possible to separate RubyGems (and other default
gems) from each boxes. All boxes will have their own copies of RubyGems.
RubyGems has its internal state, but it'll be separated between boxes
after this change.
|
|
These are internal-only helpers which can be used instead of the
RMATCH_REGS struct directly. RMATCH_REGS is just a pointer offset from
the RMatch VALUE itself, so this should not significantly affect
codegen.
The motivation for this is that it's both simpler, and should move us
towards being able to replace the storage for RMATCH, and to be able to
store the positions embedded instead of in separate malloc memory.
|
|
Fix-up for d3ef85a100a4d051fcafc6ef6c09c4faaecc086a.
|
|
[Bug #21818]
Currently exceptions can be sent across ractors,
but because of a limitation in the TypedData API,
the exception backtrace is duped as an empty backtrace.
The problem is that backtraces are embedded objects,
hence the classic `rb_class_alloc(klass)` API is insufficient
because we need to know the size of the Backtrace object we're
duping to instantiate the copy.
This is worked around by changing Ractors to call `#clone` on objects
rather than use `rb_obj_clone`, and to implement `Thread::Backtrace#clone`
to properly clone the variable size object.
|
|
Add rb_iseq_bare_opcode_at_pc which uses rb_vm_insn_addr2insn to
return the base instruction, stripping trace/zjit variants. Use it
in iseq_may_write_block_code to simplify the match arms.
|
|
Co-authored-by: Alan Wu <alanwu@ruby-lang.org>
|
|
* Instances of a subclass of Regexp are not frozen for compatibility.
* [Feature #8948]
* Use a less confusing example in test_regexp2,
the ivar was named @encoding but had no effect on Regexp#encoding.
|
|
|
|
|
|
Prism changed structure quite a bit. Most of the previously-public
structs are now opaque. This requires quite a bit of changes
internally.
It also triggered some unrelated changes, which were necessary
because Prism's main header used to pull in standard headers. So
box.c and jit.c are now no longer transitively getting all the
headers they needed.
|
|
|
|
|
|
|
|
|
|
|
|
In certain cases, things like Array#sort can result in a confusing error
message. For instance where a and b are characters in a string,
`"string"`:
```ruby
array.sort { |a, b| string.index(a) <=> string.index(b) }
```
If one of the index calls returns nil, we will get "comparison of String
with String failed", which is somewhat unhelpful, since it's easy to be
confused, given that what is really being compared is a Fixnum or
NilClass (the cause of the error). Yes, as far as Array#sort is
concerned, the two characters are the things being sorted, but it's
useful to call attention to the return value of the comparison in this
case.
This patch adds a "reason" argument to rb_cmperr, which will provide an
error message of "comparison of String with String failed: comparator
returned nil" in the case above, or, in the case of:
```ruby
1.upto('10').to_a
```
it will provide the message: "comparison of Fixnum with String failed:
coercion was not possible"
|
|
|
|
|
|
* remove the temporary buffer object.
* simplify the condition under which an extra byte is required for
sign extension.
* in the case of `R`, raise an error earlier before packing for the
negative number.
|
|
Drops C calls to `rb_ivar_get_at_no_ractor_check` out of the stats completely.
Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
|
|
Assume only one box (root box) and invalidate otherwise. Drops C calls to `rb_ivar_get_at_no_ractor_check`.
Before:
```
Top-20 calls to C functions from JIT code (77.3% of total 64,311,573):
rb_vm_opt_send_without_block: 11,939,854 (18.6%)
rb_hash_aref: 5,400,091 ( 8.4%)
rb_vm_invokeblock: 4,453,357 ( 6.9%)
rb_zjit_writebarrier_check_immediate: 4,279,890 ( 6.7%)
rb_vm_getinstancevariable: 3,504,908 ( 5.4%)
rb_vm_send: 3,103,424 ( 4.8%)
rb_ivar_get_at_no_ractor_check: 2,864,766 ( 4.5%)
rb_obj_is_kind_of: 2,313,479 ( 3.6%)
rb_hash_aset: 1,903,359 ( 3.0%)
Hash#fetch: 1,639,937 ( 2.5%)
rb_vm_setinstancevariable: 1,596,791 ( 2.5%)
rb_vm_opt_getconstant_path: 1,328,761 ( 2.1%)
rb_jit_ary_push: 960,563 ( 1.5%)
rb_ec_ary_new_from_values: 722,913 ( 1.1%)
rb_class_allocate_instance: 721,483 ( 1.1%)
fetch: 713,134 ( 1.1%)
rb_str_buf_append: 667,545 ( 1.0%)
rb_ivar_get: 585,817 ( 0.9%)
rb_hash_new_with_size: 520,347 ( 0.8%)
rb_vm_sendforward: 479,029 ( 0.7%)
```
After:
```
Top-20 calls to C functions from JIT code (76.5% of total 62,282,359):
rb_vm_opt_send_without_block: 11,939,850 (19.2%)
rb_hash_aref: 5,400,092 ( 8.7%)
rb_vm_invokeblock: 4,453,357 ( 7.2%)
rb_zjit_writebarrier_check_immediate: 4,279,893 ( 6.9%)
rb_vm_getinstancevariable: 3,504,920 ( 5.6%)
rb_vm_send: 3,103,441 ( 5.0%)
rb_obj_is_kind_of: 2,313,510 ( 3.7%)
rb_hash_aset: 1,903,359 ( 3.1%)
Hash#fetch: 1,639,937 ( 2.6%)
rb_vm_setinstancevariable: 1,596,797 ( 2.6%)
rb_vm_opt_getconstant_path: 1,328,761 ( 2.1%)
rb_jit_ary_push: 960,563 ( 1.5%)
rb_ivar_get_at_no_ractor_check: 835,498 ( 1.3%)
rb_ec_ary_new_from_values: 722,921 ( 1.2%)
rb_class_allocate_instance: 721,492 ( 1.2%)
fetch: 713,135 ( 1.1%)
rb_str_buf_append: 667,545 ( 1.1%)
rb_ivar_get: 585,815 ( 0.9%)
rb_hash_new_with_size: 520,348 ( 0.8%)
rb_vm_sendforward: 479,029 ( 0.8%)
```
The remaining `rb_ivar_get_at_no_ractor_check` are due to TypedData access, mostly on `Thread`.
|
|
If we wan't prism to use the ruby allocator, we should
include it as early as possible.
|
|
Co-Authored-By: Nathan Froyd <froydnj@gmail.com>
|
|
It was never adopted by ruby or other implementations.
Ruby 4.1 may add new directives, so now is a good time to remove it.
It was actually never properly documented (just shows `Prism::Pack` with no methods)
so removing seems safe to do even now.
Ref
* https://github.com/ruby/prism/pull/3909
* https://github.com/ruby/prism/issues/3907
|
|
[Bug #21864]
Co-Authored-By: Benoit Daloze <eregontp@gmail.com>
|
|
|
|
|
|
Followup: https://github.com/ruby/ruby/pull/15989
This feeds the GC with useful allocation metrics, but also ensure
we're correctly keeping track of our allocation sizes which is
beneficial for safety.
It also allows to use C23's `free_sized`.
|
|
`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|
```
|
|
Symbols with a corresponding ID should be pinned because they can be used
by things that don't support compaction.
|
|
T_DATA and T_STRUCT could have ivars but might not use the generic_fields_tbl.
This commit skips lookup in the generic_fields_tbl for those cases.
|
|
Include internal/error.h instead.
|
|
|
|
Since singleton classes are created lazily, we need to make sure that
we lock around their creation. Unfortunately, that means we need to
lock around every shareable object's call to `singleton_class`,
including classes and modules.
|
|
Before this change, GC'ing any Ractor object caused you to lose all
enabled tracepoints across all ractors (even main). Now tracepoints are
ractor-local and this doesn't happen. Internal events are still global.
Fixes [Bug #19112]
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
This is mostly to see what happens to the loops-times benchmark.
|
|
* ZJIT: Add NoSingletonClass patch point
This patch point makes sure that when the object has a singleton class,
the JIT code is invalidated. As of now, this is only needed for C call
optimization.
In YJIT, the singleton class guard only applies to Array, Hash, and String.
But in ZJIT, we may optimize C calls from gems (e.g. `sqlite3`). So the
patch point needs to be applied to a broader range of classes.
* ZJIT: Only generate NoSingletonClass guard when the type can have singleton class
* ZJIT: Update or forget NoSingletonClass patch point when needed
|
|
|
|
|
|
Previously unused.
|
|
Disallow pending interrupts to be checked during `FiberScheduler#unblock`.
Ractors can send signals at any time, so the previous debug assertion
can fail if a Ractor sends a signal.
Co-authored-by: Luke Gruber <luke.gruber@shopify.com>
|