#include "probes.h"
#include "ruby/encoding.h"
#include "ruby/st.h"
+#include "ruby/thread.h"
#include "ruby/util.h"
#include "vm_core.h"
#include "builtin.h"
@@ -263,12 +264,6 @@ ary_verify_(VALUE ary, const char *file, int line)
return ary;
}
-
-void
-rb_ary_verify(VALUE ary)
-{
- ary_verify(ary);
-}
#else
#define ary_verify(ary) ((void)0)
#endif
@@ -527,6 +522,8 @@ rb_ary_set_shared(VALUE ary, VALUE shared_root)
static inline void
rb_ary_modify_check(VALUE ary)
{
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
+
rb_check_frozen(ary);
ary_verify(ary);
}
@@ -711,6 +708,8 @@ empty_ary_alloc(VALUE klass)
static VALUE
ary_new(VALUE klass, long capa)
{
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
+
VALUE ary;
if (capa < 0) {
@@ -1815,7 +1814,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* If +index+ is out of range, returns +nil+.
*
* When two Integer arguments +start+ and +length+ are given,
- * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
+ * returns a new array of size +length+ containing successive elements beginning at offset +start+:
*
* a = [:foo, 'bar', 2]
* a[0, 2] # => [:foo, "bar"]
@@ -1830,7 +1829,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* a[2, 2] # => [2]
*
* If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
- * returns a new empty +Array+.
+ * returns a new empty array.
*
* If +length+ is negative, returns +nil+.
*
@@ -1842,7 +1841,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* a[0..1] # => [:foo, "bar"]
* a[1..2] # => ["bar", 2]
*
- * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
+ * Special case: If <tt>range.start == a.size</tt>, returns a new empty array.
*
* If <tt>range.end</tt> is negative, calculates the end index from the end:
*
@@ -1866,7 +1865,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* a[4..-1] # => nil
*
* When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
- * returns an +Array+ of elements corresponding to the indexes produced by
+ * returns an array of elements corresponding to the indexes produced by
* the sequence.
*
* a = ['--', 'data1', '--', 'data2', '--', 'data3']
@@ -2304,7 +2303,7 @@ rb_ary_resize(VALUE ary, long len)
rb_raise(rb_eIndexError, "index %ld too big", len);
}
if (len > olen) {
- if (len >= ARY_CAPA(ary)) {
+ if (len > ARY_CAPA(ary)) {
ary_double_capa(ary, len);
}
ary_mem_clear(ary, olen, len - olen);
@@ -2408,7 +2407,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* a[-1] = 'two' # => "two"
* a # => [:foo, "bar", "two"]
*
- * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
+ * When Integer arguments +start+ and +length+ are given and +object+ is not an array,
* removes <tt>length - 1</tt> elements beginning at offset +start+,
* and assigns +object+ at offset +start+:
*
@@ -2443,7 +2442,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* a[1, 5] = 'foo' # => "foo"
* a # => [:foo, "foo"]
*
- * When Range argument +range+ is given and +object+ is not an +Array+,
+ * When Range argument +range+ is given and +object+ is not an array,
* removes <tt>length - 1</tt> elements beginning at offset +start+,
* and assigns +object+ at offset +start+:
*
@@ -2759,7 +2758,7 @@ rb_ary_length(VALUE ary)
/*
* call-seq:
- * array.empty? -> true or false
+ * empty? -> true or false
*
* Returns +true+ if the count of elements in +self+ is zero,
* +false+ otherwise.
@@ -2928,7 +2927,7 @@ rb_ary_join(VALUE ary, VALUE sep)
/*
* call-seq:
- * array.join(separator = $,) -> new_string
+ * join(separator = $,) -> new_string
*
* Returns the new string formed by joining the converted elements of +self+;
* for each element +element+:
@@ -3019,7 +3018,7 @@ rb_ary_to_s(VALUE ary)
* call-seq:
* to_a -> self or new_array
*
- * When +self+ is an instance of +Array+, returns +self+.
+ * When +self+ is an instance of \Array, returns +self+.
*
* Otherwise, returns a new array containing the elements of +self+:
*
@@ -3094,7 +3093,7 @@ rb_ary_to_h(VALUE ary)
/*
* call-seq:
- * array.to_ary -> self
+ * to_ary -> self
*
* Returns +self+.
*/
@@ -3480,6 +3479,9 @@ rb_ary_sort_bang(VALUE ary)
* When the block returns zero, the order for +a+ and +b+ is indeterminate,
* and may be unstable.
*
+ * See an example in Numeric#nonzero? for the idiom to sort more
+ * complex structure.
+ *
* Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
@@ -3613,8 +3615,10 @@ rb_ary_sort_by_bang(VALUE ary)
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
rb_ary_modify(ary);
- sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
- rb_ary_replace(ary, sorted);
+ if (RARRAY_LEN(ary) > 1) {
+ sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
+ rb_ary_replace(ary, sorted);
+ }
return ary;
}
@@ -4470,7 +4474,7 @@ take_items(VALUE obj, long n)
/*
* call-seq:
* zip(*other_arrays) -> new_array
- * zip(*other_arrays) {|other_array| ... } -> nil
+ * zip(*other_arrays) {|sub_array| ... } -> nil
*
* With no block given, combines +self+ with the collection of +other_arrays+;
* returns a new array of sub-arrays:
@@ -5090,7 +5094,7 @@ rb_ary_concat(VALUE x, VALUE y)
* When string argument +string_separator+ is given,
* equivalent to <tt>self.join(string_separator)</tt>:
*
- * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
+ * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {foo: 0}"
*
*/
@@ -5317,8 +5321,8 @@ rb_ary_eql(VALUE ary1, VALUE ary2)
return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
}
-VALUE
-rb_ary_hash_values(long len, const VALUE *elements)
+static VALUE
+ary_hash_values(long len, const VALUE *elements, const VALUE ary)
{
long i;
st_index_t h;
@@ -5329,11 +5333,21 @@ rb_ary_hash_values(long len, const VALUE *elements)
for (i=0; i<len; i++) {
n = rb_hash(elements[i]);
h = rb_hash_uint(h, NUM2LONG(n));
+ if (ary) {
+ len = RARRAY_LEN(ary);
+ elements = RARRAY_CONST_PTR(ary);
+ }
}
h = rb_hash_end(h);
return ST2FIX(h);
}
+VALUE
+rb_ary_hash_values(long len, const VALUE *elements)
+{
+ return ary_hash_values(len, elements, 0);
+}
+
/*
* call-seq:
* hash -> integer
@@ -5352,7 +5366,8 @@ rb_ary_hash_values(long len, const VALUE *elements)
static VALUE
rb_ary_hash(VALUE ary)
{
- return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
+ RBIMPL_ASSERT_OR_ASSUME(ary);
+ return ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary), ary);
}
/*
@@ -5609,7 +5624,7 @@ rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
VALUE elt = rb_ary_elt(ary, i);
for (j = 0; j < argc; j++) {
if (is_hash[j]) {
- if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL))
+ if (rb_hash_stlike_lookup(argv[j], elt, NULL))
break;
}
else {
@@ -5979,9 +5994,9 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
/*
* call-seq:
* max -> element
- * max(n) -> new_array
+ * max(count) -> new_array
* max {|a, b| ... } -> element
- * max(n) {|a, b| ... } -> new_array
+ * max(count) {|a, b| ... } -> new_array
*
* Returns one of the following:
*
@@ -5998,8 +6013,8 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
*
* [1, 0, 3, 2].max # => 3
*
- * With non-negative numeric argument +n+ and no block,
- * returns a new array with at most +n+ elements,
+ * With non-negative numeric argument +count+ and no block,
+ * returns a new array with at most +count+ elements,
* in descending order, per method <tt>#<=></tt>:
*
* [1, 0, 3, 2].max(3) # => [3, 2, 1]
@@ -6015,8 +6030,8 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
* ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
* # => "000"
*
- * With non-negative numeric argument +n+ and a block,
- * returns a new array with at most +n+ elements,
+ * With non-negative numeric argument +count+ and a block,
+ * returns a new array with at most +count+ elements,
* in descending order, per the block:
*
* ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
@@ -6156,9 +6171,9 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
/*
* call-seq:
* min -> element
- * min(n) -> new_array
+ * min(count) -> new_array
* min {|a, b| ... } -> element
- * min(n) {|a, b| ... } -> new_array
+ * min(count) {|a, b| ... } -> new_array
*
* Returns one of the following:
*
@@ -6175,8 +6190,8 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
*
* [1, 0, 3, 2].min # => 0
*
- * With non-negative numeric argument +n+ and no block,
- * returns a new array with at most +n+ elements,
+ * With non-negative numeric argument +count+ and no block,
+ * returns a new array with at most +count+ elements,
* in ascending order, per method <tt>#<=></tt>:
*
* [1, 0, 3, 2].min(3) # => [0, 1, 2]
@@ -6192,8 +6207,8 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
* ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
* # => ""
*
- * With non-negative numeric argument +n+ and a block,
- * returns a new array with at most +n+ elements,
+ * With non-negative numeric argument +count+ and a block,
+ * returns a new array with at most +count+ elements,
* in ascending order, per the block:
*
* ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
@@ -6707,7 +6722,7 @@ rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
rb_ary_modify(ary);
i = len = RARRAY_LEN(ary);
RARRAY_PTR_USE(ary, ptr, {
- while (i) {
+ while (i > 1) {
long j = RAND_UPTO(i);
VALUE tmp;
if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
@@ -7069,14 +7084,14 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
/*
* call-seq:
- * permutation(n = self.size) {|permutation| ... } -> self
- * permutation(n = self.size) -> new_enumerator
+ * permutation(count = self.size) {|permutation| ... } -> self
+ * permutation(count = self.size) -> new_enumerator
*
* Iterates over permutations of the elements of +self+;
* the order of permutations is indeterminate.
*
- * With a block and an in-range positive integer argument +n+ (<tt>0 < n <= self.size</tt>) given,
- * calls the block with each +n+-tuple permutations of +self+;
+ * With a block and an in-range positive integer argument +count+ (<tt>0 < count <= self.size</tt>) given,
+ * calls the block with each permutation of +self+ of size +count+;
* returns +self+:
*
* a = [0, 1, 2]
@@ -7092,13 +7107,13 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* a.permutation(3) {|perm| perms.push(perm) }
* perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
*
- * When +n+ is zero, calls the block once with a new empty array:
+ * When +count+ is zero, calls the block once with a new empty array:
*
* perms = []
* a.permutation(0) {|perm| perms.push(perm) }
* perms # => [[]]
*
- * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
+ * When +count+ is out of range (negative or larger than <tt>self.size</tt>),
* does not call the block:
*
* a.permutation(-1) {|permutation| fail 'Cannot happen' }
@@ -7179,13 +7194,13 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
/*
* call-seq:
- * combination(n) {|element| ... } -> self
- * combination(n) -> new_enumerator
+ * combination(count) {|element| ... } -> self
+ * combination(count) -> new_enumerator
*
* When a block and a positive
* {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
- * argument +n+ (<tt>0 < n <= self.size</tt>)
- * are given, calls the block with all +n+-tuple combinations of +self+;
+ * argument +count+ (<tt>0 < count <= self.size</tt>)
+ * are given, calls the block with each combination of +self+ of size +count+;
* returns +self+:
*
* a = %w[a b c] # => ["a", "b", "c"]
@@ -7199,7 +7214,7 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
*
* The order of the yielded combinations is not guaranteed.
*
- * When +n+ is zero, calls the block once with a new empty array:
+ * When +count+ is zero, calls the block once with a new empty array:
*
* a.combination(0) {|combination| p combination }
* [].combination(0) {|combination| p combination }
@@ -7209,7 +7224,7 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
* []
* []
*
- * When +n+ is negative or larger than +self.size+ and +self+ is non-empty,
+ * When +count+ is negative or larger than +self.size+ and +self+ is non-empty,
* does not call the block:
*
* a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
@@ -7686,10 +7701,10 @@ rb_ary_take_while(VALUE ary)
/*
* call-seq:
- * drop(n) -> new_array
+ * drop(count) -> new_array
*
- * Returns a new array containing all but the first +n+ element of +self+,
- * where +n+ is a non-negative Integer;
+ * Returns a new array containing all but the first +count+ element of +self+,
+ * where +count+ is a non-negative integer;
* does not modify +self+.
*
* Examples:
@@ -8018,7 +8033,7 @@ rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array.dig(index, *identifiers) -> object
+ * dig(index, *identifiers) -> object
*
* Finds and returns the object in nested object
* specified by +index+ and +identifiers+;
@@ -8294,21 +8309,21 @@ rb_ary_deconstruct(VALUE ary)
*
* You can create an \Array object explicitly with:
*
- * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
+ * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]:
*
* [1, 'one', :one, [2, 'two', :two]]
*
- * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
+ * - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
*
* %w[foo bar baz] # => ["foo", "bar", "baz"]
* %w[1 % *] # => ["1", "%", "*"]
*
- * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
+ * - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
*
* %i[foo bar baz] # => [:foo, :bar, :baz]
* %i[1 % *] # => [:"1", :%, :*]
*
- * - \Method Kernel#Array:
+ * - Method Kernel#Array:
*
* Array(["a", "b"]) # => ["a", "b"]
* Array(1..5) # => [1, 2, 3, 4, 5]
@@ -8317,7 +8332,7 @@ rb_ary_deconstruct(VALUE ary)
* Array(1) # => [1]
* Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
*
- * - \Method Array.new:
+ * - Method Array.new:
*
* Array.new # => []
* Array.new(3) # => [nil, nil, nil]
@@ -8372,8 +8387,8 @@ rb_ary_deconstruct(VALUE ary)
*
* == Example Usage
*
- * In addition to the methods it mixes in through the Enumerable module, the
- * +Array+ class has proprietary methods for accessing, searching and otherwise
+ * In addition to the methods it mixes in through the Enumerable module,
+ * class \Array has proprietary methods for accessing, searching and otherwise
* manipulating arrays.
*
* Some of the more common ones are illustrated below.
@@ -8421,9 +8436,9 @@ rb_ary_deconstruct(VALUE ary)
*
* arr.drop(3) #=> [4, 5, 6]
*
- * == Obtaining Information about an +Array+
+ * == Obtaining Information about an \Array
*
- * Arrays keep track of their own length at all times. To query an array
+ * An array keeps track of its own length at all times. To query an array
* about the number of elements it contains, use #length, #count or #size.
*
* browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
@@ -8438,7 +8453,7 @@ rb_ary_deconstruct(VALUE ary)
*
* browsers.include?('Konqueror') #=> false
*
- * == Adding Items to Arrays
+ * == Adding Items to an \Array
*
* Items can be added to the end of an array by using either #push or #<<
*
@@ -8459,7 +8474,7 @@ rb_ary_deconstruct(VALUE ary)
* arr.insert(3, 'orange', 'pear', 'grapefruit')
* #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
*
- * == Removing Items from an +Array+
+ * == Removing Items from an \Array
*
* The method #pop removes the last element in an array and returns it:
*
@@ -8499,11 +8514,11 @@ rb_ary_deconstruct(VALUE ary)
* arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
* arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
*
- * == Iterating over Arrays
+ * == Iterating over an \Array
*
- * Like all classes that include the Enumerable module, +Array+ has an each
+ * Like all classes that include the Enumerable module, class \Array has an each
* method, which defines what elements should be iterated over and how. In
- * case of Array's #each, all elements in the +Array+ instance are yielded to
+ * case of Array#each, all elements in +self+ are yielded to
* the supplied block in sequence.
*
* Note that this operation leaves the array unchanged.
@@ -8530,7 +8545,7 @@ rb_ary_deconstruct(VALUE ary)
* arr #=> [1, 4, 9, 16, 25]
*
*
- * == Selecting Items from an +Array+
+ * == Selecting Items from an \Array
*
* Elements can be selected from an array according to criteria defined in a
* block. The selection can happen in a destructive or a non-destructive
@@ -8563,13 +8578,13 @@ rb_ary_deconstruct(VALUE ary)
*
* == What's Here
*
- * First, what's elsewhere. \Class +Array+:
+ * First, what's elsewhere. Class \Array:
*
* - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
* - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
* which provides dozens of additional methods.
*
- * Here, class +Array+ provides methods that are useful for:
+ * Here, class \Array provides methods that are useful for:
*
* - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
* - {Querying}[rdoc-ref:Array@Methods+for+Querying]
@@ -8582,7 +8597,7 @@ rb_ary_deconstruct(VALUE ary)
* - {Converting}[rdoc-ref:Array@Methods+for+Converting]
* - {And more....}[rdoc-ref:Array@Other+Methods]
*
- * === Methods for Creating an +Array+
+ * === Methods for Creating an \Array
*
* - ::[]: Returns a new array populated with given objects.
* - ::new: Returns a new array.