Skip to content

Commit f96f848

Browse files
committed
Replace ary_fetch_next with separate array iteration primitives
1 parent f43d294 commit f96f848

2 files changed

Lines changed: 34 additions & 25 deletions

File tree

array.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2694,18 +2694,25 @@ ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
26942694
return rb_ary_length(ary);
26952695
}
26962696

2697-
// Primitive to avoid a race condition in Array#each.
2698-
// Return `true` and write `value` and `index` if the element exists.
2697+
// Return true if the index is at or past the end of the array.
26992698
static VALUE
2700-
ary_fetch_next(VALUE self, VALUE *index, VALUE *value)
2699+
rb_jit_ary_at_end(rb_execution_context_t *ec, VALUE self, VALUE index)
27012700
{
2702-
long i = NUM2LONG(*index);
2703-
if (i >= RARRAY_LEN(self)) {
2704-
return Qfalse;
2705-
}
2706-
*value = RARRAY_AREF(self, i);
2707-
*index = LONG2NUM(i + 1);
2708-
return Qtrue;
2701+
return FIX2LONG(index) >= RARRAY_LEN(self) ? Qtrue : Qfalse;
2702+
}
2703+
2704+
// Return the element at the given fixnum index.
2705+
static VALUE
2706+
rb_jit_ary_at(rb_execution_context_t *ec, VALUE self, VALUE index)
2707+
{
2708+
return RARRAY_AREF(self, FIX2LONG(index));
2709+
}
2710+
2711+
// Increment a fixnum by 1.
2712+
static VALUE
2713+
rb_jit_fixnum_inc(rb_execution_context_t *ec, VALUE self, VALUE num)
2714+
{
2715+
return LONG2FIX(FIX2LONG(num) + 1);
27092716
}
27102717

27112718
/*

array.rb

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,10 @@ def each # :nodoc:
222222
unless defined?(yield)
223223
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
224224
end
225-
_i = 0
226-
value = nil
227-
while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
228-
yield value
225+
i = 0
226+
until Primitive.rb_jit_ary_at_end(i)
227+
yield Primitive.rb_jit_ary_at(i)
228+
i = Primitive.rb_jit_fixnum_inc(i)
229229
end
230230
self
231231
end
@@ -241,12 +241,12 @@ def map # :nodoc:
241241
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
242242
end
243243

244-
_i = 0
245-
value = nil
244+
i = 0
246245
result = Primitive.ary_sized_alloc
247-
while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
248-
value = yield(value)
249-
Primitive.cexpr!(%q{ rb_ary_push(result, value) })
246+
until Primitive.rb_jit_ary_at_end(i)
247+
_value = yield(Primitive.rb_jit_ary_at(i))
248+
Primitive.cexpr!(%q{ rb_ary_push(result, _value) })
249+
i = Primitive.rb_jit_fixnum_inc(i)
250250
end
251251
result
252252
end
@@ -267,13 +267,14 @@ def select # :nodoc:
267267
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
268268
end
269269

270-
_i = 0
271-
value = nil
270+
i = 0
272271
result = Primitive.ary_sized_alloc
273-
while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
272+
until Primitive.rb_jit_ary_at_end(i)
273+
value = Primitive.rb_jit_ary_at(i)
274274
if yield value
275275
Primitive.cexpr!(%q{ rb_ary_push(result, value) })
276276
end
277+
i = Primitive.rb_jit_fixnum_inc(i)
277278
end
278279
result
279280
end
@@ -293,10 +294,11 @@ def find(if_none_proc = nil) # :nodoc:
293294
unless defined?(yield)
294295
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
295296
end
296-
_i = 0
297-
value = nil
298-
while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
297+
i = 0
298+
until Primitive.rb_jit_ary_at_end(i)
299+
value = Primitive.rb_jit_ary_at(i)
299300
return value if yield(value)
301+
i = Primitive.rb_jit_fixnum_inc(i)
300302
end
301303
if_none_proc&.call
302304
end

0 commit comments

Comments
 (0)