From 695996c9764d7d49a8e3a87962f2475afb09a25c Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Wed, 3 Jun 2026 08:48:47 +0200 Subject: [PATCH 1/4] [ruby/json] parser.c: noinline `json_eat_comments` Comments shouldn't be present in performance sensitive documents, so it's best not to inline it to make space for more important code. https://github.com/ruby/json/commit/f7fe86ea69 --- ext/json/parser/parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index 503bed1fd477d3..56b214fc42381d 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -529,7 +529,7 @@ static uint32_t unescape_unicode(JSON_ParserState *state, const char *sp, const static const rb_data_type_t JSON_ParserConfig_type; -static void +NOINLINE(static) void json_eat_comments(JSON_ParserState *state) { const char *start = state->cursor; From 8fefa5537c58b80e08e0bb87f6bb6a999519dd95 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Wed, 3 Jun 2026 09:25:51 +0200 Subject: [PATCH 2/4] [ruby/json] Integrate with Ruby 4.1 `ruby_sized_xfree` Ensure that buffer sizes have been properly tracked when running in debug mode, and appease the GC slightly when running in release mode. Ref: https://bugs.ruby-lang.org/issues/21861 https://github.com/ruby/json/commit/90354007ea --- ext/json/fbuffer/fbuffer.h | 4 ++-- ext/json/generator/extconf.rb | 1 + ext/json/json.h | 18 ++++++++++++++++++ ext/json/parser/extconf.rb | 1 + ext/json/parser/parser.c | 6 +++--- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/ext/json/fbuffer/fbuffer.h b/ext/json/fbuffer/fbuffer.h index b84a073554cf8c..b4f5266ca57106 100644 --- a/ext/json/fbuffer/fbuffer.h +++ b/ext/json/fbuffer/fbuffer.h @@ -64,7 +64,7 @@ static inline void fbuffer_consumed(FBuffer *fb, size_t consumed) static void fbuffer_free(FBuffer *fb) { if (fb->ptr && fb->type == FBUFFER_HEAP_ALLOCATED) { - ruby_xfree(fb->ptr); + JSON_SIZED_FREE_N(fb->ptr, fb->capa); } } @@ -88,7 +88,7 @@ static void fbuffer_realloc(FBuffer *fb, size_t required) fb->type = FBUFFER_HEAP_ALLOCATED; MEMCPY(fb->ptr, old_buffer, char, fb->len); } else { - REALLOC_N(fb->ptr, char, required); + JSON_SIZED_REALLOC_N(fb->ptr, char, required, fb->capa); } fb->capa = required; } diff --git a/ext/json/generator/extconf.rb b/ext/json/generator/extconf.rb index 205a887e78f3bd..33af03ea3058f8 100644 --- a/ext/json/generator/extconf.rb +++ b/ext/json/generator/extconf.rb @@ -6,6 +6,7 @@ else append_cflags("-std=c99") have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3 + have_func("ruby_xfree_sized", "ruby.h") # RUBY_VERSION >= 4.1 $defs << "-DJSON_GENERATOR" $defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0" diff --git a/ext/json/json.h b/ext/json/json.h index 8737989a6c9aa6..cf9420d4dd2456 100644 --- a/ext/json/json.h +++ b/ext/json/json.h @@ -49,6 +49,24 @@ typedef unsigned char _Bool; #endif #endif +#ifndef HAVE_RUBY_XFREE_SIZED +static inline void ruby_xfree_sized(void *ptr, size_t oldsize) +{ + ruby_xfree(ptr); +} + +static inline void *ruby_xrealloc2_sized(void *ptr, size_t new_elems, size_t elem_size, size_t old_elems) +{ + return ruby_xrealloc2(ptr, new_elems, elem_size); +} +#endif + +# define JSON_SIZED_REALLOC_N(v, T, m, n) \ + ((v) = (T *)ruby_xrealloc2_sized((void *)(v), (m), sizeof(T), (n))) + +# define JSON_SIZED_FREE(v) ruby_xfree_sized((void *)(v), sizeof(*(v))) +# define JSON_SIZED_FREE_N(v, n) ruby_xfree_sized((void *)(v), sizeof(*(v)) * (n)) + #ifndef HAVE_RB_EXT_RACTOR_SAFE # undef RUBY_TYPED_FROZEN_SHAREABLE # define RUBY_TYPED_FROZEN_SHAREABLE 0 diff --git a/ext/json/parser/extconf.rb b/ext/json/parser/extconf.rb index f12fc2dddce02a..a9d740c7556b5d 100644 --- a/ext/json/parser/extconf.rb +++ b/ext/json/parser/extconf.rb @@ -6,6 +6,7 @@ have_func("rb_str_to_interned_str", "ruby.h") # RUBY_VERSION >= 3.0 have_func("rb_hash_new_capa", "ruby.h") # RUBY_VERSION >= 3.2 have_func("rb_hash_bulk_insert", "ruby.h") # Missing on TruffleRuby +have_func("ruby_xfree_sized", "ruby.h") # RUBY_VERSION >= 4.1 if RUBY_ENGINE == "ruby" have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3 diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index 56b214fc42381d..d0482f68611968 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -211,7 +211,7 @@ static rvalue_stack *rvalue_stack_grow(rvalue_stack *stack, VALUE *handle, rvalu if (stack->type == RVALUE_STACK_STACK_ALLOCATED) { stack = rvalue_stack_spill(stack, handle, stack_ref); } else { - REALLOC_N(stack->ptr, VALUE, required); + JSON_SIZED_REALLOC_N(stack->ptr, VALUE, required, stack->capa); stack->capa = required; } return stack; @@ -250,7 +250,7 @@ static void rvalue_stack_mark(void *ptr) static void rvalue_stack_free_buffer(rvalue_stack *stack) { - ruby_xfree(stack->ptr); + JSON_SIZED_FREE_N(stack->ptr, stack->capa); stack->ptr = NULL; } @@ -260,7 +260,7 @@ static void rvalue_stack_free(void *ptr) if (stack) { rvalue_stack_free_buffer(stack); #ifndef HAVE_RUBY_TYPED_EMBEDDABLE - ruby_xfree(stack); + JSON_SIZED_FREE(stack); #endif } } From 71515f8bfdd8da23b59742f39abac328913e2868 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Wed, 3 Jun 2026 09:45:45 +0200 Subject: [PATCH 3/4] [ruby/json] Coverage: ignore test/* https://github.com/ruby/json/commit/52c9d9bdf2 --- test/json/test_helper.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/json/test_helper.rb b/test/json/test_helper.rb index 24cde4348cdbf7..4c5a91a1926ebe 100644 --- a/test/json/test_helper.rb +++ b/test/json/test_helper.rb @@ -21,6 +21,7 @@ track_files 'lib/**/*.rb' add_filter 'lib/json/truffle_ruby' unless RUBY_ENGINE == 'truffleruby' + add_filter 'test/' end end From 464e5665a4b02760196867406f1291261ea08fbe Mon Sep 17 00:00:00 2001 From: git Date: Wed, 3 Jun 2026 08:30:18 +0000 Subject: [PATCH 4/4] [DOC] Update bundled gems list at 71515f8bfdd8da23b59742f39abac3 --- NEWS.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index b5884b5bdb512d..501b894c67264e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -75,9 +75,9 @@ releases. ### The following default gems are updated. * RubyGems 4.1.0.dev - * 4.0.3 to [v4.0.4][RubyGems-v4.0.4], [v4.0.5][RubyGems-v4.0.5], [v4.0.6][RubyGems-v4.0.6], [v4.0.7][RubyGems-v4.0.7], [v4.0.8][RubyGems-v4.0.8], [v4.0.9][RubyGems-v4.0.9], [v4.0.10][RubyGems-v4.0.10], [v4.0.11][RubyGems-v4.0.11], [v4.0.12][RubyGems-v4.0.12] + * 4.0.3 to [v4.0.4][RubyGems-v4.0.4], [v4.0.5][RubyGems-v4.0.5], [v4.0.6][RubyGems-v4.0.6], [v4.0.7][RubyGems-v4.0.7], [v4.0.8][RubyGems-v4.0.8], [v4.0.9][RubyGems-v4.0.9], [v4.0.10][RubyGems-v4.0.10], [v4.0.11][RubyGems-v4.0.11], [v4.0.12][RubyGems-v4.0.12], [v4.0.13][RubyGems-v4.0.13] * bundler 4.1.0.dev - * 4.0.3 to [v4.0.4][bundler-v4.0.4], [v4.0.5][bundler-v4.0.5], [v4.0.6][bundler-v4.0.6], [v4.0.7][bundler-v4.0.7], [v4.0.8][bundler-v4.0.8], [v4.0.9][bundler-v4.0.9], [v4.0.10][bundler-v4.0.10], [v4.0.11][bundler-v4.0.11], [v4.0.12][bundler-v4.0.12] + * 4.0.3 to [v4.0.4][bundler-v4.0.4], [v4.0.5][bundler-v4.0.5], [v4.0.6][bundler-v4.0.6], [v4.0.7][bundler-v4.0.7], [v4.0.8][bundler-v4.0.8], [v4.0.9][bundler-v4.0.9], [v4.0.10][bundler-v4.0.10], [v4.0.11][bundler-v4.0.11], [v4.0.12][bundler-v4.0.12], [v4.0.13][bundler-v4.0.13] * erb 6.0.4 * 6.0.1 to [v6.0.1.1][erb-v6.0.1.1], [v6.0.2][erb-v6.0.2], [v6.0.3][erb-v6.0.3], [v6.0.4][erb-v6.0.4] * ipaddr 1.2.9 @@ -202,6 +202,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable. [RubyGems-v4.0.10]: https://github.com/rubygems/rubygems/releases/tag/v4.0.10 [RubyGems-v4.0.11]: https://github.com/rubygems/rubygems/releases/tag/v4.0.11 [RubyGems-v4.0.12]: https://github.com/rubygems/rubygems/releases/tag/v4.0.12 +[RubyGems-v4.0.13]: https://github.com/rubygems/rubygems/releases/tag/v4.0.13 [bundler-v4.0.4]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.4 [bundler-v4.0.5]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.5 [bundler-v4.0.6]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.6 @@ -211,6 +212,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable. [bundler-v4.0.10]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.10 [bundler-v4.0.11]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.11 [bundler-v4.0.12]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.12 +[bundler-v4.0.13]: https://github.com/rubygems/rubygems/releases/tag/bundler-v4.0.13 [erb-v6.0.1.1]: https://github.com/ruby/erb/releases/tag/v6.0.1.1 [erb-v6.0.2]: https://github.com/ruby/erb/releases/tag/v6.0.2 [erb-v6.0.3]: https://github.com/ruby/erb/releases/tag/v6.0.3