From 4fa6e9938cfb9458abd876ad4219a6648bfe1c96 Mon Sep 17 00:00:00 2001 From: "NARUSE, Yui" Date: Mon, 17 Nov 2025 21:38:51 +0900 Subject: [PATCH 1/7] strnlen is not used now --- ext/json/parser/extconf.rb | 1 - ext/json/parser/parser.c | 9 --------- 2 files changed, 10 deletions(-) diff --git a/ext/json/parser/extconf.rb b/ext/json/parser/extconf.rb index cda385767c3cc7..079b37382d7bc3 100644 --- a/ext/json/parser/extconf.rb +++ b/ext/json/parser/extconf.rb @@ -6,7 +6,6 @@ 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("strnlen", "string.h") # Missing on Solaris 10 append_cflags("-std=c99") diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index 9df04ce0079fad..2bf3ae0eb38dd6 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -296,15 +296,6 @@ static void rvalue_stack_eagerly_release(VALUE handle) } } - -#ifndef HAVE_STRNLEN -static size_t strnlen(const char *s, size_t maxlen) -{ - char *p; - return ((p = memchr(s, '\0', maxlen)) ? p - s : maxlen); -} -#endif - static int convert_UTF32_to_UTF8(char *buf, uint32_t ch) { int len = 1; From a0ef236678c0e79d2f4ec369d3cbf2095013803b Mon Sep 17 00:00:00 2001 From: "NARUSE, Yui" Date: Mon, 17 Nov 2025 22:30:41 +0900 Subject: [PATCH 2/7] remove old code --- tool/format-release | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/tool/format-release b/tool/format-release index 927a35d58c23de..b7ad74a095c6fd 100755 --- a/tool/format-release +++ b/tool/format-release @@ -30,10 +30,9 @@ class Tarball def gz?; @url.end_with?('.gz'); end def zip?; @url.end_with?('.zip'); end - def bz2?; @url.end_with?('.bz2'); end def xz?; @url.end_with?('.xz'); end - def ext; @url[/(?:zip|tar\.(?:gz|bz2|xz))\z/]; end + def ext; @url[/(?:zip|tar\.(?:gz|xz))\z/]; end def to_md < Date: Mon, 17 Nov 2025 13:02:32 +0100 Subject: [PATCH 3/7] Remove alternation pattern matching handling from the prism compiler Since https://github.com/ruby/ruby/pull/15212 these are proper syntax errors, so no need to handle this explicitly anymore. Also updated the example in the docs for this --- doc/syntax/pattern_matching.rdoc | 2 +- prism_compile.c | 58 ++++++++++++-------------------- 2 files changed, 23 insertions(+), 37 deletions(-) diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc index c43919ba14e5f4..06aae26d498e82 100644 --- a/doc/syntax/pattern_matching.rdoc +++ b/doc/syntax/pattern_matching.rdoc @@ -253,11 +253,11 @@ The "rest" part of a pattern also can be bound to a variable: case {a: 1, b: 2} in {a: } | Array + # ^ SyntaxError (variable capture in alternative pattern) "matched: #{a}" else "not matched" end - # SyntaxError (illegal variable in alternative pattern (a)) Variables that start with _ are the only exclusions from this rule: diff --git a/prism_compile.c b/prism_compile.c index 811ce4781696e7..d3c66691a8325b 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2288,7 +2288,7 @@ pm_compile_index_control_flow_write_node(rb_iseq_t *iseq, const pm_node_t *node, // A forward declaration because this is the recursive function that handles // compiling a pattern. It can be reentered by nesting patterns, as in the case // of arrays or hashes. -static int pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *matched_label, LABEL *unmatched_label, bool in_single_pattern, bool in_alternation_pattern, bool use_deconstructed_cache, unsigned int base_index); +static int pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *matched_label, LABEL *unmatched_label, bool in_single_pattern, bool use_deconstructed_cache, unsigned int base_index); /** * This function generates the code to set up the error string and error_p @@ -2394,10 +2394,10 @@ pm_compile_pattern_eqq_error(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const * label. */ static int -pm_compile_pattern_match(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *unmatched_label, bool in_single_pattern, bool in_alternation_pattern, bool use_deconstructed_cache, unsigned int base_index) +pm_compile_pattern_match(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *unmatched_label, bool in_single_pattern, bool use_deconstructed_cache, unsigned int base_index) { LABEL *matched_label = NEW_LABEL(pm_node_line_number(scope_node->parser, node)); - CHECK(pm_compile_pattern(iseq, scope_node, node, ret, matched_label, unmatched_label, in_single_pattern, in_alternation_pattern, use_deconstructed_cache, base_index)); + CHECK(pm_compile_pattern(iseq, scope_node, node, ret, matched_label, unmatched_label, in_single_pattern, use_deconstructed_cache, base_index)); PUSH_LABEL(ret, matched_label); return COMPILE_OK; } @@ -2544,7 +2544,7 @@ pm_compile_pattern_error_handler(rb_iseq_t *iseq, const pm_scope_node_t *scope_n * Compile a pattern matching expression. */ static int -pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *matched_label, LABEL *unmatched_label, bool in_single_pattern, bool in_alternation_pattern, bool use_deconstructed_cache, unsigned int base_index) +pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *matched_label, LABEL *unmatched_label, bool in_single_pattern, bool use_deconstructed_cache, unsigned int base_index) { const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node); @@ -2604,7 +2604,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t PUSH_INSN(ret, location, dup); PUSH_INSN1(ret, location, putobject, INT2FIX(index)); PUSH_SEND(ret, location, idAREF, INT2FIX(1)); - CHECK(pm_compile_pattern_match(iseq, scope_node, required, ret, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 1)); + CHECK(pm_compile_pattern_match(iseq, scope_node, required, ret, match_failed_label, in_single_pattern, false, base_index + 1)); } if (cast->rest != NULL) { @@ -2617,7 +2617,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t PUSH_SEND(ret, location, idMINUS, INT2FIX(1)); PUSH_INSN1(ret, location, setn, INT2FIX(4)); PUSH_SEND(ret, location, idAREF, INT2FIX(2)); - CHECK(pm_compile_pattern_match(iseq, scope_node, ((const pm_splat_node_t *) cast->rest)->expression, ret, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 1)); + CHECK(pm_compile_pattern_match(iseq, scope_node, ((const pm_splat_node_t *) cast->rest)->expression, ret, match_failed_label, in_single_pattern, false, base_index + 1)); } else if (posts_size > 0) { PUSH_INSN(ret, location, dup); @@ -2637,7 +2637,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t PUSH_INSN1(ret, location, topn, INT2FIX(3)); PUSH_SEND(ret, location, idPLUS, INT2FIX(1)); PUSH_SEND(ret, location, idAREF, INT2FIX(1)); - CHECK(pm_compile_pattern_match(iseq, scope_node, post, ret, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 1)); + CHECK(pm_compile_pattern_match(iseq, scope_node, post, ret, match_failed_label, in_single_pattern, false, base_index + 1)); } PUSH_INSN(ret, location, pop); @@ -2734,7 +2734,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t } PUSH_SEND(ret, location, idAREF, INT2FIX(1)); - CHECK(pm_compile_pattern_match(iseq, scope_node, cast->requireds.nodes[index], ret, next_loop_label, in_single_pattern, in_alternation_pattern, false, base_index + 4)); + CHECK(pm_compile_pattern_match(iseq, scope_node, cast->requireds.nodes[index], ret, next_loop_label, in_single_pattern, false, base_index + 4)); } const pm_splat_node_t *left = cast->left; @@ -2744,7 +2744,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t PUSH_INSN1(ret, location, putobject, INT2FIX(0)); PUSH_INSN1(ret, location, topn, INT2FIX(2)); PUSH_SEND(ret, location, idAREF, INT2FIX(2)); - CHECK(pm_compile_pattern_match(iseq, scope_node, left->expression, ret, find_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 4)); + CHECK(pm_compile_pattern_match(iseq, scope_node, left->expression, ret, find_failed_label, in_single_pattern, false, base_index + 4)); } RUBY_ASSERT(PM_NODE_TYPE_P(cast->right, PM_SPLAT_NODE)); @@ -2757,7 +2757,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t PUSH_SEND(ret, location, idPLUS, INT2FIX(1)); PUSH_INSN1(ret, location, topn, INT2FIX(3)); PUSH_SEND(ret, location, idAREF, INT2FIX(2)); - pm_compile_pattern_match(iseq, scope_node, right->expression, ret, find_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 4); + pm_compile_pattern_match(iseq, scope_node, right->expression, ret, find_failed_label, in_single_pattern, false, base_index + 4); } PUSH_INSNL(ret, location, jump, find_succeeded_label); @@ -2936,7 +2936,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t value = ((const pm_implicit_node_t *) value)->value; } - CHECK(pm_compile_pattern_match(iseq, scope_node, value, match_values, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 1)); + CHECK(pm_compile_pattern_match(iseq, scope_node, value, match_values, match_failed_label, in_single_pattern, false, base_index + 1)); } PUSH_SEQ(ret, match_values); @@ -2964,7 +2964,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t case PM_ASSOC_SPLAT_NODE: { const pm_assoc_splat_node_t *splat = (const pm_assoc_splat_node_t *) cast->rest; PUSH_INSN(ret, location, dup); - pm_compile_pattern_match(iseq, scope_node, splat->value, ret, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 1); + pm_compile_pattern_match(iseq, scope_node, splat->value, ret, match_failed_label, in_single_pattern, false, base_index + 1); break; } default: @@ -3009,8 +3009,8 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t LABEL *match_failed_label = NEW_LABEL(location.line); PUSH_INSN(ret, location, dup); - CHECK(pm_compile_pattern_match(iseq, scope_node, cast->value, ret, match_failed_label, in_single_pattern, in_alternation_pattern, use_deconstructed_cache, base_index + 1)); - CHECK(pm_compile_pattern(iseq, scope_node, (const pm_node_t *) cast->target, ret, matched_label, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index)); + CHECK(pm_compile_pattern_match(iseq, scope_node, cast->value, ret, match_failed_label, in_single_pattern, use_deconstructed_cache, base_index + 1)); + CHECK(pm_compile_pattern(iseq, scope_node, (const pm_node_t *) cast->target, ret, matched_label, match_failed_label, in_single_pattern, false, base_index)); PUSH_INSN(ret, location, putnil); PUSH_LABEL(ret, match_failed_label); @@ -3026,20 +3026,6 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t const pm_local_variable_target_node_t *cast = (const pm_local_variable_target_node_t *) node; pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, cast->name, cast->depth); - // If this local variable is being written from within an alternation - // pattern, then it cannot actually be added to the local table since - // it's ambiguous which value should be used. So instead we indicate - // this with a compile error. - if (in_alternation_pattern) { - ID id = pm_constant_id_lookup(scope_node, cast->name); - const char *name = rb_id2name(id); - - if (name && strlen(name) > 0 && name[0] != '_') { - COMPILE_ERROR(iseq, location.line, "illegal variable in alternative pattern (%"PRIsVALUE")", rb_id2str(id)); - return COMPILE_NG; - } - } - PUSH_SETLOCAL(ret, location, index.index, index.level); PUSH_INSNL(ret, location, jump, matched_label); break; @@ -3055,7 +3041,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t // First, we're going to attempt to match against the left pattern. If // that pattern matches, then we'll skip matching the right pattern. PUSH_INSN(ret, location, dup); - CHECK(pm_compile_pattern(iseq, scope_node, cast->left, ret, matched_left_label, unmatched_left_label, in_single_pattern, true, use_deconstructed_cache, base_index + 1)); + CHECK(pm_compile_pattern(iseq, scope_node, cast->left, ret, matched_left_label, unmatched_left_label, in_single_pattern, use_deconstructed_cache, base_index + 1)); // If we get here, then we matched on the left pattern. In this case we // should pop out the duplicate value that we preemptively added to @@ -3068,7 +3054,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t // If we get here, then we didn't match on the left pattern. In this // case we attempt to match against the right pattern. PUSH_LABEL(ret, unmatched_left_label); - CHECK(pm_compile_pattern(iseq, scope_node, cast->right, ret, matched_label, unmatched_label, in_single_pattern, true, use_deconstructed_cache, base_index)); + CHECK(pm_compile_pattern(iseq, scope_node, cast->right, ret, matched_label, unmatched_label, in_single_pattern, use_deconstructed_cache, base_index)); break; } case PM_PARENTHESES_NODE: @@ -3076,7 +3062,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t // they do nothing since they can only wrap individual expressions and // not groups. In this case we'll recurse back into this same function // with the body of the parentheses. - return pm_compile_pattern(iseq, scope_node, ((const pm_parentheses_node_t *) node)->body, ret, matched_label, unmatched_label, in_single_pattern, in_alternation_pattern, use_deconstructed_cache, base_index); + return pm_compile_pattern(iseq, scope_node, ((const pm_parentheses_node_t *) node)->body, ret, matched_label, unmatched_label, in_single_pattern, use_deconstructed_cache, base_index); case PM_PINNED_EXPRESSION_NODE: // Pinned expressions are a way to match against the value of an // expression that should be evaluated at runtime. This looks like: @@ -3137,7 +3123,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t // looks like: foo in ^@bar. To compile these, we compile the variable // that they hold. const pm_pinned_variable_node_t *cast = (const pm_pinned_variable_node_t *) node; - CHECK(pm_compile_pattern(iseq, scope_node, cast->variable, ret, matched_label, unmatched_label, in_single_pattern, in_alternation_pattern, true, base_index)); + CHECK(pm_compile_pattern(iseq, scope_node, cast->variable, ret, matched_label, unmatched_label, in_single_pattern, true, base_index)); break; } case PM_IF_NODE: @@ -3171,7 +3157,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t statement = cast->statements->body.nodes[0]; } - CHECK(pm_compile_pattern_match(iseq, scope_node, statement, ret, unmatched_label, in_single_pattern, in_alternation_pattern, use_deconstructed_cache, base_index)); + CHECK(pm_compile_pattern_match(iseq, scope_node, statement, ret, unmatched_label, in_single_pattern, use_deconstructed_cache, base_index)); PM_COMPILE_NOT_POPPED(predicate); if (in_single_pattern) { @@ -7878,7 +7864,7 @@ pm_compile_case_match_node(rb_iseq_t *iseq, const pm_case_match_node_t *node, co LABEL *next_pattern_label = NEW_LABEL(pattern_location.line); PUSH_INSN(cond_seq, pattern_location, dup); - pm_compile_pattern(iseq, scope_node, in_node->pattern, cond_seq, body_label, next_pattern_label, in_single_pattern, false, true, 2); + pm_compile_pattern(iseq, scope_node, in_node->pattern, cond_seq, body_label, next_pattern_label, in_single_pattern, true, 2); PUSH_LABEL(cond_seq, next_pattern_label); LABEL_UNREMOVABLE(next_pattern_label); } @@ -8126,7 +8112,7 @@ pm_compile_match_required_node(rb_iseq_t *iseq, const pm_match_required_node_t * // through the in_single_pattern parameter. We also indicate that the // value to compare against is 2 slots from the top of the stack (the // base_index parameter). - pm_compile_pattern(iseq, scope_node, node->pattern, ret, matched_label, unmatched_label, true, false, true, 2); + pm_compile_pattern(iseq, scope_node, node->pattern, ret, matched_label, unmatched_label, true, true, 2); // If the pattern did not match the value, then we're going to compile // in our error handler code. This will determine which error to raise @@ -9815,7 +9801,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *matched_label = NEW_LABEL(location.line); LABEL *unmatched_label = NEW_LABEL(location.line); LABEL *done_label = NEW_LABEL(location.line); - pm_compile_pattern(iseq, scope_node, cast->pattern, ret, matched_label, unmatched_label, false, false, true, 2); + pm_compile_pattern(iseq, scope_node, cast->pattern, ret, matched_label, unmatched_label, false, true, 2); // If the pattern did not match, then compile the necessary instructions // to handle pushing false onto the stack, then jump to the end. From 9de66a8c5150266d9f827a11300cd8bcd4b64d4f Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Mon, 17 Nov 2025 13:43:20 +0100 Subject: [PATCH 4/7] [ruby/prism] Remove now obsolete todos https://github.com/ruby/prism/commit/b00d098f9a --- test/prism/ruby/parser_test.rb | 1 - test/prism/test_helper.rb | 1 - 2 files changed, 2 deletions(-) diff --git a/test/prism/ruby/parser_test.rb b/test/prism/ruby/parser_test.rb index 1629c36b382b53..648c44e77a6573 100644 --- a/test/prism/ruby/parser_test.rb +++ b/test/prism/ruby/parser_test.rb @@ -172,7 +172,6 @@ def test_non_prism_builder_class_deprecated if RUBY_VERSION >= "3.3" def test_current_parser_for_current_ruby major, minor = current_major_minor.split(".") - return if major == "3" && minor == "5" # TODO: Remove once ruby-dev becomes 4.0 # Let's just hope there never is a Ruby 3.10 or similar expected = major.to_i * 10 + minor.to_i assert_equal(expected, Translation::ParserCurrent.new.version) diff --git a/test/prism/test_helper.rb b/test/prism/test_helper.rb index c03f70b2cdab18..42555738cf318f 100644 --- a/test/prism/test_helper.rb +++ b/test/prism/test_helper.rb @@ -256,7 +256,6 @@ def current_major_minor if RUBY_VERSION >= "3.3.0" def test_all_syntax_versions_present - return if RUBY_VERSION.start_with?("3.5") # TODO: Remove once ruby-dev becomes 4.0 assert_include(SYNTAX_VERSIONS, current_major_minor) end end From 371a295e190f5b1191400a6ed6944e85ed035598 Mon Sep 17 00:00:00 2001 From: Luke Gruber Date: Wed, 12 Nov 2025 12:51:47 -0500 Subject: [PATCH 5/7] Fix improper termlen fill in `str_duplicate_setup_embed`. When term len != 1 (for example: Encoding::UTF32BE), term fill is wrong size. --- string.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/string.c b/string.c index 5c4e15c4a10384..827555d9e0faab 100644 --- a/string.c +++ b/string.c @@ -1935,8 +1935,8 @@ str_duplicate_setup_embed(VALUE klass, VALUE str, VALUE dup) long len = RSTRING_LEN(str); RUBY_ASSERT(STR_EMBED_P(dup)); - RUBY_ASSERT(str_embed_capa(dup) >= len + 1); - MEMCPY(RSTRING(dup)->as.embed.ary, RSTRING(str)->as.embed.ary, char, len + 1); + RUBY_ASSERT(str_embed_capa(dup) >= len + TERM_LEN(str)); + MEMCPY(RSTRING(dup)->as.embed.ary, RSTRING(str)->as.embed.ary, char, len + TERM_LEN(str)); STR_SET_LEN(dup, RSTRING_LEN(str)); return str_duplicate_setup_encoding(str, dup, flags); } From f9e31f4307b23fe3dbb857f589350cde79155abd Mon Sep 17 00:00:00 2001 From: Sander Verdonschot Date: Fri, 14 Nov 2025 18:22:20 -0500 Subject: [PATCH 6/7] [ruby/time] Defer default year for zone_offset until needed While parsing ISO 8601 timestamps like `2025-11-13T19:34:23.681726000Z` I noticed that a lot of time was spent to compute a default `year` argument to `zone_offset`. For ISO 8601, that year is never used, as all valid time zone designators match one of the earlier cases. This commit moves the computation of the default `year` value to just before it is used. This results in a 15% speedup parsing ISO 8601 timestamps on Mac OS X. https://github.com/ruby/time/commit/4a0bcbe575 --- lib/time.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/time.rb b/lib/time.rb index a0fc7dfbf5d300..14bfe4c8fbc43b 100644 --- a/lib/time.rb +++ b/lib/time.rb @@ -80,7 +80,7 @@ class << Time # # You must require 'time' to use this method. # - def zone_offset(zone, year=self.now.year) + def zone_offset(zone, year=nil) off = nil zone = zone.upcase if /\A([+-])(\d\d)(:?)(\d\d)(?:\3(\d\d))?\z/ =~ zone @@ -89,10 +89,13 @@ def zone_offset(zone, year=self.now.year) off = zone.to_i * 3600 elsif ZoneOffset.include?(zone) off = ZoneOffset[zone] * 3600 - elsif ((t = self.local(year, 1, 1)).zone.upcase == zone rescue false) - off = t.utc_offset - elsif ((t = self.local(year, 7, 1)).zone.upcase == zone rescue false) - off = t.utc_offset + else + year ||= self.now.year + if ((t = self.local(year, 1, 1)).zone.upcase == zone rescue false) + off = t.utc_offset + elsif ((t = self.local(year, 7, 1)).zone.upcase == zone rescue false) + off = t.utc_offset + end end off end From c0256d1d5d397991e4f2dec6359339f406aa3dd8 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Mon, 17 Nov 2025 18:41:26 +0000 Subject: [PATCH 7/7] [DOC] Update GC.stat and GC.stat_heap documentation I noticed some of the keys have been gone or renamed for a while. --- gc.rb | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/gc.rb b/gc.rb index f5e62eed6058fa..f944c653b5b467 100644 --- a/gc.rb +++ b/gc.rb @@ -193,7 +193,10 @@ def self.count # - +:time+: # The total time spent in garbage collections (in milliseconds). # - +:heap_allocated_pages+: - # The total number of +:heap_eden_pages+ + +:heap_tomb_pages+. + # The total number of allocated pages. + # - +:heap_empty_pages+: + # - +:heap_allocated_pages+: + # The number of pages with no live objects, and that could be released to the system. # - +:heap_sorted_length+: # The number of pages that can fit into the buffer that holds references to all pages. # - +:heap_allocatable_pages+: @@ -210,8 +213,6 @@ def self.count # The total number of objects marked in the last \GC. # - +:heap_eden_pages+: # The total number of pages which contain at least one live slot. - # - +:heap_tomb_pages+: - # The total number of pages which do not contain any live slots. # - +:total_allocated_pages+: # The cumulative number of pages allocated since application start. # - +:total_freed_pages+: @@ -374,11 +375,6 @@ def self.stat hash_or_key = nil # The number of pages in the eden heap. # - +:heap_eden_slots+: # The total number of slots in all of the pages in the eden heap. - # - +:heap_tomb_pages+: - # The number of pages in the tomb heap. The tomb heap only contains pages - # that do not have any live objects. - # - +:heap_tomb_slots+: - # The total number of slots in all of the pages in the tomb heap. # - +:total_allocated_pages+: # The total number of pages that have been allocated in the heap. # - +:total_freed_pages+: