1562 Commits
Author SHA1 Message Date
Jeremy Evans f4b7cc8161 Keep a superclass-keyed WeakMap for refinements module iclasses
This avoids allocating a new set of refinement module iclasses if we
have an existing set for the same superclass.  This uses a WeakMap
to avoid leaking memory when creating and using an arbitrary number
of classes including a refined module.

Add tests for using the same refinement with a large number of
classes including the refined module, as well as using a large
number of refinements with the same superclass.
2026-10-10 01:14:57 -07:00
John Hawthorn 73055acd57 Forbid setting ivars on Ractor shareable objects
Previously we had a check that objects which were shareable, but not
frozen on a non-main Ractor would raise an exception if instance
variables were read. This prevented a non-main Ractor reading
non-shareable objects.

This changes the behaviour to forbid all writes to shareable objects
(even when unfrozen). This is done by re-purposing the frozen flag on
the object shape to reflect (FL_FROZEN || FL_SHAREABLE).

With IV writes forbidden on all shareable objects whether or not they
are frozen (with the exception of classes and modules), we can also
remove the check against reading instance variables, since no unsafe
instance variables can be set.

[Bug #22291]
2026-09-16 12:26:11 -07:00
Yusuke Endoh dac86d0d35 Remove the dependency from internal/cont.h to prism. (#13984) 2026-09-12 08:11:50 +00:00
Koichi SasadaandClaude Fable 5 2e5bf429e4 Ractor: restrict class/module modification to the creator Ractor
Only the Ractor which created a class/module may modify it: define, remove or
undefine methods, alias, include/prepend, refine, define or remove constants,
register an autoload, and set the class's own instance variables.  Reading is
unchanged.  This replaces the assorted "main Ractor only" rules with one
creator-based rule, and in exchange a Ractor gets full use of the classes it
creates itself -- unshareable constant and instance variable values included,
which even the main Ractor could not do for its own classes before.

Three paths reach a class's tables without going through rb_class_modify_check,
so they get the check of their own: Module#refine (which writes its refinement
tables into the receiver as well as into the refined class), Class#initialize
(which writes the superclass of a not-yet-initialized class, and had no frozen
check either), and Module#ruby2_keywords.

The constant inline cache has to move with the rule.  Its hit condition was
"shareable value, or we are the main Ractor", which was sound only because a
non-main Ractor could not have an unshareable constant in the first place.  Now
it can, so an owner priming the cache would let any other Ractor read that value
straight out of it, never reaching the owner check in vm_get_ev_const.  The
entry records the Ractor which filled it instead -- the one that passed the
check -- which also gives a non-main owner a fast path it never had.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 16:02:03 +09:00
Luke Gruber 3a0ec78790 Don't create CCs for hook methods called from C
Calling these hook methods shouldn't create CCs because these are not hot methods.
These CCs were only looked up in the gccct table (global call cache lookup table)
for rb_funcall and friends.

For one of our apps after bootup we reduced CCs significantly:

|                       | A control  | B (your commit) | B − A                 |
|-----------------------|------------|-----------------|-----------------------|
| callcaches (after GC) | 705,957    | 651,747         | −54,210 (−7.7%)       |
| cc tables             | 46,361     | 43,051          | −3,310                |
| total cc memory       | 86,441,345 | 79,823,142      | −6,618,203 (−6.3 MB)  |
2026-09-04 10:33:08 -04:00
Hiroshi SHIBATAandClaude Opus 5 b81e0d4888 Set the long path bit for embedded interpreters too
`rb_w32_sysinit` is documented as being for `ruby(1)`, so a program which embeds libruby may skip it and keep the 260 character limit while `ruby.exe` does not. Call the same initialization from `ruby_setup`, which every embedder reaches through `ruby_init`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 16:31:10 +09:00
Shugo MaedaandClaude Fable 5 79d4e720f8 Make locals read after longjmp volatile in more setjmp users
Audit of every EC_PUSH_TAG user, following the LLVM 19 longjmp
rematerialization bug worked around in rb_fiber_start: locals and
arguments that are read on the longjmp path but not modified inside
the tag region are made volatile.  C99 7.13.2.1p3 guarantees such
unmodified locals, but LLVM 17 and 19 have been observed to
reconstruct their values incorrectly after a longjmp (cfp in
rb_iterate0, fiber in rb_fiber_start).  volatile on a parameter may
not be effective (67d0f4821f,
https://bugs.ruby-lang.org/issues/19145), so arguments are copied
into volatile locals instead.

* vm_eval.c (rb_iterate0): cfp is compared against the escaping
  frame after a longjmp; clang 17 at -O1 with -fPIC was observed to
  clobber it during the development of the ifunc invalidation for
  https://bugs.ruby-lang.org/issues/22019.  ec is read next to it to
  rewind the frame and to rethrow.

* eval_error.c (rb_ec_error_print_detailed0): opt and highlight are
  read on the path reached by a longjmp from rb_get_backtrace while
  the other locals of the function are already volatile.

* scheduler.c (rb_fiber_scheduler_unblock, fiber_interrupt): ec and
  saved_interrupt_mask are read after a longjmp to restore
  ec->interrupt_mask; cfp next to them was already volatile.

* eval.c (rb_vrescue2): r_proc and data2 are used when the raise is
  handled.  args is left as is; a va_list cannot portably be
  volatile-qualified and is memory-backed in practice.

* eval.c (rb_protect): pstate is written through after the tag is
  popped.

* eval.c (rb_ec_ensure): ec, e_proc and data2 run the ensure proc
  after a longjmp; a clobbered e_proc would miscall it.

* vm_eval.c (vm_catch_protect): stateptr is written through after
  the pop.  tag has its address taken and stays in memory.

* vm_trace.c (exec_hooks_protected): ec and list are passed to
  exec_hooks_postcheck after the pop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 10:37:13 +09:00
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
Nobuyoshi Nakada 0d7e50a174 [Bug #22191] Report EXIT handler exceptions after END blocks
Keep exceptions raised by `EXIT` traps until `END` handlers finish.
That leaves them available for reporting during cleanup.

Print `END` handler exceptions without replaying causes already
reported from earlier exit handlers. This keeps the previous handler
exception visible while avoiding duplicate diagnostics.
2026-07-13 04:22:19 +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
Satoshi Tagomori 276f0d9b3e [Bug #21881] Separate the master and root box
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.
2026-05-10 09:38:45 +09:00
dak2 d4727cd4e6 Ruby::Box fix stale cached values for exception-related global variables ($! and $@)
Ruby::Box fix stale cached values for exception-related global variables ($! and $@)

The exception-related virtual variables $! (current exception) and
$@ (its backtrace) are stored on the execution context (ec->errinfo
and the rescue/ensure frame's local slot accessed via errinfo_place),
not in box->gvar_tbl. Caching their values in box->gvar_tbl makes the
second read return a stale value from the previous raise/rescue:

```
begin; raise "first";  rescue; p $!; end
begin; raise "second"; rescue; p $!; end
# before: #<RuntimeError: first> / #<RuntimeError: first>
# after:  #<RuntimeError: first> / #<RuntimeError: second>
```

```
begin; raise "first";  rescue; p $@.first; end
begin; raise "second"; rescue; p $@.first; end
# before: same backtrace returned for both
# after:  distinct backtrace per raise
```

Fixes [Bug #21991](https://bugs.ruby-lang.org/issues/21991)
Related PR: https://github.com/ruby/ruby/pull/16303
2026-05-08 09:21:29 +09:00
Takashi Kokubun ee60b99b2f Rename rb_cfp_iseq to CFP_ISEQ and rb_cfp_pc to CFP_PC
Rename for consistency with ISEQ_BODY naming convention. Remove the
separate rb_cfp_has_iseq/rb_cfp_has_pc wrappers — CFP_ISEQ and CFP_PC
return NULL for missing values, which works directly in if conditions.
2026-03-27 16:26:12 -07:00
Takashi Kokubun 226f37059e Rename cfp->iseq to cfp->_iseq and rb_zjit_cfp_iseq to rb_cfp_iseq
Per tenderlove's review, every cfp->iseq read should go through an
accessor that accounts for JITFrame. Rename the field to _iseq so
direct access causes a compile error, and rename the accessors to
drop the zjit prefix (rb_cfp_iseq, rb_cfp_has_iseq, rb_cfp_pc,
rb_cfp_has_pc).
2026-03-27 16:26:12 -07:00
Takashi KokubunandAlan Wu c8f97943ef ZJIT: Lightweight Frames
Co-authored-by: Alan Wu <alanwu@ruby-lang.org>
2026-03-27 16:26:12 -07:00
John Hawthorn a2531ba293 Simplify subclasses list, remove from Box
Currently we maintain the subclasses list for two separate purposes (we essentially have to different relationships we're putting into the same list):

1. On a T_MODULE, we track the T_ICLASSes created to include it into
   other classes. Used for method invalidation and propagating includes
   on the module that happen after it's been used
2. On a T_CLASS/T_ICLASS, we track the T_CLASS/T_ICLASS which are the
   immediate children of the class. We use this for method invalidation,
   some cvar things, and to iterate through subclasses.

Purpose 1 does not have any issues with box, the T_ICLASS always belongs
to one specific module and that's immutable. This list can be box-global
(always use the prime classext or hoist it out) and only needs to be
pruned during free. If we care about behaviour under a particular box
(ie. the propagating includes), we should look up the current box being
modified on the ICLASS itself.

Purpose 2 is more complicated. It currently tracks the immediate
children, the T_CLASS or T_ICLASS whose super points back. Because super
is per-box and is mutable (include/prepend insert ICLASSes into the
chain) we need to update the list on include/prepend, entries must be
per-box, and we can have multiple entries per-box. *I propose we
simplify this by no longer tracking the immediate subclass*, but instead
tracking the T_CLASS -> ... -> T_CLASS relationship, ie. the inverse of
rb_class_superclass. That relationship is the same across all boxes and
immutable after Class creation.

As a special case the ICLASS for refinements are also added to the
purpose 2 list (on T_CLASS). As those ICLASS do not chain to an eventual
leaf T_CLASS.

When we need to find the classes which have included a module, we can
use the module subclasses list to find the ICLASS and then use
RCLASS_INCLUDER. If we needed to iterate all T_ICLASS, we could then
walk up the CLASS_SUPER chain, but I didn't find anywhere we needed to
do that.
2026-03-17 14:42:07 -07:00
BurdetteLamar b7102933ee [DOC] Doc for Module.nesting 2026-01-26 17:07:53 -05:00
Victor Shepelev ec4ca91319 Small documentation adjustments for new/updated features (#15634)
* Document Range#to_set

* Update Thread#raise and Fiber#raise signatures and docs

* Add reference to String#strip to character_selectors.rdoc

* Update *nil docs when calling methods

* Enhance Array#find and #rfind docs

* Add a notice to Kernel#raise about cause:
2025-12-20 13:07:38 +02: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
Jeremy Evans e436dba9fe Use rb_error_frozen_object in rb_class_modify_check
This provides information on the class of the frozen object. It also
results in a much simpler implementation.

Fixes [Bug #21374]
2025-12-10 07:35:50 +09:00
Satoshi Tagomori d2a587c791 renaming internal data structures and functions from namespace to box 2025-11-07 13:14:54 +09:00
Satoshi Tagomori 4f47327287 Update current namespace management by using control frames and lexical contexts
to fix inconsistent and wrong current namespace detections.

This includes:
* Moving load_path and related things from rb_vm_t to rb_namespace_t to simplify
  accessing those values via namespace (instead of accessing either vm or ns)
* Initializing root_namespace earlier and consolidate builtin_namespace into root_namespace
* Adding VM_FRAME_FLAG_NS_REQUIRE for checkpoints to detect a namespace to load/require files
* Removing implicit refinements in the root namespace which was used to determine
  the namespace to be loaded (replaced by VM_FRAME_FLAG_NS_REQUIRE)
* Removing namespaces from rb_proc_t because its namespace can be identified by lexical context
* Starting to use ep[VM_ENV_DATA_INDEX_SPECVAL] to store the current namespace when
  the frame type is MAGIC_TOP or MAGIC_CLASS (block handlers don't exist in this case)
2025-09-29 01:15:38 +09: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
Jean Boussier 393e9a5f3e Optimize rb_namespace_available
Rather than to lazily check the env using a trinary
value, we can more straightforwardly check for the
env during the VM boot.

This allow `rb_namespace_available` to just be a pointer
dereference.
2025-06-23 10:04:58 +01:00
John Hawthorn d1343e12d2 Use flag for RCLASS_IS_INITIALIZED
Previously we used a flag to set whether a module was uninitialized.
When checked whether a class was initialized, we first had to check that
it had a non-zero superclass, as well as that it wasn't BasicObject.

With the advent of namespaces, RCLASS_SUPER is now an expensive
operation, and though we could just check for the prime superclass, we
might as well take this opportunity to use a flag so that we can perform
the initialized check with as few instructions as possible.

It's possible in the future that we could prevent uninitialized classes
from being available to the user, but currently there are a few ways to
do that.
2025-05-28 11:44:07 -04:00
Jean BoussierandJohn Hawthorn 60ffb714d2 Ensure shape_id is never used on T_IMEMO
It doesn't make sense to set ivars or anything shape
related on a T_IMEMO.

Co-Authored-By: John Hawthorn <john@hawthorn.email>
2025-05-15 16:06:52 +02:00
Satoshi Tagomori 382645d440 namespace on read 2025-05-11 23:32:50 +09:00
John Hawthorn 57b6a7503f Lock-free hash set for fstrings [Feature #21268]
This implements a hash set which is wait-free for lookup and lock-free
for insert (unless resizing) to use for fstring de-duplication.

As highlighted in https://bugs.ruby-lang.org/issues/19288, heavy use of
fstrings (frozen interned strings) can significantly reduce the
parallelism of Ractors.

I tried a few other approaches first: using an RWLock, striping a series
of RWlocks (partitioning the hash N-ways to reduce lock contention), and
putting a cache in front of it. All of these improved the situation, but
were unsatisfying as all still required locks for writes (and granular
locks are awkward, since we run the risk of needing to reach a vm
barrier) and this table is somewhat write-heavy.

My main reference for this was Cliff Click's talk on a lock free
hash-table for java https://www.youtube.com/watch?v=HJ-719EGIts. It
turns out this lock-free hash set is made easier to implement by a few
properties:

 * We only need a hash set rather than a hash table (we only need keys,
   not values), and so the full entry can be written as a single VALUE
 * As a set we only need lookup/insert/delete, no update
 * Delete is only run inside GC so does not need to be atomic (It could
   be made concurrent)
 * I use rb_vm_barrier for the (rare) table rebuilds (It could be made
   concurrent) We VM lock (but don't require other threads to stop) for
   table rebuilds, as those are rare
 * The conservative garbage collector makes deferred replication easy,
   using a T_DATA object

Another benefits of having a table specific to fstrings is that we
compare by value on lookup/insert, but by identity on delete, as we only
want to remove the exact string which is being freed. This is faster and
provides a second way to avoid the race condition in
https://bugs.ruby-lang.org/issues/21172.

This is a pretty standard open-addressing hash table with quadratic
probing. Similar to our existing st_table or id_table. Deletes (which
happen on GC) replace existing keys with a tombstone, which is the only
type of update which can occur. Tombstones are only cleared out on
resize.

Unlike st_table, the VALUEs are stored in the hash table itself
(st_table's bins) rather than as a compact index. This avoids an extra
pointer dereference and is possible because we don't need to preserve
insertion order. The table targets a load factor of 2 (it is enlarged
once it is half full).
2025-04-18 13:03:54 +09:00
Nobuyoshi Nakada 4a67ef09cc [Feature #21116] Extract RJIT as a third-party gem 2025-02-13 18:01:03 +09:00
Victor Shepelev 58460b4dbd [DOC] Adjust documentation related to backtraces (#12420) 2024-12-24 20:49:55 +02:00
Shugo Maeda 7ed027a833 Remove deprecated method Refinement#refined_class
[Feature #20901]
2024-11-19 14:33:38 +09:00
OKURA Masafumi 511925f99b [ci-skip] Fix doc for refinements
The current doc is partially wrong since `refinements` method
returns an array of `Refinement` class, not `Module`.
I'm not sure if it's right to link to `Refinement`, but it has
some documentation so it should be useful.
https://docs.ruby-lang.org/en/3.2/Refinement.html
2024-09-20 19:26:37 +09:00
Yusuke Endoh ac5ac48a36 Revert 28a1c4f33e
28a1c4f33e seems to call an improper
ensure clause. [Bug #20655]
Than fixing it properly, I bet it would be much better to simply revert
that commit. It reduces the unneeded complexity. Jumping into a block
called by a C function like Hash#each with callcc is user's fault.
It does not need serious support.
2024-07-30 15:31:24 +09:00
Peter Zhu 51bd816517 [Feature #20470] Split GC into gc_impl.c
This commit splits gc.c into two files:

- gc.c now only contains code not specific to Ruby GC. This includes
  code to mark objects (which the GC implementation may choose not to
  use) and wrappers for internal APIs that the implementation may need
  to use (e.g. locking the VM).

- gc_impl.c now contains the implementation of Ruby's GC. This includes
  marking, sweeping, compaction, and statistics. Most importantly,
  gc_impl.c only uses public APIs in Ruby and a limited set of functions
  exposed in gc.c. This allows us to build gc_impl.c independently of
  Ruby and plug Ruby's GC into itself.
2024-07-03 09:03:40 -04:00
Burdette Lamar 43d7db3828 [DOC] Doc for exceptions (#11008) 2024-06-26 13:31:40 -04:00
Nobuyoshi Nakada 58918788ab [Bug #20342] Consider wrapped load in main methods 2024-04-05 01:33:08 +09:00
Matt Valentine-HouseandPeter Zhu ef19234b10 Merge rb_objspace_alloc and Init_heap.
Co-Authored-By: Peter Zhu <peter@peterzhu.ca>
2024-04-04 15:00:57 +01:00
Takashi Kokubun cbcb2d46fc [DOC] Unify Doxygen formats (#10285) 2024-03-19 10:59:25 -07:00
Jean Boussier 8a8df49174 Update set_backtrace documentation
Followup: https://github.com/ruby/ruby/pull/10017

[Feature #13557]
2024-03-18 08:55:46 +01:00
Nobuyoshi Nakada 28a2105a55 Prefer enum ruby_tag_type over int 2024-03-17 15:57:19 +09:00
Jean Boussier b4a69351ec Move FL_SINGLETON to FL_USER1
This frees FL_USER0 on both T_MODULE and T_CLASS.

Note: prior to this, FL_SINGLETON was never set on T_MODULE,
so checking for `FL_SINGLETON` without first checking that
`FL_TYPE` was `T_CLASS` was valid. That's no longer the case.
2024-03-06 13:11:41 -05:00
Shugo Maeda d50f9ca2dd [Bug #20302] Multiple refinements cannot be applied to the same module
In the following code, the iclass tree of refinements in cref should be <iclass of Kernel@M2> -> <iclass of Kernel@M1> -> Kernel.

However, the iclass tree was broken because of code for included modules of refinements in rb_using_refinement().
Refinement#include is now removed, so this commit removes such unnecessary code.

```ruby
module M1
  refine(Kernel) do
    def f1 = :f1
  end
end

module M2
  refine(Kernel) do
    def f2 = :f2
  end
end

class Foo
  using M1
  using M2

  def test
    p f2 #=> :f2

    p f1 # expected => :f1
         # actual => undefined local variable or method 'f1' for an instance of Foo
  end
end

Foo.new.test
```
2024-02-27 14:51:04 +09:00
Nobuyoshi Nakada d597335c6d Remove unused variable
It was used only in old `SAVE_ROOT_JMPBUF`, and the warning was
suppressed by this macro.
2024-02-22 20:18:49 +09:00
Samuel Williams 6a0b05f413 Remove SAVE_ROOT_JMPBUF as it no longer has any effect. (#10066) 2024-02-22 22:35:54 +13:00
Yusuke Endoh 25d74b9527 Do not include a backtick in error messages and backtraces
[Feature #16495]
2024-02-15 18:42:31 +09:00
KJ Tsanaktsidis 807714447e Pass down "stack start" variables from closer to the top of the stack
This commit changes how stack extents are calculated for both the main
thread and other threads. Ruby uses the address of a local variable as
part of the calculation for machine stack extents:

* pthreads uses it as a lower-bound on the start of the stack, because
  glibc (and maybe other libcs) can store its own data on the stack
  before calling into user code on thread creation.
* win32 uses it as an argument to VirtualQuery, which gets the extent of
  the memory mapping which contains the variable

However, the local being used for this is actually too low (too close to
the leaf function call) in both the main thread case and the new thread
case.

In the main thread case, we have the `INIT_STACK` macro, which is used
for pthreads to set the `native_main_thread->stack_start` value. This
value is correctly captured at the very top level of the program (in
main.c). However, this is _not_ what's used to set the execution context
machine stack (`th->ec->machine_stack.stack_start`); that gets set as
part of a call to `ruby_thread_init_stack` in `Init_BareVM`, using the
address of a local variable allocated _inside_ `Init_BareVM`. This is
too low; we need to use a local allocated closer to the top of the
program.

In the new thread case, the lolcal is allocated inside
`native_thread_init_stack`, which is, again, too low.

In both cases, this means that we might have VALUEs lying outside the
bounds of `th->ec->machine.stack_{start,end}`, which won't be marked
correctly by the GC machinery.

To fix this,

* In the main thread case: We already have `INIT_STACK` at the right
  level, so just pass that local var to `ruby_thread_init_stack`.
* In the new thread case: Allocate the local one level above the call to
  `native_thread_init_stack` in `call_thread_start_func2`.

[Bug #20001]

fix
2024-01-19 09:55:12 +11:00
KJ Tsanaktsidis 396e94666b Revert "Pass down "stack start" variables from closer to the top of the stack"
This reverts commit 4ba8f0dc99.
2024-01-12 17:58:54 +11:00
KJ Tsanaktsidis 4ba8f0dc99 Pass down "stack start" variables from closer to the top of the stack
The implementation of `native_thread_init_stack` for the various
threading models can use the address of a local variable as part of the
calculation of the machine stack extents:

* pthreads uses it as a lower-bound on the start of the stack, because
  glibc (and maybe other libcs) can store its own data on the stack
  before calling into user code on thread creation.
* win32 uses it as an argument to VirtualQuery, which gets the extent of
  the memory mapping which contains the variable

However, the local being used for this is actually allocated _inside_
the `native_thread_init_stack` frame; that means the caller might
allocate a VALUE on the stack that actually lies outside the bounds
stored in machine.stack_{start,end}.

A local variable from one level above the topmost frame that stores
VALUEs on the stack must be drilled down into the call to
`native_thread_init_stack` to be used in the calculation. This probably
doesn't _really_ matter for the win32 case (they'll be in the same
memory mapping so VirtualQuery should return the same thing), but
definitely could matter for the pthreads case.

[Bug #20001]
2024-01-12 17:29:48 +11:00
S.H a6ba45e9b0 Remove unnecessary semicolons (#9469) 2024-01-10 16:21:55 -08:00
Peter Zhu 0d2ca33404 [DOC] Fix link to untrace_var from trace_var 2023-12-30 22:13:24 -05:00