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

ruby-changes:22612

From: nobu <ko1@a...>
Date: Fri, 17 Feb 2012 13:25:04 +0900 (JST)
Subject: [ruby-changes:22612] nobu:r34661 (trunk): * enum.c: move work variables to objects not to let called blocks

nobu	2012-02-17 13:24:48 +0900 (Fri, 17 Feb 2012)

  New Revision: 34661

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=34661

  Log:
    * enum.c: move work variables to objects not to let called blocks
      access stack area out of scope.  [Bug #5801]

  Modified files:
    trunk/ChangeLog
    trunk/enum.c
    trunk/test/ruby/test_enum.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 34660)
+++ ChangeLog	(revision 34661)
@@ -1,3 +1,8 @@
+Fri Feb 17 13:24:43 2012  Nobuyoshi Nakada  <nobu@r...>
+
+	* enum.c: move work variables to objects not to let called blocks
+	  access stack area out of scope.  [Bug #5801]
+
 Fri Feb 17 12:35:55 2012  NARUSE, Yui  <naruse@r...>
 
 	* tool/merger.rb: remove borders from the commit message which is used
Index: enum.c
===================================================================
--- enum.c	(revision 34660)
+++ enum.c	(revision 34661)
@@ -13,7 +13,19 @@
 #include "ruby/util.h"
 #include "node.h"
 #include "id.h"
+#include "internal.h"
 
+#define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[1 - 2*!(expr)]
+
+#define NEW_MEMO(a, b, c) rb_node_newnode(NODE_MEMO, (a), (b), (c))
+
+#define roomof(x, y) ((sizeof(x) + sizeof(y) - 1) / sizeof(y))
+#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value))
+#define NEW_MEMO_FOR(type, value) \
+    (rb_ary_set_len(((value) = rb_ary_tmp_new(roomof(type, VALUE))), \
+		    roomof(type, VALUE)), \
+     MEMO_FOR(type, value))
+
 VALUE rb_mEnumerable;
 static ID id_next;
 #define id_each idEach
@@ -38,11 +50,11 @@
 static VALUE
 grep_i(VALUE i, VALUE args, int argc, VALUE *argv)
 {
-    VALUE *arg = (VALUE *)args;
+    NODE *memo = RNODE(args);
     ENUM_WANT_SVALUE();
 
-    if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
-	rb_ary_push(arg[1], i);
+    if (RTEST(rb_funcall(memo->u1.value, id_eqq, 1, i))) {
+	rb_ary_push(memo->u2.value, i);
     }
     return Qnil;
 }
@@ -50,11 +62,11 @@
 static VALUE
 grep_iter_i(VALUE i, VALUE args, int argc, VALUE *argv)
 {
-    VALUE *arg = (VALUE *)args;
+    NODE *memo = RNODE(args);
     ENUM_WANT_SVALUE();
 
-    if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
-	rb_ary_push(arg[1], rb_yield(i));
+    if (RTEST(rb_funcall(memo->u1.value, id_eqq, 1, i))) {
+	rb_ary_push(memo->u2.value, rb_yield(i));
     }
     return Qnil;
 }
@@ -81,25 +93,22 @@
 enum_grep(VALUE obj, VALUE pat)
 {
     VALUE ary = rb_ary_new();
-    VALUE arg[2];
+    NODE *memo = NEW_MEMO(pat, ary, 0);
 
-    arg[0] = pat;
-    arg[1] = ary;
+    rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)memo);
 
-    rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)arg);
-
     return ary;
 }
 
 static VALUE
 count_i(VALUE i, VALUE memop, int argc, VALUE *argv)
 {
-    VALUE *memo = (VALUE*)memop;
+    NODE *memo = RNODE(memop);
 
     ENUM_WANT_SVALUE();
 
-    if (rb_equal(i, memo[1])) {
-	memo[0]++;
+    if (rb_equal(i, memo->u1.value)) {
+	memo->u3.cnt++;
     }
     return Qnil;
 }
@@ -107,10 +116,10 @@
 static VALUE
 count_iter_i(VALUE i, VALUE memop, int argc, VALUE *argv)
 {
-    VALUE *memo = (VALUE*)memop;
+    NODE *memo = RNODE(memop);
 
     if (RTEST(enum_yield(argc, argv))) {
-	memo[0]++;
+	memo->u3.cnt++;
     }
     return Qnil;
 }
@@ -118,9 +127,9 @@
 static VALUE
 count_all_i(VALUE i, VALUE memop, int argc, VALUE *argv)
 {
-    VALUE *memo = (VALUE*)memop;
+    NODE *memo = RNODE(memop);
 
-    memo[0]++;
+    memo->u3.cnt++;
     return Qnil;
 }
 
@@ -146,7 +155,8 @@
 static VALUE
 enum_count(int argc, VALUE *argv, VALUE obj)
 {
-    VALUE memo[2];	/* [count, condition value] */
+    VALUE item = Qnil;
+    NODE *memo;
     rb_block_call_func *func;
 
     if (argc == 0) {
@@ -158,25 +168,27 @@
 	}
     }
     else {
-	rb_scan_args(argc, argv, "1", &memo[1]);
+	rb_scan_args(argc, argv, "1", &item);
 	if (rb_block_given_p()) {
 	    rb_warn("given block not used");
 	}
         func = count_i;
     }
 
-    memo[0] = 0;
-    rb_block_call(obj, id_each, 0, 0, func, (VALUE)&memo);
-    return INT2NUM(memo[0]);
+    memo = NEW_MEMO(item, 0, 0);
+    rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
+    return INT2NUM(memo->u3.cnt);
 }
 
 static VALUE
-find_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
+find_i(VALUE i, VALUE memop, int argc, VALUE *argv)
 {
     ENUM_WANT_SVALUE();
 
     if (RTEST(rb_yield(i))) {
-	*memo = i;
+	NODE *memo = RNODE(memop);
+	memo->u1.value = i;
+	memo->u3.cnt = 1;
 	rb_iter_break();
     }
     return Qnil;
@@ -204,14 +216,15 @@
 static VALUE
 enum_find(int argc, VALUE *argv, VALUE obj)
 {
-    VALUE memo = Qundef;
+    NODE *memo;
     VALUE if_none;
 
     rb_scan_args(argc, argv, "01", &if_none);
     RETURN_ENUMERATOR(obj, argc, argv);
-    rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)&memo);
-    if (memo != Qundef) {
-	return memo;
+    memo = NEW_MEMO(Qundef, 0, 0);
+    rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
+    if (memo->u3.cnt) {
+	return memo->u1.value;
     }
     if (!NIL_P(if_none)) {
 	return rb_funcall(if_none, rb_intern("call"), 0, 0);
@@ -222,28 +235,28 @@
 static VALUE
 find_index_i(VALUE i, VALUE memop, int argc, VALUE *argv)
 {
-    VALUE *memo = (VALUE*)memop;
+    NODE *memo = RNODE(memop);
 
     ENUM_WANT_SVALUE();
 
-    if (rb_equal(i, memo[2])) {
-	memo[0] = UINT2NUM(memo[1]);
+    if (rb_equal(i, memo->u2.value)) {
+	memo->u1.value = UINT2NUM(memo->u3.cnt);
 	rb_iter_break();
     }
-    memo[1]++;
+    memo->u3.cnt++;
     return Qnil;
 }
 
 static VALUE
 find_index_iter_i(VALUE i, VALUE memop, int argc, VALUE *argv)
 {
-    VALUE *memo = (VALUE*)memop;
+    NODE *memo = RNODE(memop);
 
     if (RTEST(enum_yield(argc, argv))) {
-	memo[0] = UINT2NUM(memo[1]);
+	memo->u1.value = UINT2NUM(memo->u3.cnt);
 	rb_iter_break();
     }
-    memo[1]++;
+    memo->u3.cnt++;
     return Qnil;
 }
 
@@ -269,7 +282,8 @@
 static VALUE
 enum_find_index(int argc, VALUE *argv, VALUE obj)
 {
-    VALUE memo[3];	/* [return value, current index, condition value] */
+    NODE *memo;	/* [return value, current index, ] */
+    VALUE condition_value = Qnil;
     rb_block_call_func *func;
 
     if (argc == 0) {
@@ -277,17 +291,16 @@
         func = find_index_iter_i;
     }
     else {
-	rb_scan_args(argc, argv, "1", &memo[2]);
+	rb_scan_args(argc, argv, "1", &condition_value);
 	if (rb_block_given_p()) {
 	    rb_warn("given block not used");
 	}
         func = find_index_i;
     }
 
-    memo[0] = Qnil;
-    memo[1] = 0;
+    memo = NEW_MEMO(Qnil, condition_value, 0);
     rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
-    return memo[0];
+    return memo->u1.value;
 }
 
 static VALUE
@@ -488,15 +501,16 @@
 static VALUE
 inject_i(VALUE i, VALUE p, int argc, VALUE *argv)
 {
-    VALUE *memo = (VALUE *)p;
+    NODE *memo = RNODE(p);
 
     ENUM_WANT_SVALUE();
 
-    if (memo[0] == Qundef) {
-	memo[0] = i;
+    if (memo->u2.argc == 0) {
+	memo->u2.argc = 1;
+	memo->u1.value = i;
     }
     else {
-	memo[0] = rb_yield_values(2, memo[0], i);
+	memo->u1.value = rb_yield_values(2, memo->u1.value, i);
     }
     return Qnil;
 }
@@ -504,15 +518,16 @@
 static VALUE
 inject_op_i(VALUE i, VALUE p, int argc, VALUE *argv)
 {
-    VALUE *memo = (VALUE *)p;
+    NODE *memo = RNODE(p);
 
     ENUM_WANT_SVALUE();
 
-    if (memo[0] == Qundef) {
-	memo[0] = i;
+    if (memo->u2.argc == 0) {
+	memo->u2.argc = 1;
+	memo->u1.value = i;
     }
     else {
-	memo[0] = rb_funcall(memo[0], (ID)memo[1], 1, i);
+	memo->u1.value = rb_funcall(memo->u1.value, memo->u3.id, 1, i);
     }
     return Qnil;
 }
@@ -563,45 +578,49 @@
 static VALUE
 enum_inject(int argc, VALUE *argv, VALUE obj)
 {
-    VALUE memo[2];
+    NODE *memo;
+    VALUE init, op;
     VALUE (*iter)(VALUE, VALUE, int, VALUE*) = inject_i;
 
-    switch (rb_scan_args(argc, argv, "02", &memo[0], &memo[1])) {
+    switch (rb_scan_args(argc, argv, "02", &init, &op)) {
       case 0:
-	memo[0] = Qundef;
 	break;
       case 1:
 	if (rb_block_given_p()) {
 	    break;
 	}
-	memo[1] = (VALUE)rb_to_id(memo[0]);
-	memo[0] = Qundef;
+	op = (VALUE)rb_to_id(init);
+	argc = 0;
+	init = Qnil;
 	iter = inject_op_i;
 	break;
       case 2:
 	if (rb_block_given_p()) {
 	    rb_warning("given block not used");
 	}
-	memo[1] = (VALUE)rb_to_id(memo[1]);
+	op = (VALUE)rb_to_id(op);
 	iter = inject_op_i;
 	break;
     }
+    memo = NEW_MEMO(init, argc, op);
     rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
-    if (memo[0] == Qundef) return Qnil;
-    return memo[0];
+    return memo->u1.value;
 }
 
 static VALUE
-partition_i(VALUE i, VALUE *ary, int argc, VALUE *argv)
+partition_i(VALUE i, VALUE arys, int argc, VALUE *argv)
 {
+    NODE *memo = RNODE(arys);
+    VALUE ary;
     ENUM_WANT_SVALUE();
 
     if (RTEST(rb_yield(i))) {
-	rb_ary_push(ary[0], i);
+	ary = memo->u1.value;
     }
     else {
-	rb_ary_push(ary[1], i);
+	ary = memo->u2.value;
     }
+    rb_ary_push(ary, i);
     return Qnil;
 }
 
@@ -623,15 +642,14 @@
 static VALUE
 enum_partition(VALUE obj)
 {
-    VALUE ary[2];
+    NODE *memo;
 
     RETURN_ENUMERATOR(obj, 0, 0);
 
-    ary[0] = rb_ary_new();
-    ary[1] = rb_ary_new();
-    rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)ary);
+    memo = NEW_MEMO(rb_ary_new(), rb_ary_new(), 0);
+    rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);
 
-    return rb_assoc_new(ary[0], ary[1]);
+    return rb_assoc_new(memo->u1.value, memo->u2.value);
 }
 
 static VALUE
@@ -644,7 +662,7 @@
 
     group = rb_yield(i);
     values = rb_hash_aref(hash, group);
-    if (NIL_P(values)) {
+    if (!RB_TYPE_P(values, T_ARRAY)) {
 	values = rb_ary_new3(1, i);
 	rb_hash_aset(hash, group, values);
     }
@@ -684,24 +702,30 @@
 }
 
 static VALUE
-first_i(VALUE i, VALUE *params, int argc, VALUE *argv)
+first_i(VALUE i, VALUE params, int argc, VALUE *argv)
 {
+    NODE *memo = RNODE(params);
     ENUM_WANT_SVALUE();
 
-    if (NIL_P(params[1])) {
-	params[1] = i;
+    memo->u1.value = i;
+    rb_iter_break();
+    return Qnil;		/* not reached */
+}
+
+static VALUE
+first_ary_i(VALUE i, VALUE params, int argc, VALUE *argv)
+{
+    NODE *memo = RNODE(params);
+    long n = memo->u3.cnt;
+
+    ENUM_WANT_SVALUE();
+
+    rb_ary_push(memo->u1.value, i);
+    n--;
+    if (n <= 0) {
 	rb_iter_break();
     }
-    else {
-	long n = params[0];
-
-	rb_ary_push(params[1], i);
-	n--;
-	if (n <= 0) {
-	    rb_iter_break();
-	}
-	params[0] = n;
-    }
+    memo->u3.cnt = n;
     return Qnil;
 }
 
@@ -724,26 +748,28 @@
 static VALUE
 enum_first(int argc, VALUE *argv, VALUE obj)
 {
-    VALUE n, params[2];
+    NODE *memo;
+    if (argc > 0) {
+	VALUE ary = Qnil;
+	VALUE n;
+	long len = 0;
 
-    if (argc == 0) {
-	params[0] = params[1] = Qnil;
-    }
-    else {
-	long len;
-
 	rb_scan_args(argc, argv, "01", &n);
 	len = NUM2LONG(n);
 	if (len == 0) return rb_ary_new2(0);
 	if (len < 0) {
 	    rb_raise(rb_eArgError, "negative length");
 	}
-	params[0] = len;
-	params[1] = rb_ary_new2(len);
+	ary = rb_ary_new2(len);
+	memo = NEW_MEMO(ary, 0, len);
+	rb_block_call(obj, id_each, 0, 0, first_ary_i, (VALUE)memo);
+	return ary;
     }
-    rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)params);
-
-    return params[1];
+    else {
+	memo = NEW_MEMO(Qnil, 0, 0);
+	rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
+	return memo->u1.value;
+    }
 }
 
 
@@ -774,13 +800,13 @@
 struct sort_by_data {
     VALUE ary;
     VALUE buf;
-    int n;
+    long n;
 };
 
 static VALUE
 sort_by_i(VALUE i, VALUE _data, int argc, VALUE *argv)
 {
-    struct sort_by_data *data = (struct sort_by_data *)_data;
+    struct sort_by_data *data = (struct sort_by_data *)&RNODE(_data)->u1;
     VALUE ary = data->ary;
     VALUE v;
 
@@ -896,9 +922,10 @@
 static VALUE
 enum_sort_by(VALUE obj)
 {
-    VALUE ary;
+    VALUE ary, buf;
+    NODE *memo;
     long i;
-    struct sort_by_data data;
+    struct sort_by_data *data;
 
     RETURN_ENUMERATOR(obj, 0, 0);
 
@@ -909,14 +936,20 @@
 	ary = rb_ary_new();
     }
     RBASIC(ary)->klass = 0;
-    data.ary = ary;
-    data.buf = rb_ary_tmp_new(SORT_BY_BUFSIZE*2);
-    data.n = 0;
-    rb_ary_store(data.buf, SORT_BY_BUFSIZE*2-1, Qnil);
-    rb_block_call(obj, id_each, 0, 0, sort_by_i, (VALUE)&data);
-    if (data.n) {
-	rb_ary_resize(data.buf, data.n*2);
-	rb_ary_concat(ary, data.buf);
+    buf = rb_ary_tmp_new(SORT_BY_BUFSIZE*2);
+    rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
+    memo = NEW_MEMO(0, 0, 0);
+    OBJ_INFECT(memo, obj);
+    data = (struct sort_by_data *)&memo->u1;
+    data->ary = ary;
+    data->buf = buf;
+    data->n = 0;
+    rb_block_call(obj, id_each, 0, 0, sort_by_i, (VALUE)memo);
+    ary = data->ary;
+    buf = data->buf;
+    if (data->n) {
+	rb_ary_resize(buf, data->n*2);
+	rb_ary_concat(ary, buf);
     }
     if (RARRAY_LEN(ary) > 2) {
 	ruby_qsort(RARRAY_PTR(ary), RARRAY_LEN(ary)/2, 2*sizeof(VALUE),
@@ -930,7 +963,7 @@
     }
     rb_ary_resize(ary, RARRAY_LEN(ary)/2);
     RBASIC(ary)->klass = rb_cArray;
-    OBJ_INFECT(ary, obj);
+    OBJ_INFECT(ary, memo);
 
     return ary;
 }
@@ -938,27 +971,27 @@
 #define ENUMFUNC(name) rb_block_given_p() ? name##_iter_i : name##_i
 
 #define DEFINE_ENUMFUNCS(name) \
-static VALUE enum_##name##_func(VALUE result, VALUE *memo); \
+static VALUE enum_##name##_func(VALUE result, NODE *memo); \
 \
 static VALUE \
-name##_i(VALUE i, VALUE *memo, int argc, VALUE *argv) \
+name##_i(VALUE i, VALUE memo, int argc, VALUE *argv) \
 { \
-    return enum_##name##_func(enum_values_pack(argc, argv), memo); \
+    return enum_##name##_func(enum_values_pack(argc, argv), RNODE(memo)); \
 } \
 \
 static VALUE \
-name##_iter_i(VALUE i, VALUE *memo, int argc, VALUE *argv) \
+name##_iter_i(VALUE i, VALUE memo, int argc, VALUE *argv) \
 { \
-    return enum_##name##_func(enum_yield(argc, argv), memo); \
+    return enum_##name##_func(enum_yield(argc, argv), RNODE(memo));	\
 } \
 \
 static VALUE \
-enum_##name##_func(VALUE result, VALUE *memo)
+enum_##name##_func(VALUE result, NODE *memo)
 
 DEFINE_ENUMFUNCS(all)
 {
     if (!RTEST(result)) {
-	*memo = Qfalse;
+	memo->u1.value = Qfalse;
 	rb_iter_break();
     }
     return Qnil;
@@ -984,16 +1017,15 @@
 static VALUE
 enum_all(VALUE obj)
 {
-    VALUE result = Qtrue;
-
-    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)&result);
-    return result;
+    NODE *memo = NEW_MEMO(Qtrue, 0, 0);
+    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
+    return memo->u1.value;
 }
 
 DEFINE_ENUMFUNCS(any)
 {
     if (RTEST(result)) {
-	*memo = Qtrue;
+	memo->u1.value = Qtrue;
 	rb_iter_break();
     }
     return Qnil;
@@ -1019,20 +1051,19 @@
 static VALUE
 enum_any(VALUE obj)
 {
-    VALUE result = Qfalse;
-
-    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)&result);
-    return result;
+    NODE *memo = NEW_MEMO(Qfalse, 0, 0);
+    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
+    return memo->u1.value;
 }
 
 DEFINE_ENUMFUNCS(one)
 {
     if (RTEST(result)) {
-	if (*memo == Qundef) {
-	    *memo = Qtrue;
+	if (memo->u1.value == Qundef) {
+	    memo->u1.value = Qtrue;
 	}
-	else if (*memo == Qtrue) {
-	    *memo = Qfalse;
+	else if (memo->u1.value == Qtrue) {
+	    memo->u1.value = Qfalse;
 	    rb_iter_break();
 	}
     }
@@ -1060,9 +1091,11 @@
 static VALUE
 enum_one(VALUE obj)
 {
-    VALUE result = Qundef;
+    NODE *memo = NEW_MEMO(Qundef, 0, 0);
+    VALUE result;
 
-    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)&result);
+    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
+    result = memo->u1.value;
     if (result == Qundef) return Qfalse;
     return result;
 }
@@ -1070,7 +1103,7 @@
 DEFINE_ENUMFUNCS(none)
 {
     if (RTEST(result)) {
-	*memo = Qfalse;
+	memo->u1.value = Qfalse;
 	rb_iter_break();
     }
     return Qnil;
@@ -1094,45 +1127,46 @@
 static VALUE
 enum_none(VALUE obj)
 {
-    VALUE result = Qtrue;
-
-    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)&result);
-    return result;
+    NODE *memo = NEW_MEMO(Qtrue, 0, 0);
+    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
+    return memo->u1.value;
 }
 
 static VALUE
-min_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
+min_i(VALUE i, VALUE args, int argc, VALUE *argv)
 {
     VALUE cmp;
+    NODE *memo = RNODE(args);
 
     ENUM_WANT_SVALUE();
 
-    if (*memo == Qundef) {
-	*memo = i;
+    if (memo->u1.value == Qundef) {
+	memo->u1.value = i;
     }
     else {
-	cmp = rb_funcall(i, id_cmp, 1, *memo);
-	if (rb_cmpint(cmp, i, *memo) < 0) {
-	    *memo = i;
+	cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
+	if (rb_cmpint(cmp, i, memo->u1.value) < 0) {
+	    memo->u1.value = i;
 	}
     }
     return Qnil;
 }
 
 static VALUE
-min_ii(VALUE i, VALUE *memo, int argc, VALUE *argv)
+min_ii(VALUE i, VALUE args, int argc, VALUE *argv)
 {
     VALUE cmp;
+    NODE *memo = RNODE(args);
 
     ENUM_WANT_SVALUE();
 
-    if (*memo == Qundef) {
-	*memo = i;
+    if (memo->u1.value == Qundef) {
+	memo->u1.value = i;
     }
     else {
-	cmp = rb_yield_values(2, i, *memo);
-	if (rb_cmpint(cmp, i, *memo) < 0) {
-	    *memo = i;
+	cmp = rb_yield_values(2, i, memo->u1.value);
+	if (rb_cmpint(cmp, i, memo->u1.value) < 0) {
+	    memo->u1.value = i;
 	}
     }
     return Qnil;
@@ -1156,51 +1190,55 @@
 static VALUE
 enum_min(VALUE obj)
 {
-    VALUE result = Qundef;
+    NODE *memo = NEW_MEMO(Qundef, 0, 0);
+    VALUE result;
 
     if (rb_block_given_p()) {
-	rb_block_call(obj, id_each, 0, 0, min_ii, (VALUE)&result);
+	rb_block_call(obj, id_each, 0, 0, min_ii, (VALUE)memo);
     }
     else {
-	rb_block_call(obj, id_each, 0, 0, min_i, (VALUE)&result);
+	rb_block_call(obj, id_each, 0, 0, min_i, (VALUE)memo);
     }
+    result = memo->u1.value;
     if (result == Qundef) return Qnil;
     return result;
 }
 
 static VALUE
-max_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
+max_i(VALUE i, VALUE args, int argc, VALUE *argv)
 {
+    NODE *memo = RNODE(args);
     VALUE cmp;
 
     ENUM_WANT_SVALUE();
 
-    if (*memo == Qundef) {
-	*memo = i;
+    if (memo->u1.value == Qundef) {
+	memo->u1.value = i;
     }
     else {
-	cmp = rb_funcall(i, id_cmp, 1, *memo);
-	if (rb_cmpint(cmp, i, *memo) > 0) {
-	    *memo = i;
+	cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
+	if (rb_cmpint(cmp, i, memo->u1.value) > 0) {
+	    memo->u1.value = i;
 	}
     }
     return Qnil;
 }
 
 static VALUE
-max_ii(VALUE i, VALUE *memo, int argc, VALUE *argv)
+max_ii(VALUE i, VALUE args, int argc, VALUE *argv)
 {
+    NODE *memo = RNODE(args);
     VALUE cmp;
 
     ENUM_WANT_SVALUE();
 
-    if (*memo == Qundef) {
-	*memo = i;
+    if (memo->u1.value == Qundef) {
+	memo->u1.value = i;
     }
     else {
-	cmp = rb_yield_values(2, i, *memo);
-	if (rb_cmpint(cmp, i, *memo) > 0) {
-	    *memo = i;
+	cmp = rb_yield_values(2, i, memo->u1.value);
+	if (rb_cmpint(cmp, i, memo->u1.value) > 0) {
+	    memo->u1.value = i;
 	}
     }
     return Qnil;
@@ -1223,14 +1261,16 @@
 static VALUE
 enum_max(VALUE obj)
 {
-    VALUE result = Qundef;
+    NODE *memo = NEW_MEMO(Qundef, 0, 0);
+    VALUE result;
 
     if (rb_block_given_p()) {
-	rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)&result);
+	rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)memo);
     }
     else {
-	rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)&result);
+	rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)memo);
     }
+    result = memo->u1.value;
     if (result == Qundef) return Qnil;
     return result;
 }
@@ -1241,6 +1281,8 @@
     VALUE last;
 };
 
+STATIC_ASSERT(minmax_t, sizeof(struct minmax_t) <= sizeof(NODE) - offsetof(NODE, u1));
+
 static void
 minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo)
 {
@@ -1265,7 +1307,7 @@
 static VALUE
 minmax_i(VALUE i, VALUE _memo, int argc, VALUE *argv)
 {
-    struct minmax_t *memo = (struct minmax_t *)_memo;
+    struct minmax_t *memo = (struct minmax_t *)&RNODE(_memo)->u1.value;
     int n;
     VALUE j;
 
@@ -1317,7 +1359,7 @@
 static VALUE
 minmax_ii(VALUE i, VALUE _memo, int argc, VALUE *argv)
 {
-    struct minmax_t *memo = (struct minmax_t *)_memo;
+    struct minmax_t *memo = (struct minmax_t *)&RNODE(_memo)->u1.value;
     int n;
     VALUE j;
 
@@ -1363,43 +1405,45 @@
 static VALUE
 enum_minmax(VALUE obj)
 {
-    struct minmax_t (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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