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/