Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/zjit-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
fail-fast: false
matrix:
include:
- test_task: 'zjit-test'
- test_task: 'zjit-check'
configure: '--enable-yjit=dev --enable-zjit'

- test_task: 'ruby' # build test for combo build
Expand Down Expand Up @@ -84,7 +84,7 @@ jobs:
- uses: taiki-e/install-action@v2
with:
tool: nextest@0.9
if: ${{ matrix.test_task == 'zjit-test' }}
if: ${{ matrix.test_task == 'zjit-check' }}

- name: Install Rust # TODO(alan): remove when GitHub images catch up past 1.85.0
run: rustup default 1.85.0
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/zjit-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
configure: '--enable-zjit=dev --with-gcc=clang-14'
libclang_path: '/usr/lib/llvm-14/lib/libclang.so.1'

- test_task: 'zjit-test'
- test_task: 'zjit-check'
configure: '--enable-yjit --enable-zjit=dev'

- test_task: 'zjit-test-all'
Expand Down Expand Up @@ -85,7 +85,7 @@ jobs:
- uses: taiki-e/install-action@v2
with:
tool: nextest@0.9
if: ${{ matrix.test_task == 'zjit-test' }}
if: ${{ matrix.test_task == 'zjit-check' }}


- uses: ./.github/actions/setup/directories
Expand Down
20 changes: 10 additions & 10 deletions class.c
Original file line number Diff line number Diff line change
Expand Up @@ -734,13 +734,13 @@ static void
class_initialize_method_table(VALUE c)
{
// initialize the prime classext m_tbl
RCLASS_SET_M_TBL_EVEN_WHEN_PROMOTED(c, rb_id_table_create(0));
RCLASS_SET_M_TBL(c, rb_id_table_create(0));
}

static void
class_clear_method_table(VALUE c)
{
RCLASS_WRITE_M_TBL_EVEN_WHEN_PROMOTED(c, rb_id_table_create(0));
RCLASS_WRITE_M_TBL(c, rb_id_table_create(0));
}

static VALUE
Expand Down Expand Up @@ -978,7 +978,7 @@ copy_tables(VALUE clone, VALUE orig)
RCLASS_WRITE_CVC_TBL(clone, rb_cvc_tbl_dup);
}
rb_id_table_free(RCLASS_M_TBL(clone));
RCLASS_WRITE_M_TBL_EVEN_WHEN_PROMOTED(clone, 0);
RCLASS_WRITE_M_TBL(clone, 0);
if (!RB_TYPE_P(clone, T_ICLASS)) {
rb_fields_tbl_copy(clone, orig);
}
Expand Down Expand Up @@ -1053,9 +1053,7 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
struct clone_method_arg arg;
arg.old_klass = orig;
arg.new_klass = clone;
// TODO: use class_initialize_method_table() instead of RCLASS_SET_M_TBL_*
// after RCLASS_SET_M_TBL is protected by write barrier
RCLASS_SET_M_TBL_EVEN_WHEN_PROMOTED(clone, rb_id_table_create(0));
class_initialize_method_table(clone);
rb_id_table_foreach(RCLASS_M_TBL(orig), clone_method_i, &arg);
}

Expand All @@ -1081,9 +1079,6 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
rb_bug("non iclass between module/class and origin");
}
clone_p = class_alloc(T_ICLASS, METACLASS_OF(p));
/* We should set the m_tbl right after allocation before anything
* that can trigger GC to avoid clone_p from becoming old and
* needing to fire write barriers. */
RCLASS_SET_M_TBL(clone_p, RCLASS_M_TBL(p));
rb_class_set_super(prev_clone_p, clone_p);
prev_clone_p = clone_p;
Expand Down Expand Up @@ -1931,6 +1926,11 @@ ensure_origin(VALUE klass)
rb_class_set_super(origin, RCLASS_SUPER(klass));
rb_class_set_super(klass, origin); // writes origin into RCLASS_SUPER(klass)
RCLASS_WRITE_ORIGIN(klass, origin);

// RCLASS_WRITE_ORIGIN marks origin as an origin, so this is the first
// point that it sees M_TBL and may mark it
rb_gc_writebarrier_remember(origin);

class_clear_method_table(klass);
rb_id_table_foreach(RCLASS_M_TBL(origin), cache_clear_refined_method, (void *)klass);
rb_id_table_foreach(RCLASS_M_TBL(origin), move_refined_method, (void *)klass);
Expand Down Expand Up @@ -1968,7 +1968,7 @@ rb_prepend_module(VALUE klass, VALUE module)
if (klass_had_no_origin && klass_origin_m_tbl == RCLASS_M_TBL(subclass)) {
// backfill an origin iclass to handle refinements and future prepends
rb_id_table_foreach(RCLASS_M_TBL(subclass), clear_module_cache_i, (void *)subclass);
RCLASS_WRITE_M_TBL_EVEN_WHEN_PROMOTED(subclass, klass_m_tbl);
RCLASS_WRITE_M_TBL(subclass, klass_m_tbl);
VALUE origin = rb_include_class_new(klass_origin, RCLASS_SUPER(subclass));
rb_class_set_super(subclass, origin);
RCLASS_SET_INCLUDER(origin, RCLASS_INCLUDER(subclass));
Expand Down
2 changes: 1 addition & 1 deletion doc/string.rb
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@
# _Counts_
#
# - #length (aliased as #size): Returns the count of characters (not bytes).
# - #empty?: Returns +true+ if +self.length+ is zero; +false+ otherwise.
# - #empty?: Returns whether the length of +self+ is zero.
# - #bytesize: Returns the count of bytes.
# - #count: Returns the count of substrings matching given strings.
#
Expand Down
31 changes: 18 additions & 13 deletions doc/string/each_char.rdoc
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
Calls the given block with each successive character from +self+;
With a block given, calls the block with each successive character from +self+;
returns +self+:

'hello'.each_char {|char| print char, ' ' }
print "\n"
'тест'.each_char {|char| print char, ' ' }
print "\n"
'こんにちは'.each_char {|char| print char, ' ' }
print "\n"
a = []
'hello'.each_char do |char|
a.push(char)
end
a # => ["h", "e", "l", "l", "o"]
a = []
'тест'.each_char do |char|
a.push(char)
end
a # => ["т", "е", "с", "т"]
a = []
'こんにちは'.each_char do |char|
a.push(char)
end
a # => ["こ", "ん", "に", "ち", "は"]

Output:
With no block given, returns an enumerator.

h e l l o
т е с т
こ ん に ち は

Returns an enumerator if no block is given.
Related: see {Iterating}[rdoc-ref:String@Iterating].
33 changes: 19 additions & 14 deletions doc/string/each_codepoint.rdoc
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
Calls the given block with each successive codepoint from +self+;
each codepoint is the integer value for a character;
With a block given, calls the block with each successive codepoint from +self+;
each {codepoint}[https://en.wikipedia.org/wiki/Code_point] is the integer value for a character;
returns +self+:

'hello'.each_codepoint {|codepoint| print codepoint, ' ' }
print "\n"
'тест'.each_codepoint {|codepoint| print codepoint, ' ' }
print "\n"
'こんにちは'.each_codepoint {|codepoint| print codepoint, ' ' }
print "\n"
a = []
'hello'.each_codepoint do |codepoint|
a.push(codepoint)
end
a # => [104, 101, 108, 108, 111]
a = []
'тест'.each_codepoint do |codepoint|
a.push(codepoint)
end
a # => [1090, 1077, 1089, 1090]
a = []
'こんにちは'.each_codepoint do |codepoint|
a.push(codepoint)
end
a # => [12371, 12435, 12395, 12385, 12399]

Output:
With no block given, returns an enumerator.

104 101 108 108 111
1090 1077 1089 1090
12371 12435 12395 12385 12399

Returns an enumerator if no block is given.
Related: see {Iterating}[rdoc-ref:String@Iterating].
25 changes: 19 additions & 6 deletions doc/string/each_grapheme_cluster.rdoc
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
Calls the given block with each successive grapheme cluster from +self+
With a block given, calls the given block with each successive grapheme cluster from +self+
(see {Unicode Grapheme Cluster Boundaries}[https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries]);
returns +self+:

s = "\u0061\u0308-pqr-\u0062\u0308-xyz-\u0063\u0308" # => "ä-pqr-b̈-xyz-c̈"
s.each_grapheme_cluster {|gc| print gc, ' ' }
a = []
'hello'.each_grapheme_cluster do |grapheme_cluster|
a.push(grapheme_cluster)
end
a # => ["h", "e", "l", "l", "o"]

Output:
a = []
'тест'.each_grapheme_cluster do |grapheme_cluster|
a.push(grapheme_cluster)
end
a # => ["т", "е", "с", "т"]

ä - p q r - b̈ - x y z - c̈
a = []
'こんにちは'.each_grapheme_cluster do |grapheme_cluster|
a.push(grapheme_cluster)
end
a # => ["こ", "ん", "に", "ち", "は"]

Returns an enumerator if no block is given.
With no block given, returns an enumerator.

Related: see {Iterating}[rdoc-ref:String@Iterating].
24 changes: 15 additions & 9 deletions doc/string/each_line.rdoc
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
With a block given, forms the substrings ("lines")
With a block given, forms the substrings (lines)
that are the result of splitting +self+
at each occurrence of the given line separator +line_sep+;
at each occurrence of the given +record_separator+;
passes each line to the block;
returns +self+:
returns +self+.

With the default +record_separator+:

$/ # => "\n"
s = <<~EOT
This is the first line.
This is line two.

This is line four.
This is line five.
EOT

s.each_line {|line| p line }

Output:
Expand All @@ -22,9 +24,10 @@ Output:
"This is line four.\n"
"This is line five.\n"

With a different +line_sep+:
With a different +record_separator+:

s.each_line(' is ') {|line| p line }
record_separator = ' is '
s.each_line(record_separator) {|line| p line }

Output:

Expand All @@ -34,7 +37,7 @@ Output:
"line four.\nThis is "
"line five.\n"

With +chomp+ as +true+, removes the trailing +line_sep+ from each line:
With +chomp+ as +true+, removes the trailing +record_separator+ from each line:

s.each_line(chomp: true) {|line| p line }

Expand All @@ -46,15 +49,18 @@ Output:
"This is line four."
"This is line five."

With an empty string as +line_sep+,
With an empty string as +record_separator+,
forms and passes "paragraphs" by splitting at each occurrence
of two or more newlines:

s.each_line('') {|line| p line }
record_separator = ''
s.each_line(record_separator) {|line| p line }

Output:

"This is the first line.\nThis is line two.\n\n"
"This is line four.\nThis is line five.\n"

With no block given, returns an enumerator.

Related: see {Iterating}[rdoc-ref:String@Iterating].
7 changes: 5 additions & 2 deletions encoding.c
Original file line number Diff line number Diff line change
Expand Up @@ -1177,9 +1177,12 @@ rb_enc_copy(VALUE obj1, VALUE obj2)

/*
* call-seq:
* obj.encoding -> encoding
* encoding -> encoding
*
* Returns the Encoding object that represents the encoding of obj.
* Returns an Encoding object that represents the encoding of +self+;
* see {Encodings}[rdoc-ref:encodings.rdoc].
*
* Related: see {Querying}[rdoc-ref:String@Querying].
*/

VALUE
Expand Down
7 changes: 4 additions & 3 deletions ext/objspace/objspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@
* information as only a *HINT*. Especially, the size of +T_DATA+ may not be
* correct.
*
* This method is only expected to work with C Ruby.
* This method is only expected to work with CRuby.
*
* From Ruby 2.2, memsize_of(obj) returns a memory size includes
* sizeof(RVALUE).
* From Ruby 3.2 with Variable Width Allocation, it returns the actual slot
* size used plus any additional memory allocated outside the slot (such
* as external strings, arrays, or hash tables).
*/

static VALUE
Expand Down
17 changes: 2 additions & 15 deletions internal/class.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,6 @@ static inline void RCLASSEXT_SET_INCLUDER(rb_classext_t *ext, VALUE klass, VALUE

static inline void RCLASS_SET_SUPER(VALUE klass, VALUE super);
static inline void RCLASS_WRITE_SUPER(VALUE klass, VALUE super);
// TODO: rename RCLASS_SET_M_TBL_WORKAROUND (and _WRITE_) to RCLASS_SET_M_TBL with write barrier
static inline void RCLASS_SET_M_TBL_WORKAROUND(VALUE klass, struct rb_id_table *table, bool check_promoted);
static inline void RCLASS_WRITE_M_TBL_WORKAROUND(VALUE klass, struct rb_id_table *table, bool check_promoted);
static inline void RCLASS_SET_CONST_TBL(VALUE klass, struct rb_id_table *table, bool shared);
static inline void RCLASS_WRITE_CONST_TBL(VALUE klass, struct rb_id_table *table, bool shared);
static inline void RCLASS_WRITE_CALLABLE_M_TBL(VALUE klass, struct rb_id_table *table);
Expand Down Expand Up @@ -594,25 +591,15 @@ RCLASS_FIELDS_COUNT(VALUE obj)
return 0;
}

#define RCLASS_SET_M_TBL_EVEN_WHEN_PROMOTED(klass, table) RCLASS_SET_M_TBL_WORKAROUND(klass, table, false)
#define RCLASS_SET_M_TBL(klass, table) RCLASS_SET_M_TBL_WORKAROUND(klass, table, true)

static inline void
RCLASS_SET_M_TBL_WORKAROUND(VALUE klass, struct rb_id_table *table, bool check_promoted)
RCLASS_SET_M_TBL(VALUE klass, struct rb_id_table *table)
{
RUBY_ASSERT(!check_promoted || !RB_OBJ_PROMOTED(klass));
RCLASSEXT_M_TBL(RCLASS_EXT_PRIME(klass)) = table;
}

#define RCLASS_WRITE_M_TBL_EVEN_WHEN_PROMOTED(klass, table) RCLASS_WRITE_M_TBL_WORKAROUND(klass, table, false)
#define RCLASS_WRITE_M_TBL(klass, table) RCLASS_WRITE_M_TBL_WORKAROUND(klass, table, true)

static inline void
RCLASS_WRITE_M_TBL_WORKAROUND(VALUE klass, struct rb_id_table *table, bool check_promoted)
RCLASS_WRITE_M_TBL(VALUE klass, struct rb_id_table *table)
{
RUBY_ASSERT(!check_promoted || !RB_OBJ_PROMOTED(klass));
// TODO: add write barrier here to guard assigning m_tbl
// see commit 28a6e4ea9d9379a654a8f7c4b37fa33aa3ccd0b7
RCLASSEXT_M_TBL(RCLASS_EXT_WRITABLE(klass)) = table;
}

Expand Down
Loading