summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author卜部昌平 <shyouhei@ruby-lang.org>2020-06-16 14:31:11 +0900
committer卜部昌平 <shyouhei@ruby-lang.org>2020-06-29 11:05:41 +0900
commit9c5804ac1ce78126670082327fa3ab80cff0ee25 (patch)
tree104caddf513e1efb81bf4e54512bce6895d3180d
parentcc27cd26d728d285aed728e730994d31f5ac1241 (diff)
range_each: do not goto into a branch
I'm not necessarily against every goto in general, but jumping into a branch is definitely a bad idea. Better refactor.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3247
-rw-r--r--range.c56
1 files changed, 36 insertions, 20 deletions
diff --git a/range.c b/range.c
index d4732a1a82..b00800b3fb 100644
--- a/range.c
+++ b/range.c
@@ -829,6 +829,36 @@ range_enum_size(VALUE range, VALUE args, VALUE eobj)
return range_size(range);
}
+RBIMPL_ATTR_NORETURN()
+static void
+range_each_bignum_endless(VALUE beg)
+{
+ for (;; beg = rb_big_plus(beg, INT2FIX(1))) {
+ rb_yield(beg);
+ }
+}
+
+RBIMPL_ATTR_NORETURN()
+static void
+range_each_fixnum_endless(VALUE beg)
+{
+ for (long i = FIX2LONG(beg); FIXABLE(i); i++) {
+ rb_yield(LONG2FIX(i));
+ }
+
+ range_each_bignum_endless(LONG2NUM(RUBY_FIXNUM_MAX + 1));
+}
+
+static VALUE
+range_each_fixnum_loop(VALUE beg, VALUE end, VALUE range)
+{
+ long lim = FIX2LONG(end) + !EXCL(range);
+ for (long i = FIX2LONG(beg); i < lim; i++) {
+ rb_yield(LONG2FIX(i));
+ }
+ return range;
+}
+
/*
* call-seq:
* rng.each {| i | block } -> rng
@@ -854,7 +884,7 @@ static VALUE
range_each(VALUE range)
{
VALUE beg, end;
- long i, lim;
+ long i;
RETURN_SIZED_ENUMERATOR(range, 0, 0, range_enum_size);
@@ -862,24 +892,10 @@ range_each(VALUE range)
end = RANGE_END(range);
if (FIXNUM_P(beg) && NIL_P(end)) {
- fixnum_endless:
- i = FIX2LONG(beg);
- while (FIXABLE(i)) {
- rb_yield(LONG2FIX(i++));
- }
- beg = LONG2NUM(i);
- bignum_endless:
- for (;; beg = rb_big_plus(beg, INT2FIX(1)))
- rb_yield(beg);
+ range_each_fixnum_endless(beg);
}
else if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
- fixnum_loop:
- lim = FIX2LONG(end);
- if (!EXCL(range))
- lim += 1;
- for (i = FIX2LONG(beg); i < lim; i++) {
- rb_yield(LONG2FIX(i));
- }
+ return range_each_fixnum_loop(beg, end, range);
}
else if (RB_INTEGER_TYPE_P(beg) && (NIL_P(end) || RB_INTEGER_TYPE_P(end))) {
if (SPECIAL_CONST_P(end) || RBIGNUM_POSITIVE_P(end)) { /* end >= FIXNUM_MIN */
@@ -888,11 +904,11 @@ range_each(VALUE range)
do {
rb_yield(beg);
} while (!FIXNUM_P(beg = rb_big_plus(beg, INT2FIX(1))));
- if (NIL_P(end)) goto fixnum_endless;
- if (FIXNUM_P(end)) goto fixnum_loop;
+ if (NIL_P(end)) range_each_fixnum_endless(beg);
+ if (FIXNUM_P(end)) return range_each_fixnum_loop(beg, end, range);
}
else {
- if (NIL_P(end)) goto bignum_endless;
+ if (NIL_P(end)) range_each_bignum_endless(beg);
if (FIXNUM_P(end)) return range;
}
}