* internal.h: use T_IMEMO to represent `struct MEMO' value.

memo->v1 and memo->v2 is WB protected values.
  So use MEMO_V1/V2_SET() macros to set these values.
  memo->u3 is ambiguous (sometimes a VALUE, sometimes an integer
  value), so use gc_mark_maybe() in gc.c to mark it.
  Rename NEW_MEMO() to MEMO_NEW().
  Move MEMO_FOR and NEW_MEMO_FOF macros from node.h.
  Export a rb_imemo_new() function for ext/ripper.
* node.h: remove NODE_MEMO.
* enum.c: catch up these change.
* enumerator.c: ditto.
* load.c: ditto.
* ext/objspace/objspace.c (count_nodes): ditto.
* gc.c (gc_mark_children): mark imemo_memo type.
* parse.y (new_args_gen): use T_IMEMO.
  (I'm not sure it is working correctly...)



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49942 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2015-03-11 23:13:01 +00:00
Родитель 287b046fab
Коммит 08f3cfb585
9 изменённых файлов: 119 добавлений и 85 удалений

Просмотреть файл

@ -1,3 +1,32 @@
Thu Mar 12 07:44:17 2015 Koichi Sasada <ko1@atdot.net>
* internal.h: use T_IMEMO to represent `struct MEMO' value.
memo->v1 and memo->v2 is WB protected values.
So use MEMO_V1/V2_SET() macros to set these values.
memo->u3 is ambiguous (sometimes a VALUE, sometimes an integer
value), so use gc_mark_maybe() in gc.c to mark it.
Rename NEW_MEMO() to MEMO_NEW().
Move MEMO_FOR and NEW_MEMO_FOF macros from node.h.
Export a rb_imemo_new() function for ext/ripper.
* node.h: remove NODE_MEMO.
* enum.c: catch up these change.
* enumerator.c: ditto.
* load.c: ditto.
* ext/objspace/objspace.c (count_nodes): ditto.
* gc.c (gc_mark_children): mark imemo_memo type.
* parse.y (new_args_gen): use T_IMEMO.
(I'm not sure it is working correctly...)
Wed Mar 11 22:36:34 2015 Koichi Sasada <ko1@atdot.net> Wed Mar 11 22:36:34 2015 Koichi Sasada <ko1@atdot.net>
* eval.c (frame_called_id): it should use vm_ifunc type. * eval.c (frame_called_id): it should use vm_ifunc type.

117
enum.c
Просмотреть файл

@ -11,7 +11,6 @@
#include "internal.h" #include "internal.h"
#include "ruby/util.h" #include "ruby/util.h"
#include "node.h"
#include "id.h" #include "id.h"
VALUE rb_mEnumerable; VALUE rb_mEnumerable;
@ -86,7 +85,7 @@ static VALUE
enum_grep(VALUE obj, VALUE pat) enum_grep(VALUE obj, VALUE pat)
{ {
VALUE ary = rb_ary_new(); VALUE ary = rb_ary_new();
struct MEMO *memo = NEW_MEMO(pat, ary, 0); struct MEMO *memo = MEMO_NEW(pat, ary, 0);
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)memo);
@ -167,7 +166,7 @@ enum_count(int argc, VALUE *argv, VALUE obj)
func = count_i; func = count_i;
} }
memo = NEW_MEMO(item, 0, 0); memo = MEMO_NEW(item, 0, 0);
rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
return INT2NUM(memo->u3.cnt); return INT2NUM(memo->u3.cnt);
} }
@ -179,7 +178,7 @@ find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
if (RTEST(rb_yield(i))) { if (RTEST(rb_yield(i))) {
struct MEMO *memo = MEMO_CAST(memop); struct MEMO *memo = MEMO_CAST(memop);
memo->v1 = i; MEMO_V1_SET(memo, i);
memo->u3.cnt = 1; memo->u3.cnt = 1;
rb_iter_break(); rb_iter_break();
} }
@ -213,7 +212,7 @@ enum_find(int argc, VALUE *argv, VALUE obj)
rb_scan_args(argc, argv, "01", &if_none); rb_scan_args(argc, argv, "01", &if_none);
RETURN_ENUMERATOR(obj, argc, argv); RETURN_ENUMERATOR(obj, argc, argv);
memo = NEW_MEMO(Qundef, 0, 0); memo = MEMO_NEW(Qundef, 0, 0);
rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
if (memo->u3.cnt) { if (memo->u3.cnt) {
return memo->v1; return memo->v1;
@ -232,7 +231,7 @@ find_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
ENUM_WANT_SVALUE(); ENUM_WANT_SVALUE();
if (rb_equal(i, memo->v2)) { if (rb_equal(i, memo->v2)) {
memo->v1 = UINT2NUM(memo->u3.cnt); MEMO_V1_SET(memo, UINT2NUM(memo->u3.cnt));
rb_iter_break(); rb_iter_break();
} }
memo->u3.cnt++; memo->u3.cnt++;
@ -245,7 +244,7 @@ find_index_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
struct MEMO *memo = MEMO_CAST(memop); struct MEMO *memo = MEMO_CAST(memop);
if (RTEST(enum_yield(argc, argv))) { if (RTEST(enum_yield(argc, argv))) {
memo->v1 = UINT2NUM(memo->u3.cnt); MEMO_V1_SET(memo, UINT2NUM(memo->u3.cnt));
rb_iter_break(); rb_iter_break();
} }
memo->u3.cnt++; memo->u3.cnt++;
@ -290,7 +289,7 @@ enum_find_index(int argc, VALUE *argv, VALUE obj)
func = find_index_i; func = find_index_i;
} }
memo = NEW_MEMO(Qnil, condition_value, 0); memo = MEMO_NEW(Qnil, condition_value, 0);
rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
return memo->v1; return memo->v1;
} }
@ -571,10 +570,10 @@ inject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
ENUM_WANT_SVALUE(); ENUM_WANT_SVALUE();
if (memo->v1 == Qundef) { if (memo->v1 == Qundef) {
memo->v1 = i; MEMO_V1_SET(memo, i);
} }
else { else {
memo->v1 = rb_yield_values(2, memo->v1, i); MEMO_V1_SET(memo, rb_yield_values(2, memo->v1, i));
} }
return Qnil; return Qnil;
} }
@ -588,17 +587,17 @@ inject_op_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
ENUM_WANT_SVALUE(); ENUM_WANT_SVALUE();
if (memo->v1 == Qundef) { if (memo->v1 == Qundef) {
memo->v1 = i; MEMO_V1_SET(memo, i);
} }
else if (SYMBOL_P(name = memo->u3.value)) { else if (SYMBOL_P(name = memo->u3.value)) {
const ID mid = SYM2ID(name); const ID mid = SYM2ID(name);
memo->v1 = rb_funcall(memo->v1, mid, 1, i); MEMO_V1_SET(memo, rb_funcall(memo->v1, mid, 1, i));
} }
else { else {
VALUE args[2]; VALUE args[2];
args[0] = name; args[0] = name;
args[1] = i; args[1] = i;
memo->v1 = rb_f_send(numberof(args), args, memo->v1); MEMO_V1_SET(memo, rb_f_send(numberof(args), args, memo->v1));
} }
return Qnil; return Qnil;
} }
@ -676,7 +675,7 @@ enum_inject(int argc, VALUE *argv, VALUE obj)
iter = inject_op_i; iter = inject_op_i;
break; break;
} }
memo = NEW_MEMO(init, Qnil, op); memo = MEMO_NEW(init, Qnil, op);
rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
if (memo->v1 == Qundef) return Qnil; if (memo->v1 == Qundef) return Qnil;
return memo->v1; return memo->v1;
@ -721,7 +720,7 @@ enum_partition(VALUE obj)
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size); RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
memo = NEW_MEMO(rb_ary_new(), rb_ary_new(), 0); memo = MEMO_NEW(rb_ary_new(), rb_ary_new(), 0);
rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);
return rb_assoc_new(memo->v1, memo->v2); return rb_assoc_new(memo->v1, memo->v2);
@ -782,7 +781,7 @@ first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))
struct MEMO *memo = MEMO_CAST(params); struct MEMO *memo = MEMO_CAST(params);
ENUM_WANT_SVALUE(); ENUM_WANT_SVALUE();
memo->v1 = i; MEMO_V1_SET(memo, i);
rb_iter_break(); rb_iter_break();
UNREACHABLE; UNREACHABLE;
@ -815,7 +814,7 @@ enum_first(int argc, VALUE *argv, VALUE obj)
return enum_take(obj, argv[0]); return enum_take(obj, argv[0]);
} }
else { else {
memo = NEW_MEMO(Qnil, 0, 0); memo = MEMO_NEW(Qnil, 0, 0);
rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
return memo->v1; return memo->v1;
} }
@ -987,7 +986,7 @@ enum_sort_by(VALUE obj)
RBASIC_CLEAR_CLASS(ary); RBASIC_CLEAR_CLASS(ary);
buf = rb_ary_tmp_new(SORT_BY_BUFSIZE*2); buf = rb_ary_tmp_new(SORT_BY_BUFSIZE*2);
rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil); rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
memo = NEW_MEMO(0, 0, 0); memo = MEMO_NEW(0, 0, 0);
OBJ_INFECT(memo, obj); OBJ_INFECT(memo, obj);
data = (struct sort_by_data *)&memo->v1; data = (struct sort_by_data *)&memo->v1;
data->ary = ary; data->ary = ary;
@ -1041,7 +1040,7 @@ enum_##name##_func(VALUE result, struct MEMO *memo)
DEFINE_ENUMFUNCS(all) DEFINE_ENUMFUNCS(all)
{ {
if (!RTEST(result)) { if (!RTEST(result)) {
memo->v1 = Qfalse; MEMO_V1_SET(memo, Qfalse);
rb_iter_break(); rb_iter_break();
} }
return Qnil; return Qnil;
@ -1067,7 +1066,7 @@ DEFINE_ENUMFUNCS(all)
static VALUE static VALUE
enum_all(VALUE obj) enum_all(VALUE obj)
{ {
struct MEMO *memo = NEW_MEMO(Qtrue, 0, 0); struct MEMO *memo = MEMO_NEW(Qtrue, 0, 0);
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo); rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
return memo->v1; return memo->v1;
} }
@ -1075,7 +1074,7 @@ enum_all(VALUE obj)
DEFINE_ENUMFUNCS(any) DEFINE_ENUMFUNCS(any)
{ {
if (RTEST(result)) { if (RTEST(result)) {
memo->v1 = Qtrue; MEMO_V1_SET(memo, Qtrue);
rb_iter_break(); rb_iter_break();
} }
return Qnil; return Qnil;
@ -1101,7 +1100,7 @@ DEFINE_ENUMFUNCS(any)
static VALUE static VALUE
enum_any(VALUE obj) enum_any(VALUE obj)
{ {
struct MEMO *memo = NEW_MEMO(Qfalse, 0, 0); struct MEMO *memo = MEMO_NEW(Qfalse, 0, 0);
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo); rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
return memo->v1; return memo->v1;
} }
@ -1110,10 +1109,10 @@ DEFINE_ENUMFUNCS(one)
{ {
if (RTEST(result)) { if (RTEST(result)) {
if (memo->v1 == Qundef) { if (memo->v1 == Qundef) {
memo->v1 = Qtrue; MEMO_V1_SET(memo, Qtrue);
} }
else if (memo->v1 == Qtrue) { else if (memo->v1 == Qtrue) {
memo->v1 = Qfalse; MEMO_V1_SET(memo, Qfalse);
rb_iter_break(); rb_iter_break();
} }
} }
@ -1344,7 +1343,7 @@ nmin_run(VALUE obj, VALUE num, int by, int rev)
static VALUE static VALUE
enum_one(VALUE obj) enum_one(VALUE obj)
{ {
struct MEMO *memo = NEW_MEMO(Qundef, 0, 0); struct MEMO *memo = MEMO_NEW(Qundef, 0, 0);
VALUE result; VALUE result;
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo); rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
@ -1356,7 +1355,7 @@ enum_one(VALUE obj)
DEFINE_ENUMFUNCS(none) DEFINE_ENUMFUNCS(none)
{ {
if (RTEST(result)) { if (RTEST(result)) {
memo->v1 = Qfalse; MEMO_V1_SET(memo, Qfalse);
rb_iter_break(); rb_iter_break();
} }
return Qnil; return Qnil;
@ -1380,7 +1379,7 @@ DEFINE_ENUMFUNCS(none)
static VALUE static VALUE
enum_none(VALUE obj) enum_none(VALUE obj)
{ {
struct MEMO *memo = NEW_MEMO(Qtrue, 0, 0); struct MEMO *memo = MEMO_NEW(Qtrue, 0, 0);
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo); rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
return memo->v1; return memo->v1;
} }
@ -1394,12 +1393,12 @@ min_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
ENUM_WANT_SVALUE(); ENUM_WANT_SVALUE();
if (memo->v1 == Qundef) { if (memo->v1 == Qundef) {
memo->v1 = i; MEMO_V1_SET(memo, i);
} }
else { else {
cmp = rb_funcall(i, id_cmp, 1, memo->v1); cmp = rb_funcall(i, id_cmp, 1, memo->v1);
if (rb_cmpint(cmp, i, memo->v1) < 0) { if (rb_cmpint(cmp, i, memo->v1) < 0) {
memo->v1 = i; MEMO_V1_SET(memo, i);
} }
} }
return Qnil; return Qnil;
@ -1414,12 +1413,12 @@ min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
ENUM_WANT_SVALUE(); ENUM_WANT_SVALUE();
if (memo->v1 == Qundef) { if (memo->v1 == Qundef) {
memo->v1 = i; MEMO_V1_SET(memo, i);
} }
else { else {
cmp = rb_yield_values(2, i, memo->v1); cmp = rb_yield_values(2, i, memo->v1);
if (rb_cmpint(cmp, i, memo->v1) < 0) { if (rb_cmpint(cmp, i, memo->v1) < 0) {
memo->v1 = i; MEMO_V1_SET(memo, i);
} }
} }
return Qnil; return Qnil;
@ -1452,7 +1451,7 @@ min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
static VALUE static VALUE
enum_min(int argc, VALUE *argv, VALUE obj) enum_min(int argc, VALUE *argv, VALUE obj)
{ {
struct MEMO *memo = NEW_MEMO(Qundef, 0, 0); struct MEMO *memo = MEMO_NEW(Qundef, 0, 0);
VALUE result; VALUE result;
VALUE num; VALUE num;
@ -1481,12 +1480,12 @@ max_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
ENUM_WANT_SVALUE(); ENUM_WANT_SVALUE();
if (memo->v1 == Qundef) { if (memo->v1 == Qundef) {
memo->v1 = i; MEMO_V1_SET(memo, i);
} }
else { else {
cmp = rb_funcall(i, id_cmp, 1, memo->v1); cmp = rb_funcall(i, id_cmp, 1, memo->v1);
if (rb_cmpint(cmp, i, memo->v1) > 0) { if (rb_cmpint(cmp, i, memo->v1) > 0) {
memo->v1 = i; MEMO_V1_SET(memo, i);
} }
} }
return Qnil; return Qnil;
@ -1501,12 +1500,12 @@ max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
ENUM_WANT_SVALUE(); ENUM_WANT_SVALUE();
if (memo->v1 == Qundef) { if (memo->v1 == Qundef) {
memo->v1 = i; MEMO_V1_SET(memo, i);
} }
else { else {
cmp = rb_yield_values(2, i, memo->v1); cmp = rb_yield_values(2, i, memo->v1);
if (rb_cmpint(cmp, i, memo->v1) > 0) { if (rb_cmpint(cmp, i, memo->v1) > 0) {
memo->v1 = i; MEMO_V1_SET(memo, i);
} }
} }
return Qnil; return Qnil;
@ -1538,7 +1537,7 @@ max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
static VALUE static VALUE
enum_max(int argc, VALUE *argv, VALUE obj) enum_max(int argc, VALUE *argv, VALUE obj)
{ {
struct MEMO *memo = NEW_MEMO(Qundef, 0, 0); struct MEMO *memo = MEMO_NEW(Qundef, 0, 0);
VALUE result; VALUE result;
VALUE num; VALUE num;
@ -1564,7 +1563,7 @@ struct minmax_t {
VALUE last; VALUE last;
}; };
STATIC_ASSERT(minmax_t, sizeof(struct minmax_t) <= sizeof(NODE) - offsetof(NODE, u1)); STATIC_ASSERT(minmax_t, sizeof(struct minmax_t) <= sizeof(struct MEMO) - offsetof(struct MEMO, v1));
static void static void
minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo) minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo)
@ -1688,7 +1687,7 @@ minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
static VALUE static VALUE
enum_minmax(VALUE obj) enum_minmax(VALUE obj)
{ {
struct MEMO *memo = NEW_MEMO(Qundef, Qundef, Qundef); struct MEMO *memo = MEMO_NEW(Qundef, Qundef, Qundef);
struct minmax_t *m = (struct minmax_t *)&memo->v1; struct minmax_t *m = (struct minmax_t *)&memo->v1;
VALUE ary = rb_ary_new3(2, Qnil, Qnil); VALUE ary = rb_ary_new3(2, Qnil, Qnil);
@ -1721,12 +1720,12 @@ min_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
v = rb_yield(i); v = rb_yield(i);
if (memo->v1 == Qundef) { if (memo->v1 == Qundef) {
memo->v1 = v; MEMO_V1_SET(memo, v);
memo->v2 = i; MEMO_V2_SET(memo, i);
} }
else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->v1), v, memo->v1) < 0) { else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->v1), v, memo->v1) < 0) {
memo->v1 = v; MEMO_V1_SET(memo, v);
memo->v2 = i; MEMO_V2_SET(memo, i);
} }
return Qnil; return Qnil;
} }
@ -1766,7 +1765,7 @@ enum_min_by(int argc, VALUE *argv, VALUE obj)
if (!NIL_P(num)) if (!NIL_P(num))
return nmin_run(obj, num, 1, 0); return nmin_run(obj, num, 1, 0);
memo = NEW_MEMO(Qundef, Qnil, 0); memo = MEMO_NEW(Qundef, Qnil, 0);
rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
return memo->v2; return memo->v2;
} }
@ -1781,12 +1780,12 @@ max_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
v = rb_yield(i); v = rb_yield(i);
if (memo->v1 == Qundef) { if (memo->v1 == Qundef) {
memo->v1 = v; MEMO_V1_SET(memo, v);
memo->v2 = i; MEMO_V2_SET(memo, i);
} }
else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->v1), v, memo->v1) > 0) { else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->v1), v, memo->v1) > 0) {
memo->v1 = v; MEMO_V1_SET(memo, v);
memo->v2 = i; MEMO_V2_SET(memo, i);
} }
return Qnil; return Qnil;
} }
@ -1871,7 +1870,7 @@ enum_max_by(int argc, VALUE *argv, VALUE obj)
if (!NIL_P(num)) if (!NIL_P(num))
return nmin_run(obj, num, 1, 1); return nmin_run(obj, num, 1, 1);
memo = NEW_MEMO(Qundef, Qnil, 0); memo = MEMO_NEW(Qundef, Qnil, 0);
rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
return memo->v2; return memo->v2;
} }
@ -1988,7 +1987,7 @@ member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args))
struct MEMO *memo = MEMO_CAST(args); struct MEMO *memo = MEMO_CAST(args);
if (rb_equal(rb_enum_values_pack(argc, argv), memo->v1)) { if (rb_equal(rb_enum_values_pack(argc, argv), memo->v1)) {
memo->v2 = Qtrue; MEMO_V2_SET(memo, Qtrue);
rb_iter_break(); rb_iter_break();
} }
return Qnil; return Qnil;
@ -2010,7 +2009,7 @@ member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args))
static VALUE static VALUE
enum_member(VALUE obj, VALUE val) enum_member(VALUE obj, VALUE val)
{ {
struct MEMO *memo = NEW_MEMO(val, Qfalse, 0); struct MEMO *memo = MEMO_NEW(val, Qfalse, 0);
rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
return memo->v2; return memo->v2;
@ -2050,7 +2049,7 @@ enum_each_with_index(int argc, VALUE *argv, VALUE obj)
RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size); RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
memo = NEW_MEMO(0, 0, 0); memo = MEMO_NEW(0, 0, 0);
rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo); rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo);
return obj; return obj;
} }
@ -2154,7 +2153,7 @@ each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, m))
v = rb_yield(ary); v = rb_yield(ary);
if (memo->v2) { if (memo->v2) {
memo->v1 = rb_ary_new2(size); MEMO_V1_SET(memo, rb_ary_new2(size));
} }
else { else {
rb_ary_clear(ary); rb_ary_clear(ary);
@ -2207,7 +2206,7 @@ enum_each_slice(VALUE obj, VALUE n)
size = limit_by_enum_size(obj, size); size = limit_by_enum_size(obj, size);
ary = rb_ary_new2(size); ary = rb_ary_new2(size);
arity = rb_block_arity(); arity = rb_block_arity();
memo = NEW_MEMO(ary, dont_recycle_block_arg(arity), size); memo = MEMO_NEW(ary, dont_recycle_block_arg(arity), size);
rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
ary = memo->v1; ary = memo->v1;
if (RARRAY_LEN(ary) > 0) rb_yield(ary); if (RARRAY_LEN(ary) > 0) rb_yield(ary);
@ -2283,7 +2282,7 @@ enum_each_cons(VALUE obj, VALUE n)
RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size); RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size);
arity = rb_block_arity(); arity = rb_block_arity();
if (enum_size_over_p(obj, size)) return Qnil; if (enum_size_over_p(obj, size)) return Qnil;
memo = NEW_MEMO(rb_ary_new2(size), dont_recycle_block_arg(arity), size); memo = MEMO_NEW(rb_ary_new2(size), dont_recycle_block_arg(arity), size);
rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo);
return Qnil; return Qnil;
@ -2457,7 +2456,7 @@ enum_zip(int argc, VALUE *argv, VALUE obj)
} }
/* TODO: use NODE_DOT2 as memo(v, v, -) */ /* TODO: use NODE_DOT2 as memo(v, v, -) */
memo = NEW_MEMO(result, args, 0); memo = MEMO_NEW(result, args, 0);
rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
return result; return result;
@ -2497,7 +2496,7 @@ enum_take(VALUE obj, VALUE n)
if (len == 0) return rb_ary_new2(0); if (len == 0) return rb_ary_new2(0);
result = rb_ary_new2(len); result = rb_ary_new2(len);
memo = NEW_MEMO(result, 0, len); memo = MEMO_NEW(result, 0, len);
rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)memo);
return result; return result;
} }
@ -2574,7 +2573,7 @@ enum_drop(VALUE obj, VALUE n)
} }
result = rb_ary_new(); result = rb_ary_new();
memo = NEW_MEMO(result, 0, len); memo = MEMO_NEW(result, 0, len);
rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)memo);
return result; return result;
} }
@ -2619,7 +2618,7 @@ enum_drop_while(VALUE obj)
RETURN_ENUMERATOR(obj, 0, 0); RETURN_ENUMERATOR(obj, 0, 0);
result = rb_ary_new(); result = rb_ary_new();
memo = NEW_MEMO(result, 0, FALSE); memo = MEMO_NEW(result, 0, FALSE);
rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)memo); rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)memo);
return result; return result;
} }

Просмотреть файл

@ -13,7 +13,6 @@
************************************************/ ************************************************/
#include "internal.h" #include "internal.h"
#include "node.h"
/* /*
* Document-class: Enumerator * Document-class: Enumerator
@ -496,7 +495,7 @@ enumerator_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
{ {
struct MEMO *memo = (struct MEMO *)m; struct MEMO *memo = (struct MEMO *)m;
VALUE idx = memo->v1; VALUE idx = memo->v1;
memo->v1 = rb_int_succ(idx); MEMO_V1_SET(memo, rb_int_succ(idx));
if (argc <= 1) if (argc <= 1)
return rb_yield_values(2, val, idx); return rb_yield_values(2, val, idx);
@ -536,7 +535,7 @@ enumerator_with_index(int argc, VALUE *argv, VALUE obj)
memo = INT2FIX(0); memo = INT2FIX(0);
else else
memo = rb_to_int(memo); memo = rb_to_int(memo);
return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)NEW_MEMO(memo, 0, 0)); return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)MEMO_NEW(memo, 0, 0));
} }
/* /*

Просмотреть файл

@ -405,7 +405,6 @@ count_nodes(int argc, VALUE *argv, VALUE os)
COUNT_NODE(NODE_POSTEXE); COUNT_NODE(NODE_POSTEXE);
COUNT_NODE(NODE_ALLOCA); COUNT_NODE(NODE_ALLOCA);
COUNT_NODE(NODE_BMETHOD); COUNT_NODE(NODE_BMETHOD);
COUNT_NODE(NODE_MEMO);
COUNT_NODE(NODE_DSYM); COUNT_NODE(NODE_DSYM);
COUNT_NODE(NODE_ATTRASGN); COUNT_NODE(NODE_ATTRASGN);
COUNT_NODE(NODE_PRELUDE); COUNT_NODE(NODE_PRELUDE);

8
gc.c
Просмотреть файл

@ -217,7 +217,7 @@ static ruby_gc_params_t gc_params = {
* 5: show all references * 5: show all references
*/ */
#ifndef RGENGC_CHECK_MODE #ifndef RGENGC_CHECK_MODE
#define RGENGC_CHECK_MODE 0 #define RGENGC_CHECK_MODE 2
#endif #endif
/* RGENGC_PROFILE /* RGENGC_PROFILE
@ -385,6 +385,7 @@ typedef struct RVALUE {
struct vm_svar svar; struct vm_svar svar;
struct vm_throw_data throw_data; struct vm_throw_data throw_data;
struct vm_ifunc ifunc; struct vm_ifunc ifunc;
struct MEMO memo;
} imemo; } imemo;
struct { struct {
struct RBasic basic; struct RBasic basic;
@ -4171,6 +4172,11 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
case imemo_ifunc: case imemo_ifunc:
gc_mark_maybe(objspace, (VALUE)RANY(obj)->as.imemo.ifunc.data); gc_mark_maybe(objspace, (VALUE)RANY(obj)->as.imemo.ifunc.data);
return; return;
case imemo_memo:
gc_mark(objspace, RANY(obj)->as.imemo.memo.v1);
gc_mark(objspace, RANY(obj)->as.imemo.memo.v2);
gc_mark_maybe(objspace, RANY(obj)->as.imemo.memo.u3.value);
return;
default: default:
rb_bug("T_IMEMO: unreachable"); rb_bug("T_IMEMO: unreachable");
} }

Просмотреть файл

@ -530,11 +530,12 @@ struct RIMemo {
}; };
enum imemo_type { enum imemo_type {
imemo_none, imemo_none = 0,
imemo_cref, imemo_cref = 1,
imemo_svar, imemo_svar = 2,
imemo_throw_data, imemo_throw_data = 3,
imemo_ifunc, imemo_ifunc = 4,
imemo_memo = 5,
imemo_mask = 0x07 imemo_mask = 0x07
}; };
@ -544,8 +545,6 @@ imemo_type(VALUE imemo)
return (RBASIC(imemo)->flags >> FL_USHIFT) & imemo_mask; return (RBASIC(imemo)->flags >> FL_USHIFT) & imemo_mask;
} }
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0);
/* CREF */ /* CREF */
typedef struct rb_cref_struct { typedef struct rb_cref_struct {
@ -595,17 +594,26 @@ struct vm_ifunc {
struct MEMO { struct MEMO {
VALUE flags; VALUE flags;
VALUE reserved; VALUE reserved;
VALUE v1; const VALUE v1;
VALUE v2; const VALUE v2;
union { union {
long cnt; long cnt;
long state; long state;
VALUE value; const VALUE value;
VALUE (*func)(ANYARGS); VALUE (*func)(ANYARGS);
} u3; } u3;
}; };
#define MEMO_V1_SET(m, v) RB_OBJ_WRITE((memo), &(memo)->v1, (v))
#define MEMO_V2_SET(m, v) RB_OBJ_WRITE((memo), &(memo)->v2, (v))
#define MEMO_CAST(m) ((struct MEMO *)m) #define MEMO_CAST(m) ((struct MEMO *)m)
#define MEMO_NEW(a, b, c) ((struct MEMO *)rb_imemo_new(imemo_memo, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0))
#define type_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) \
((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value))
struct vtm; /* defined by timev.h */ struct vtm; /* defined by timev.h */
@ -1267,6 +1275,8 @@ size_t rb_obj_memsize_of(VALUE);
size_t rb_obj_gc_flags(VALUE, ID[], size_t); size_t rb_obj_gc_flags(VALUE, ID[], size_t);
void rb_gc_mark_values(long n, const VALUE *values); void rb_gc_mark_values(long n, const VALUE *values);
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0);
RUBY_SYMBOL_EXPORT_END RUBY_SYMBOL_EXPORT_END
#if defined(__cplusplus) #if defined(__cplusplus)

4
load.c
Просмотреть файл

@ -728,7 +728,7 @@ load_lock(const char *ftptr)
st_insert(loading_tbl, (st_data_t)ftptr, data); st_insert(loading_tbl, (st_data_t)ftptr, data);
return (char *)ftptr; return (char *)ftptr;
} }
else if (RB_TYPE_P((VALUE)data, T_NODE) && nd_type((VALUE)data) == NODE_MEMO) { else if (RB_TYPE_P((VALUE)data, T_IMEMO) && imemo_type((VALUE)data) == imemo_memo) {
struct MEMO *memo = MEMO_CAST(data); struct MEMO *memo = MEMO_CAST(data);
void (*init)(void) = (void (*)(void))memo->u3.func; void (*init)(void) = (void (*)(void))memo->u3.func;
data = (st_data_t)rb_thread_shield_new(); data = (st_data_t)rb_thread_shield_new();
@ -1078,7 +1078,7 @@ register_init_ext(st_data_t *key, st_data_t *value, st_data_t init, int existing
rb_warn("%s is already registered", name); rb_warn("%s is already registered", name);
} }
else { else {
*value = (st_data_t)NEW_MEMO(0, 0, init); *value = (st_data_t)MEMO_NEW(0, 0, init);
*key = (st_data_t)ruby_strdup(name); *key = (st_data_t)ruby_strdup(name);
} }
return ST_CONTINUE; return ST_CONTINUE;

8
node.h
Просмотреть файл

@ -218,8 +218,6 @@ enum node_type {
#define NODE_ALLOCA NODE_ALLOCA #define NODE_ALLOCA NODE_ALLOCA
NODE_BMETHOD, NODE_BMETHOD,
#define NODE_BMETHOD NODE_BMETHOD #define NODE_BMETHOD NODE_BMETHOD
NODE_MEMO,
#define NODE_MEMO NODE_MEMO
NODE_DSYM, NODE_DSYM,
#define NODE_DSYM NODE_DSYM #define NODE_DSYM NODE_DSYM
NODE_ATTRASGN, NODE_ATTRASGN,
@ -455,12 +453,6 @@ typedef struct RNode {
#define NEW_BMETHOD(b) NEW_NODE(NODE_BMETHOD,0,0,b) #define NEW_BMETHOD(b) NEW_NODE(NODE_BMETHOD,0,0,b)
#define NEW_ATTRASGN(r,m,a) NEW_NODE(NODE_ATTRASGN,r,m,a) #define NEW_ATTRASGN(r,m,a) NEW_NODE(NODE_ATTRASGN,r,m,a)
#define NEW_PRELUDE(p,b) NEW_NODE(NODE_PRELUDE,p,b,0) #define NEW_PRELUDE(p,b) NEW_NODE(NODE_PRELUDE,p,b,0)
#define NEW_MEMO(a,b,c) ((struct MEMO *)NEW_NODE(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) \
((value) = rb_ary_tmp_new_fill(roomof(type, VALUE)), MEMO_FOR(type, value))
RUBY_SYMBOL_EXPORT_BEGIN RUBY_SYMBOL_EXPORT_BEGIN

Просмотреть файл

@ -654,7 +654,7 @@ new_args_gen(struct parser_params *parser, VALUE f, VALUE o, VALUE r, VALUE p, V
static inline VALUE static inline VALUE
new_args_tail_gen(struct parser_params *parser, VALUE k, VALUE kr, VALUE b) new_args_tail_gen(struct parser_params *parser, VALUE k, VALUE kr, VALUE b)
{ {
return (VALUE)rb_node_newnode(NODE_MEMO, k, kr, b); return (VALUE)MEMO_NEW(k, kr, b);
} }
#define new_args_tail(k,kr,b) new_args_tail_gen(parser, (k),(kr),(b)) #define new_args_tail(k,kr,b) new_args_tail_gen(parser, (k),(kr),(b))