diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-04-15 03:49:55 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-04-15 03:49:55 +0000 |
commit | 20675167d76183d37990f68349fe877f8ee1c005 (patch) | |
tree | 55791127018ee5da0bb740bf24282c58015ab609 /enum.c | |
parent | 70cbe70b71da249925c87edf88eaf1988906ba5c (diff) | |
download | ruby-20675167d76183d37990f68349fe877f8ee1c005.tar.gz |
enum.c: make each_slice and each_cons more efficient
* enum.c (enum_each_slice, enum_each_cons): make more efficient by
allocating less and recycling block argument arrays if possible.
[Fixes GH-596]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45589 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'enum.c')
-rw-r--r-- | enum.c | 24 |
1 files changed, 20 insertions, 4 deletions
@@ -2058,6 +2058,9 @@ enum_each_entry(int argc, VALUE *argv, VALUE obj) return obj; } +#define dont_recycle_block_arg(arity) ((arity) == 1 || (arity) == -1) +#define nd_no_recycle u2.value + static VALUE each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, m)) { @@ -2071,7 +2074,13 @@ each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, m)) if (RARRAY_LEN(ary) == size) { v = rb_yield(ary); - memo->u1.value = rb_ary_new2(size); + + if (memo->nd_no_recycle) { + memo->u1.value = rb_ary_new2(size); + } + else { + rb_ary_clear(ary); + } } return v; @@ -2113,11 +2122,13 @@ enum_each_slice(VALUE obj, VALUE n) long size = NUM2LONG(n); VALUE ary; NODE *memo; + int arity; if (size <= 0) rb_raise(rb_eArgError, "invalid slice size"); RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_slice_size); ary = rb_ary_new2(size); - memo = NEW_MEMO(ary, 0, size); + arity = rb_block_arity(); + memo = NEW_MEMO(ary, dont_recycle_block_arg(arity), size); rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo); ary = memo->u1.value; if (RARRAY_LEN(ary) > 0) rb_yield(ary); @@ -2139,7 +2150,10 @@ each_cons_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) } rb_ary_push(ary, i); if (RARRAY_LEN(ary) == size) { - v = rb_yield(rb_ary_dup(ary)); + if (memo->nd_no_recycle) { + ary = rb_ary_dup(ary); + } + v = rb_yield(ary); } return v; } @@ -2184,10 +2198,12 @@ enum_each_cons(VALUE obj, VALUE n) { long size = NUM2LONG(n); NODE *memo; + int arity; if (size <= 0) rb_raise(rb_eArgError, "invalid size"); RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size); - memo = NEW_MEMO(rb_ary_new2(size), 0, size); + arity = rb_block_arity(); + memo = NEW_MEMO(rb_ary_new2(size), dont_recycle_block_arg(arity), size); rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo); return Qnil; |