ruby-changes:51348
From: nobu <ko1@a...>
Date: Sat, 2 Jun 2018 16:50:23 +0900 (JST)
Subject: [ruby-changes:51348] nobu:r63554 (trunk): enum.c: bignum counter
nobu 2018-06-02 16:50:18 +0900 (Sat, 02 Jun 2018) New Revision: 63554 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=63554 Log: enum.c: bignum counter * enum.c (imemo_count_up, imemo_count_value): promote the counter value to a bignum on overflow. [Bug #14805] Modified files: trunk/enum.c Index: enum.c =================================================================== --- enum.c (revision 63553) +++ enum.c (revision 63554) @@ -142,6 +142,34 @@ enum_grep_v(VALUE obj, VALUE pat) https://github.com/ruby/ruby/blob/trunk/enum.c#L142 return ary; } +#define COUNT_BIGNUM IMEMO_FL_USER0 +#define MEMO_V3_SET(m, v) RB_OBJ_WRITE((m), &(m)->u3.value, (v)) + +static void +imemo_count_up(struct MEMO *memo) +{ + if (memo->flags & COUNT_BIGNUM) { + MEMO_V3_SET(memo, rb_int_succ(memo->u3.value)); + } + else if (++memo->u3.cnt == 0) { + /* overflow */ + unsigned long buf[2] = {0, 1}; + MEMO_V3_SET(memo, rb_big_unpack(buf, 2)); + memo->flags |= COUNT_BIGNUM; + } +} + +static VALUE +imemo_count_value(struct MEMO *memo) +{ + if (memo->flags & COUNT_BIGNUM) { + return memo->u3.value; + } + else { + return ULONG2NUM(memo->u3.cnt); + } +} + static VALUE count_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop)) { @@ -150,7 +178,7 @@ count_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, me https://github.com/ruby/ruby/blob/trunk/enum.c#L178 ENUM_WANT_SVALUE(); if (rb_equal(i, memo->v1)) { - memo->u3.cnt++; + imemo_count_up(memo); } return Qnil; } @@ -161,7 +189,7 @@ count_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST( https://github.com/ruby/ruby/blob/trunk/enum.c#L189 struct MEMO *memo = MEMO_CAST(memop); if (RTEST(rb_yield_values2(argc, argv))) { - memo->u3.cnt++; + imemo_count_up(memo); } return Qnil; } @@ -171,7 +199,7 @@ count_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i https://github.com/ruby/ruby/blob/trunk/enum.c#L199 { struct MEMO *memo = MEMO_CAST(memop); - memo->u3.cnt++; + imemo_count_up(memo); return Qnil; } @@ -218,7 +246,7 @@ enum_count(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/enum.c#L246 memo = MEMO_NEW(item, 0, 0); rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo); - return ULONG2NUM(memo->u3.cnt); + return imemo_count_value(memo); } static VALUE @@ -286,10 +314,10 @@ find_index_i(RB_BLOCK_CALL_FUNC_ARGLIST( https://github.com/ruby/ruby/blob/trunk/enum.c#L314 ENUM_WANT_SVALUE(); if (rb_equal(i, memo->v2)) { - MEMO_V1_SET(memo, ULONG2NUM(memo->u3.cnt)); + MEMO_V1_SET(memo, imemo_count_value(memo)); rb_iter_break(); } - memo->u3.cnt++; + imemo_count_up(memo); return Qnil; } @@ -299,10 +327,10 @@ find_index_iter_i(RB_BLOCK_CALL_FUNC_ARG https://github.com/ruby/ruby/blob/trunk/enum.c#L327 struct MEMO *memo = MEMO_CAST(memop); if (RTEST(rb_yield_values2(argc, argv))) { - MEMO_V1_SET(memo, ULONG2NUM(memo->u3.cnt)); + MEMO_V1_SET(memo, imemo_count_value(memo)); rb_iter_break(); } - memo->u3.cnt++; + imemo_count_up(memo); return Qnil; } @@ -2232,9 +2260,11 @@ enum_member(VALUE obj, VALUE val) https://github.com/ruby/ruby/blob/trunk/enum.c#L2260 static VALUE each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) { - long n = MEMO_CAST(memo)->u3.cnt++; + struct MEMO *m = MEMO_CAST(memo); + VALUE n = imemo_count_value(m); - return rb_yield_values(2, rb_enum_values_pack(argc, argv), ULONG2NUM(n)); + imemo_count_up(m); + return rb_yield_values(2, rb_enum_values_pack(argc, argv), n); } /* -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/