[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]