435 Commits
Author SHA1 Message Date
Hiroshi SHIBATAandClaude Opus 5.5 ee3d6c987b Use rb_len_t for the lengths and indices left in long
These still held String and Array lengths and indices in long, or cast them to long. rb_len_t is still long everywhere, so the generated code does not change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:45:25 +09:00
Jean Boussier 522f6ea227 String#tr: take a Hash for multi-character replacements
[Feature #22238]
2026-09-03 13:11:59 +02:00
Jean Boussier 56abc30ec2 Righ-size more hashes
The pattern of allocating an empty hash with `rb_hash_new()` and
then appending to it is relatively wasteful, because every time
we go over the hash capacity, we'll have to `realloc`, rehash etc.

It may even get worse if https://github.com/ruby/ruby/pull/18345
lands, as right now an empty hash starts with a capacity of 8,
but it may very well start with a capacity of 2.

Hence in cases where the final hash size is easy to predict, we
should use `rb_hash_new_capa()`.
2026-08-23 11:50:40 +02:00
Koichi SasadaandClaude Opus 4.8 9be06a4455 encoding.c: use RB_OBJ_SET_SHAREABLE instead of raw FL_SET_RAW
enc_list_update makes the frozen encoding list shareable by setting
RUBY_FL_SHAREABLE directly. Use the public RB_OBJ_SET_SHAREABLE() helper
instead, which is the intended way to mark an object shareable
(rb_obj_set_shareable). No behavioural change on the shared interpreter;
it keeps the encoding-list sharing off the raw-flag path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 18:33:37 +09:00
John HawthornandLuke Gruber daffaaee73 Mark most TypedData types as THREAD_SAFE_FREE
Set RUBY_TYPED_THREAD_SAFE_FREE on TypedData types whose dfree function
is trivially safe, and only frees its own memory

Types not yet marked as THREAD_SAFE_FREE:
- id2ref_tbl_type: sets the process-global id2ref_tbl to NULL.
- mutex_data_type: unlinks itself from another thread's keeping_mutexes list.
- autoload_data_type: deletes nodes from a shared intrusive list.
- autoload_const_type: deletes itself from a shared list.
- rb_cont_data_type: mutates the shared fiber pool and the global first_jit_cont list.
- rb_fiber_data_type: delegates to cont_free.
- FiberPoolDataType: mutates shared fiber pool free-lists.
- ractor_data_type: reconfigures global VM event-hook flags and call caches.
- exported_object_registry: frees a global table under the VM lock.
- rb_box_data_type (Box::Entry): unlinks classext from other live class and module objects.
- box_ext_cleanup_type: dereferences another String object and calls unlink.
- monitor_data_type: uses the default free, so the flag has no effect.

Co-authored-by: Luke Gruber <luke.gruber@shopify.com>
2026-06-23 13:30:26 -07:00
John Hawthorn d901035136 Atomic fast path for "locale" encoding registration
The "locale" encoding is only registered once, so we can use an atomic
to avoid the full lock and hash lookup.
2026-05-29 11:29:43 -07:00
Nobuyoshi Nakada 5497859f40 Remove use of RTYPEDDATA_P and rbimpl_rtypeddata_p 2026-05-28 19:29:32 +09:00
Nobuyoshi Nakada 8ca2f6489b Revert "Fix rb_interned_str: create strings with BINARY (akak ASCII_8BIT) encoding"
This reverts commit 1f3c52dc15.
2026-01-17 13:38:55 +09:00
Jean Boussier 1f3c52dc15 Fix rb_interned_str: create strings with BINARY (akak ASCII_8BIT) encoding
[Bug #21842]

The documentation always stated as much, and it's consistent with the
rb_str_* family of functions.
2026-01-16 22:44:38 +01:00
Nobuyoshi Nakada b27d9353a7 Use is_obj_encoding instead of is_data_encoding
The argument to `is_data_encoding` is assumed to be `T_DATA`.
2025-12-31 23:56:58 +09:00
John Hawthorn 176e384bcf Cache filesystem_encindex 2025-12-12 14:03:37 -08:00
John Hawthorn e7a38b32e0 Store Encoding#name as an attribute
When debugging the fstring table, I found "UTF-8" to be the most common
interned strings in many benchmarks.

We have a fixed, limited number of these strings, so we might as well permanently
cache their fstrings.
2025-12-12 13:53:06 -08:00
John Hawthorn 41ee65899a Always treat encoding as TYPEDDATA
Encodings are RTypedData, not the deprecated RData. Although the
structures are compatible we should use the correct API.
2025-12-10 09:49:18 -08:00
Koichi Sasada bc00c4468e use SET_SHAREABLE
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
2025-10-23 13:08:26 +09:00
John Hawthorn 02d5b8443a Simplify enc_autoload_body
Previously we were looping over the enc_table, but when I added an
assertion the only thing that loop was doing is the equivalent of
ENC_TO_ENCINDEX(base). However we don't even need the index of base.

Instead we should be able to just use the badirectly.
2025-09-19 15:35:15 -07:00
John Hawthorn f048f77c4a Extract enc_load_from_base from enc_register_at
Previously we would sometimes call enc_register_at several times in
order to update the encoding values after the base encoding may have
been loaded.

This updates enc_register_at to only be used via enc_register, when an
actual new encoding at a new index is being registered.

Other callers (which in all cases found the index by the name matching)
now call enc_load_from_base which is only responsibly for loading the
encoding from the base values.
2025-09-19 15:35:15 -07:00
John Hawthorn 7c51ce5ff6 Mark list as frozen and shareable 2025-09-19 15:35:15 -07:00
John Hawthorn 0bb6a8bea4 Avoid racing ruby_encoding_index with base index
Previously when we copied base_encoding on top of the encoding, other
threads could briefly see the name and ruby_encoding_index of the base
encoding.
2025-09-17 16:24:22 -07:00
John Hawthorn 71fa9809a3 Avoid duplicate autoloading of encodings 2025-09-17 16:24:22 -07:00
Luke Gruber 9db54a1a98 Fixes to encoding/transcoding for ractors.
Not all ractor-related encoding issues were fixed by 1afc07e815.
I found more by running my test-all branch with 3 ractors for each test.
2025-08-22 10:49:44 -07:00
Luke Gruber 7c67060dad Fix enc_list across ractors
Calling rb_ary_replace(copy, orig) can modify orig, which is not safe
across ractors because orig is shared (it's the global encoding list).

Hoping to address CI failures such as https://ci.rvm.jp/results/trunk-gc-asserts@ruby-sp2-noble-docker/5890058
2025-08-15 13:25:17 -04:00
Luke Gruber 1afc07e815 Allow encodings to be autoloaded through transcoding functions
Make sure VM lock is not held when calling `load_transcoder_entry`, as
that causes deadlock inside ractors. `String#encode` now works inside
ractors, among others.

Atomic load the rb_encoding_list

Without this, wbcheck would sometimes hit a missing write barrier.

Co-authored-by: John Hawthorn <john.hawthorn@shopify.com>

Hold VM lock when iterating over global_enc_table.names

This st_table can be inserted into at runtime when autoloading
encodings.

minor optimization when calling Encoding.list
2025-08-12 15:19:02 -07:00
Nobuyoshi Nakada 6179cc0118 [DOC] Fill undocumented documents 2025-08-04 02:23:43 +09:00
BurdetteLamar 54a578e72a [DOC] Tweaks for String#encoding 2025-07-23 17:09:33 -04:00
Jean Boussier 8541dec8c4 encoding.c: check for autoload before checking index
Otherwise we may be checking the index while the encoding
is being autoloaded by another ractor.
2025-07-22 12:58:49 +02:00
Jean Boussier 1fb4929ace Make rb_enc_autoload_p atomic
Using `encoding->max_enc_len` as a way to check if the encoding
has been loaded isn't atomic, because it's not atomically set
last.

Intead we can use a dedicated atomic value inside the encoding table.
2025-07-10 17:18:20 +02:00
Jean Boussier 482f4cad82 Autoload encodings on the main ractor
None of the datastructures involved in the require process are
safe to call on a secondary ractor, however when autoloading
encodings, we do so from the current ractor.

So all sorts of corruption can happen when using an autoloaded
encoding for the first time from a secondary ractor.
2025-07-07 12:44:21 +02:00
John Hawthorn 24ac9f11de Revert "Add locks around accesses/modifications to global encodings table"
This reverts commit cf4d37fbc0.
2025-07-03 21:39:10 -07:00
John Hawthorn 50704fe8e6 Revert "Make get/set default internal/external encoding lock-free"
This reverts commit dda5a04f2b.
2025-07-03 21:39:10 -07:00
Luke Gruber dda5a04f2b Make get/set default internal/external encoding lock-free
Also, make sure autoloading of encodings is safe across ractors.
2025-07-03 13:33:10 -07:00
Luke Gruber cf4d37fbc0 Add locks around accesses/modifications to global encodings table
This fixes segfaults and errors of the type "Encoding not found" when
using encoding-related methods and internal encoding c functions across
ractors.

Example of a possible segfault in release mode or assertion error in debug mode:

```ruby
rs = []
100.times do
  rs << Ractor.new do
    "abc".force_encoding(Encoding.list.shuffle.first)
  end
end
while rs.any?
  r, obj = Ractor.select(*rs)
  rs.delete(r)
end
```
2025-07-03 13:33:10 -07:00
Nobuyoshi Nakada fc518fe1ff Delimit the scopes using encoding/symbol tables 2025-05-25 15:22:43 +09:00
Nobuyoshi Nakada b4417ff665 Add Encoding::UNICODE_VERSION constant 2025-04-23 14:14:36 +09:00
Jean Boussier fae86a701e string.c: Directly create strings with the correct encoding
While profiling msgpack-ruby I noticed a very substantial amout of time
spent in `rb_enc_associate_index`, called by `rb_utf8_str_new`.

On that benchmark, `rb_utf8_str_new` is 33% of the total runtime,
in big part because it cause GC to trigger often, but even then
`5.3%` of the total runtime is spent in `rb_enc_associate_index`
called by `rb_utf8_str_new`.

After closer inspection, it appears that it's performing a lot of
safety check we can assert we don't need, and other extra useless
operations, because strings are first created and filled as ASCII-8BIT
and then later reassociated to the desired encoding.

By directly allocating the string with the right encoding, it allow
to skip a lot of duplicated and useless operations.

After this change, the time spent in `rb_utf8_str_new` is down
to `28.4%` of total runtime, and most of that is GC.
2024-11-13 13:32:32 +01:00
Nobuyoshi Nakada 4b065bbe2b Move common code to enc_compatible_latter 2024-10-05 16:06:54 +09:00
Peter ZhuandMatthew Valentine-House 176c4bb3c7 Fix corruption of internal encoding string
[Bug #20598]

Just like [Bug #20595], Encoding#name_list and Encoding#aliases can have
their strings corrupted when Encoding.default_internal is set to nil.

Co-authored-by: Matthew Valentine-House <matt@eightbitraptor.com>
2024-06-27 14:06:40 -04:00
Peter ZhuandMatthew Valentine-House c6a0d03649 Fix corruption of encoding name string
[Bug #20595]

enc_set_default_encoding will free the C string if the encoding is nil,
but the C string can be used by the encoding name string. This will cause
the encoding name string to be corrupted.

Consider the following code:

    Encoding.default_internal = Encoding::ASCII_8BIT
    names = Encoding.default_internal.names
    p names
    Encoding.default_internal = nil
    p names

It outputs:

    ["ASCII-8BIT", "BINARY", "internal"]
    ["ASCII-8BIT", "BINARY", "\x00\x00\x00\x00\x00\x00\x00\x00"]

Co-authored-by: Matthew Valentine-House <matt@eightbitraptor.com>
2024-06-27 09:47:22 -04:00
Jean Boussier 3a7846b1aa Add a hint of ASCII-8BIT being BINARY
[Feature #18576]

Since outright renaming `ASCII-8BIT` is deemed to backward incompatible,
the next best thing would be to only change its `#inspect`, particularly
in exception messages.
2024-04-18 10:17:26 +02:00
Jean Boussier d4f3dcf4df Refactor VM root modules
This `st_table` is used to both mark and pin classes
defined from the C API. But `vm->mark_object_ary` already
does both much more efficiently.

Currently a Ruby process starts with 252 rooted classes,
which uses `7224B` in an `st_table` or `2016B` in an `RArray`.

So a baseline of 5kB saved, but since `mark_object_ary` is
preallocated with `1024` slots but only use `405` of them,
it's a net `7kB` save.

`vm->mark_object_ary` is also being refactored.

Prior to this changes, `mark_object_ary` was a regular `RArray`, but
since this allows for references to be moved, it was marked a second
time from `rb_vm_mark()` to pin these objects.

This has the detrimental effect of marking these references on every
minors even though it's a mostly append only list.

But using a custom TypedData we can save from having to mark
all the references on minor GC runs.

Addtionally, immediate values are now ignored and not appended
to `vm->mark_object_ary` as it's just wasted space.
2024-03-06 15:33:43 -05:00
Peter Zhu c7ce2f537f Fix memory leak in setting encodings
There is a memory leak in Encoding.default_external= and
Encoding.default_internal= because the duplicated name is not freed
when overwriting.

    10.times do
      1_000_000.times do
        Encoding.default_internal = nil
      end

      puts `ps -o rss= -p #{$$}`
    end

Before:

     25664
     41504
     57360
     73232
     89168
    105056
    120944
    136816
    152720
    168576

After:

    9648
    9648
    9648
    9680
    9680
    9680
    9680
    9680
    9680
    9680
2024-01-03 13:31:43 -05:00
6816e8efcf Free everything at shutdown
when the RUBY_FREE_ON_SHUTDOWN environment variable is set, manually free memory at shutdown.

Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
Co-authored-by: Peter Zhu <peter@peterzhu.ca>
2023-12-07 15:52:35 -05:00
Jean Boussier 60c924770d Mark Encoding as Write Barrier protected
It doesn't even have a mark function.
It's only about a hundred objects, but not reason
to scan them every time.
2023-02-07 11:48:57 +01:00
Benoit Daloze 6abe20e87b Remove Encoding#replicate 2023-01-11 13:41:41 +01:00
Koichi Sasada dbf77d420d surpress warning
now `enc_table->list` is not a pointer.
2022-12-16 11:12:37 +09:00
Koichi Sasada ae19ac5b5b fixed encoding table
This reduces global lock acquiring for reading.
https://bugs.ruby-lang.org/issues/18949
2022-12-16 10:04:37 +09:00
Benoit Daloze 6525b6f760 Remove get_actual_encoding() and the dynamic endian detection for dummy UTF-16/UTF-32
* And simplify callers of get_actual_encoding().
* See [Feature #18949].
* See https://github.com/ruby/ruby/pull/6322#issuecomment-1242758474
2022-09-12 14:02:34 +02:00
Benoit Daloze 14bcf69c9c Deprecate Encoding#replicate
* See [Feature #18949].
2022-09-10 19:02:15 +02:00
Takashi Kokubun 5b21e94beb Expand tabs [ci skip]
[Misc #18891]
2022-07-21 09:42:04 -07:00
Jean Boussier d084585f01 Rename ENCINDEX_ASCII to ENCINDEX_ASCII_8BIT
Otherwise it's way too easy to confuse it with US_ASCII.
2022-07-19 08:48:56 +02:00
Burdette Lamar 81741690a0 [DOC] Main doc for encodings moved from encoding.c to doc/encodings.rdoc (#5748)
Main doc for encodings moved from encoding.c to doc/encodings.rdoc
2022-04-01 20:41:04 -05:00