11 Commits
Author SHA1 Message Date
Shugo MaedaandClaude Opus 4.8 cce7041630 [Feature #22097] Add Proc#refined
Add Proc#refined(mod, ...), which returns a new Proc that behaves like
the receiver but with the refinements activated by the given modules in
effect inside its body, without affecting the original Proc.  This is
an alternative to the previously proposed Proc#using
(https://bugs.ruby-lang.org/issues/16461) that does not modify the
existing block and needs no `using Proc::Refinements` declaration.

Refinements are resolved at run time through the cref, so a refined
proc gets two pieces of its own:

* A cref carrying the additional refinements, built by activating the
  modules (rb_using_module_recursive, under the VM lock) on a duplicate
  of the block's captured cref.  It is stored in a hidden ivar on the
  Proc and injected into the block frame on every proc-invocation path
  (Proc#call, yield from C methods, invokeblock/opt_call, and
  instance_eval/instance_exec/module_eval/class_eval via yield_under).
  The captured environment stays shared, so closure variables are still
  shared with the original Proc.  `using` inside the body is rejected
  (CREF_REFINED_PROC), so the cref's refinements never change after
  publication.

* A recursive deep copy of the block's instruction sequences
  (rb_iseq_dup_with_independent_caches) so the new Proc has its own
  inline method caches.  This is required for correctness: the VM
  caches refinement method resolution per call site assuming a single
  lexical cref per iseq, so sharing the iseq would leak the refined
  methods into the original Proc.  Coverage keeps measuring the copied
  iseq.

The copy and the cref are memoized in a hidden identity Hash keyed by
the source iseq (one slot per iseq, matched by the captured cref and
the module arguments, accessed under the VM lock), so repeated calls at
the same site reuse one copy and procs refined with the same modules
share the iseq and the cref.  A differing module set or a ruby2_keywords
flag mismatch rebuilds the entry (with a performance warning).  The
refinements table of the memoized cref is frozen and marked shareable so
the memo also serves other Ractors.

Procs without an iseq block (Symbol#to_proc, C-function procs), procs
created from methods, and procs that already have refinements are
rejected with ArgumentError.

The YJIT/ZJIT Rust bindings are regenerated for the new rb_proc_t field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 15:21:01 +09:00
Shugo MaedaandClaude Fable 5 27793ca83a Remove unused rb_vm_using_module
382645d440 added rb_vm_using_module together with its only caller (the
namespace loader), and 4f47327287 removed that caller when the current
namespace management was reworked, leaving the function unused.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 17:53:17 +09:00
Jean Boussier 07b2356a6a Mutex: avoid repeated calls to GET_EC
That call is surprisingly expensive, so trying doing it once
in `#synchronize` and then passing the EC to lock and unlock
saves quite a few cycles.

Before:

```
ruby 4.0.0dev (2025-12-10T09:30:18Z master c5608ab4d7) +YJIT +PRISM [arm64-darwin25]
Warming up --------------------------------------
               Mutex     1.888M i/100ms
             Monitor     1.633M i/100ms
Calculating -------------------------------------
               Mutex     22.610M (± 0.2%) i/s   (44.23 ns/i) -    113.258M in   5.009097s
             Monitor     19.148M (± 0.3%) i/s   (52.22 ns/i) -     96.366M in   5.032755s
```

After:
```
ruby 4.0.0dev (2025-12-10T10:40:07Z speedup-mutex 1c901cd4f8) +YJIT +PRISM [arm64-darwin25]
Warming up --------------------------------------
               Mutex     2.095M i/100ms
             Monitor     1.578M i/100ms
Calculating -------------------------------------
               Mutex     24.456M (± 0.4%) i/s   (40.89 ns/i) -    123.584M in   5.053418s
             Monitor     19.176M (± 0.1%) i/s   (52.15 ns/i) -     96.243M in   5.018977s
```

Bench:

```
require 'bundler/inline'

gemfile do
  gem "benchmark-ips"
end

mutex = Mutex.new
require "monitor"
monitor = Monitor.new

Benchmark.ips do |x|
  x.report("Mutex") { mutex.synchronize { } }
  x.report("Monitor") { monitor.synchronize { } }
end
```
2025-12-11 23:25:57 +01:00
Samuel WilliamsandSamuel Williams 64f508ade8 Support cause: in Thread#raise and Fiber#raise. (#13967)
* Add support for `cause:` argument to `Fiber#raise` and `Thread#raise`.

The implementation behaviour is consistent with `Kernel#raise` and
`Exception#initialize` methods, allowing the `cause:` argument to be
passed to `Fiber#raise` and `Thread#raise`. This change ensures that
the `cause:` argument is handled correctly, providing a more consistent
and expected behavior when raising exceptions in fibers and threads.

[Feature #21360]

* Shared specs for Fiber/Thread/Kernel raise.

---------

Co-authored-by: Samuel Williams <samuel.williams@shopify.com>
2025-07-24 14:45:43 +12:00
Satoshi Tagomori 382645d440 namespace on read 2025-05-11 23:32:50 +09:00
Nobuyoshi Nakada 58918788ab [Bug #20342] Consider wrapped load in main methods 2024-04-05 01:33:08 +09:00
卜部昌平 daf0c04a47 internal/*.h: skip doxygen
These contents are purely implementation details, not worth appearing in
CAPI documents. [ci skip]
2021-09-10 20:00:06 +09:00
卜部昌平 4ff3f20540 add #include guard hack
According to MSVC manual (*1), cl.exe can skip including a header file
when that:

- contains #pragma once, or
- starts with #ifndef, or
- starts with #if ! defined.

GCC has a similar trick (*2), but it acts more stricter (e. g. there
must be _no tokens_ outside of #ifndef...#endif).

Sun C lacked #pragma once for a looong time.  Oracle Developer Studio
12.5 finally implemented it, but we cannot assume such recent version.

This changeset modifies header files so that each of them include
strictly one #ifndef...#endif.  I believe this is the most portable way
to trigger compiler optimizations. [Bug #16770]

*1: https://docs.microsoft.com/en-us/cpp/preprocessor/once
*2: https://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html
2020-04-13 16:06:00 +09:00
卜部昌平 9e6e39c351 Merge pull request #2991 from shyouhei/ruby.h
Split ruby.h
2020-04-08 13:28:13 +09:00
卜部昌平 bf53d6c7d1 other minior internal header tweaks
These headers need no rewrite.  Just add some minor tweaks, like
addition of #include lines.  Mainly cosmetic.

TIMET_MAX_PLUS_ONE was deleted because the macro was used from only
one place (directly write expression there).
2019-12-26 20:45:12 +09:00
卜部昌平 b739a63eb4 split internal.h into files
One day, I could not resist the way it was written.  I finally started
to make the code clean.  This changeset is the beginning of a series of
housekeeping commits.  It is a simple refactoring; split internal.h into
files, so that we can divide and concur in the upcoming commits.  No
lines of codes are either added or removed, except the obvious file
headers/footers.  The generated binary is identical to the one before.
2019-12-26 20:45:12 +09:00