Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into Ractor-Local-GC-v…
Browse files Browse the repository at this point in the history
…ersion-3
  • Loading branch information
rm155 committed Oct 22, 2024
2 parents c74c73c + da82b84 commit 4f8ee4e
Show file tree
Hide file tree
Showing 37 changed files with 444 additions and 428 deletions.
93 changes: 44 additions & 49 deletions array.c
Original file line number Diff line number Diff line change
Expand Up @@ -2964,14 +2964,15 @@ inspect_ary(VALUE ary, VALUE dummy, int recur)
/*
* call-seq:
* inspect -> new_string
* to_s -> new_string
*
* Returns the new string formed by calling method <tt>#inspect</tt>
* on each array element:
*
* a = [:foo, 'bar', 2]
* a.inspect # => "[:foo, \"bar\", 2]"
*
* Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
* Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
*/

static VALUE
Expand All @@ -2991,21 +2992,17 @@ rb_ary_to_s(VALUE ary)
* call-seq:
* to_a -> self or new_array
*
* When +self+ is an instance of +Array+, returns +self+:
*
* a = [:foo, 'bar', 2]
* a.to_a # => [:foo, "bar", 2]
* When +self+ is an instance of +Array+, returns +self+.
*
* Otherwise, returns a new +Array+ containing the elements of +self+:
* Otherwise, returns a new array containing the elements of +self+:
*
* class MyArray < Array; end
* a = MyArray.new(['foo', 'bar', 'two'])
* a.instance_of?(Array) # => false
* a.kind_of?(Array) # => true
* a1 = a.to_a
* a1 # => ["foo", "bar", "two"]
* a1.class # => Array # Not MyArray
* my_a = MyArray.new(['foo', 'bar', 'two'])
* a = my_a.to_a
* a # => ["foo", "bar", "two"]
* a.class # => Array # Not MyArray.
*
* Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
*/

static VALUE
Expand All @@ -3021,27 +3018,27 @@ rb_ary_to_a(VALUE ary)

/*
* call-seq:
* array.to_h -> new_hash
* array.to_h {|item| ... } -> new_hash
* to_h -> new_hash
* to_h {|element| ... } -> new_hash
*
* Returns a new Hash formed from +self+.
* Returns a new hash formed from +self+.
*
* When a block is given, calls the block with each array element;
* the block must return a 2-element +Array+ whose two elements
* form a key-value pair in the returned Hash:
* With no block given, each element of +self+ must be a 2-element sub-array;
* forms each sub-array into a key-value pair in the new hash:
*
* a = ['foo', :bar, 1, [2, 3], {baz: 4}]
* h = a.to_h {|item| [item, item] }
* h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
* a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
* a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
* [].to_h # => {}
*
* When no block is given, +self+ must be an +Array+ of 2-element sub-arrays,
* each sub-array is formed into a key-value pair in the new Hash:
* With a block given, the block must return a 2-element array;
* calls the block with each element of +self+;
* forms each returned array into a key-value pair in the returned hash:
*
* [].to_h # => {}
* a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
* h = a.to_h
* h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
* a = ['foo', :bar, 1, [2, 3], {baz: 4}]
* a.to_h {|element| [element, element.class] }
* # => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash}
*
* Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
*/

static VALUE
Expand Down Expand Up @@ -7491,20 +7488,20 @@ rb_ary_product(int argc, VALUE *argv, VALUE ary)

/*
* call-seq:
* array.take(n) -> new_array
*
* Returns a new +Array+ containing the first +n+ element of +self+,
* where +n+ is a non-negative Integer;
* does not modify +self+.
* take(count) -> new_array
*
* Examples:
* Returns a new array containing the first +count+ element of +self+
* (as available);
* +count+ must be a non-negative numeric;
* does not modify +self+:
*
* a = [0, 1, 2, 3, 4, 5]
* a.take(1) # => [0]
* a.take(2) # => [0, 1]
* a.take(50) # => [0, 1, 2, 3, 4, 5]
* a # => [0, 1, 2, 3, 4, 5]
* a = ['a', 'b', 'c', 'd']
* a.take(2) # => ["a", "b"]
* a.take(2.1) # => ["a", "b"]
* a.take(50) # => ["a", "b", "c", "d"]
* a.take(0) # => []
*
* Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/

static VALUE
Expand All @@ -7519,25 +7516,23 @@ rb_ary_take(VALUE obj, VALUE n)

/*
* call-seq:
* array.take_while {|element| ... } -> new_array
* array.take_while -> new_enumerator
*
* Returns a new +Array+ containing zero or more leading elements of +self+;
* does not modify +self+.
* take_while {|element| ... } -> new_array
* take_while -> new_enumerator
*
* With a block given, calls the block with each successive element of +self+;
* stops if the block returns +false+ or +nil+;
* returns a new +Array+ containing those elements for which the block returned a truthy value:
* stops iterating if the block returns +false+ or +nil+;
* returns a new array containing those elements for which the block returned a truthy value:
*
* a = [0, 1, 2, 3, 4, 5]
* a.take_while {|element| element < 3 } # => [0, 1, 2]
* a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
* a # => [0, 1, 2, 3, 4, 5]
* a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
* a.take_while {|element| false } # => []
*
* With no block given, returns a new Enumerator:
* With no block given, returns a new Enumerator.
*
* [0, 1].take_while # => #<Enumerator: [0, 1]:take_while>
* Does not modify +self+.
*
* Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/

static VALUE
Expand Down
4 changes: 2 additions & 2 deletions bootstraptest/test_yjit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4726,7 +4726,7 @@ def test(klass, args)
}

# Chilled string setivar trigger warning
assert_equal 'literal string will be frozen in the future', %q{
assert_match(/literal string will be frozen in the future/, %q{
Warning[:deprecated] = true
$VERBOSE = true
$warning = "no-warning"
Expand Down Expand Up @@ -4754,7 +4754,7 @@ def setivar!(str)
setivar!("chilled") # Emit warning
$warning
}
})

# arity=-2 cfuncs
assert_equal '["", "1/2", [0, [:ok, 1]]]', %q{
Expand Down
23 changes: 9 additions & 14 deletions compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -4874,10 +4874,8 @@ static_literal_value(const NODE *node, rb_iseq_t *iseq)
case NODE_FILE:
case NODE_STR:
if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX((int)nd_line(node)));
VALUE lit = rb_str_dup(get_string_value(node));
rb_ivar_set(lit, id_debug_created_info, rb_ary_freeze(debug_info));
return rb_str_freeze(lit);
VALUE lit = get_string_value(node);
return rb_str_with_debug_created_info(lit, rb_iseq_path(iseq), (int)nd_line(node));
}
else {
return get_string_value(node);
Expand Down Expand Up @@ -10932,28 +10930,25 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
debugp_param("nd_lit", get_string_value(node));
if (!popped) {
VALUE lit = get_string_value(node);
switch (ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
const rb_compile_option_t *option = ISEQ_COMPILE_DATA(iseq)->option;
if ((option->debug_frozen_string_literal || RTEST(ruby_debug)) &&
option->frozen_string_literal != ISEQ_FROZEN_STRING_LITERAL_DISABLED) {
lit = rb_str_with_debug_created_info(lit, rb_iseq_path(iseq), line);
}
switch (option->frozen_string_literal) {
case ISEQ_FROZEN_STRING_LITERAL_UNSET:
ADD_INSN1(ret, node, putchilledstring, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
break;
case ISEQ_FROZEN_STRING_LITERAL_DISABLED:
ADD_INSN1(ret, node, putstring, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
break;
case ISEQ_FROZEN_STRING_LITERAL_ENABLED:
if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line));
lit = rb_str_dup(lit);
rb_ivar_set(lit, id_debug_created_info, rb_ary_freeze(debug_info));
lit = rb_str_freeze(lit);
}
ADD_INSN1(ret, node, putobject, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
break;
default:
rb_bug("invalid frozen_string_literal");
}
RB_OBJ_WRITTEN(iseq, Qundef, lit);
}
break;
}
Expand Down
57 changes: 50 additions & 7 deletions error.c
Original file line number Diff line number Diff line change
Expand Up @@ -3973,29 +3973,72 @@ inspect_frozen_obj(VALUE obj, VALUE mesg, int recur)
return mesg;
}

static VALUE
get_created_info(VALUE obj, int *pline)
{
VALUE info = rb_attr_get(obj, id_debug_created_info);

if (NIL_P(info)) return Qnil;

VALUE path = rb_ary_entry(info, 0);
VALUE line = rb_ary_entry(info, 1);
if (NIL_P(path)) return Qnil;
*pline = NUM2INT(line);
return StringValue(path);
}

void
rb_error_frozen_object(VALUE frozen_obj)
{
rb_yjit_lazy_push_frame(GET_EC()->cfp->pc);

VALUE debug_info;
const ID created_info = id_debug_created_info;
VALUE mesg = rb_sprintf("can't modify frozen %"PRIsVALUE": ",
CLASS_OF(frozen_obj));
VALUE exc = rb_exc_new_str(rb_eFrozenError, mesg);

rb_ivar_set(exc, id_recv, frozen_obj);
rb_exec_recursive(inspect_frozen_obj, frozen_obj, mesg);

if (!NIL_P(debug_info = rb_attr_get(frozen_obj, created_info))) {
VALUE path = rb_ary_entry(debug_info, 0);
VALUE line = rb_ary_entry(debug_info, 1);

rb_str_catf(mesg, ", created at %"PRIsVALUE":%"PRIsVALUE, path, line);
int created_line;
VALUE created_path = get_created_info(frozen_obj, &created_line);
if (!NIL_P(created_path)) {
rb_str_catf(mesg, ", created at %"PRIsVALUE":%d", created_path, created_line);
}
rb_exc_raise(exc);
}

void
rb_warn_unchilled(VALUE obj)
{
rb_warning_category_t category = RB_WARN_CATEGORY_DEPRECATED;
if (!NIL_P(ruby_verbose) && rb_warning_category_enabled_p(category)) {
int line;
VALUE file = rb_source_location(&line);
VALUE mesg = NIL_P(file) ? rb_str_new(0, 0) : rb_str_dup(file);

if (!NIL_P(file)) {
if (line) rb_str_catf(mesg, ":%d", line);
rb_str_cat2(mesg, ": ");
}
rb_str_cat2(mesg, "warning: literal string will be frozen in the future");

VALUE str = obj;
if (STR_SHARED_P(str)) {
str = RSTRING(obj)->as.heap.aux.shared;
}
VALUE created = get_created_info(str, &line);
if (NIL_P(created)) {
rb_str_cat2(mesg, " (run with --debug-frozen-string-literal for more information)\n");
} else {
rb_str_cat2(mesg, "\n");
rb_str_append(mesg, created);
if (line) rb_str_catf(mesg, ":%d", line);
rb_str_cat2(mesg, ": info: the string was created here\n");
}
rb_warn_category(mesg, rb_warning_category_to_name(category));
}
}

#undef rb_check_frozen
void
rb_check_frozen(VALUE obj)
Expand Down
31 changes: 28 additions & 3 deletions ext/socket/lib/socket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -629,15 +629,22 @@ class << self
#
# creates a new socket object connected to host:port using TCP/IP.
#
# Starting from Ruby 3.4, this method operates according to the
# Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305])
# algorithm by default.
#
# To make it behave the same as in Ruby 3.3 and earlier,
# explicitly specify the option +fast_fallback:false+.
#
# If local_host:local_port is given,
# the socket is bound to it.
#
# The optional last argument _opts_ is options represented by a hash.
# _opts_ may have following options:
#
# [:resolv_timeout] specify the timeout of hostname resolution in seconds.
# [:connect_timeout] specify the timeout of conncetion in seconds.
# [:fast_fallback] enable Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305]) algorithm (Enabled by default).
# [:resolv_timeout] Specifies the timeout in seconds from when the hostname resolution starts.
# [:connect_timeout] This method sequentially attempts connecting to all candidate destination addresses.<br>The +connect_timeout+ specifies the timeout in seconds from the start of the connection attempt to the last candidate.<br>By default, all connection attempts continue until the timeout occurs.<br>When +fast_fallback:false+ is explicitly specified,<br>a timeout is set for each connection attempt and any connection attempt that exceeds its timeout will be canceled.
# [:fast_fallback] Enables the Happy Eyeballs Version 2 algorithm (enabled by default).
#
# If a block is given, the block is called with the socket.
# The value of the block is returned.
Expand All @@ -650,6 +657,24 @@ class << self
# sock.close_write
# puts sock.read
# }
#
# === Happy Eyeballs Version 2
# Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305])
# is an algorithm designed to improve client socket connectivity.<br>
# It aims for more reliable and efficient connections by performing hostname resolution
# and connection attempts in parallel, instead of serially.
#
# Starting from Ruby 3.4, this method operates as follows with this algorithm:
#
# 1. Start resolving both IPv6 and IPv4 addresses concurrently.
# 2. Start connecting to the one of the addresses that are obtained first.<br>If IPv4 addresses are obtained first,
# the method waits 50 ms for IPv6 name resolution to prioritize IPv6 connections.
# 3. After starting a connection attempt, wait 250 ms for the connection to be established.<br>
# If no connection is established within this time, a new connection is started every 250 ms<br>
# until a connection is established or there are no more candidate addresses.<br>
# (Although RFC 8305 strictly specifies sorting addresses,<br>
# this method only alternates between IPv6 / IPv4 addresses due to the performance concerns)
# 4. Once a connection is established, all remaining connection attempts are canceled.
def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, fast_fallback: tcp_fast_fallback, &) # :yield: socket
sock = if fast_fallback && !(host && ip_address?(host))
tcp_with_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:)
Expand Down
1 change: 0 additions & 1 deletion gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1407,7 +1407,6 @@ rb_gc_obj_free(void *objspace, VALUE obj)
return FALSE;
}
else {
RBASIC(obj)->flags = 0;
return TRUE;
}
}
Expand Down
8 changes: 6 additions & 2 deletions gc/default.c
Original file line number Diff line number Diff line change
Expand Up @@ -3515,7 +3515,9 @@ rb_gc_impl_shutdown_free_objects(void *objspace_ptr)
VALUE vp = (VALUE)p;
asan_unpoisoning_object(vp) {
if (RB_BUILTIN_TYPE(vp) != T_NONE) {
rb_gc_obj_free(objspace, vp);
if (rb_gc_obj_free(objspace, vp)) {
RBASIC(vp)->flags = 0;
}
}
}
}
Expand Down Expand Up @@ -3595,7 +3597,9 @@ rb_gc_impl_shutdown_call_finalizer(void *objspace_ptr)
VALUE vp = (VALUE)p;
asan_unpoisoning_object(vp) {
if (rb_gc_shutdown_call_finalizer_p(vp)) {
rb_gc_obj_free(objspace, vp);
if (rb_gc_obj_free(objspace, vp)) {
RBASIC(vp)->flags = 0;
}
}
}
}
Expand Down
Loading

0 comments on commit 4f8ee4e

Please sign in to comment.