diff options
author | mrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-05-18 00:54:52 +0000 |
---|---|---|
committer | mrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-05-18 00:54:52 +0000 |
commit | 218fd06328af866fb16cb2971844090f503e06bf (patch) | |
tree | a6c27a16ff957ed2b5b76f96ff98baec95382d10 /enum.c | |
parent | 896e1852708daa75f1ffa61e388ed62005df11a5 (diff) | |
download | ruby-218fd06328af866fb16cb2971844090f503e06bf.tar.gz |
Optimize each_sum for hashes
* enum.c (enum_sum, hash_sum, hash_sum_i, enum_sum_i, sum_iter):
Optimize for hashes when each method isn't redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55041 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'enum.c')
-rw-r--r-- | enum.c | 39 |
1 files changed, 33 insertions, 6 deletions
@@ -13,6 +13,8 @@ #include "ruby/util.h" #include "id.h" +#include <assert.h> + VALUE rb_mEnumerable; static ID id_next; @@ -3569,18 +3571,17 @@ struct enum_sum_memo { int float_value; }; -static VALUE -enum_sum_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) +static void +sum_iter(VALUE i, struct enum_sum_memo *memo) { - struct enum_sum_memo *memo = (struct enum_sum_memo *)args; + assert(memo != NULL); + long n = memo->n; VALUE v = memo->v; VALUE r = memo->r; double f = memo->f; double c = memo->c; - ENUM_WANT_SVALUE(); - if (memo->block_given) i = rb_yield(i); @@ -3662,10 +3663,32 @@ enum_sum_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) memo->r = r; memo->f = f; memo->c = c; +} +static VALUE +enum_sum_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) +{ + ENUM_WANT_SVALUE(); + sum_iter(i, (struct enum_sum_memo *) args); return Qnil; } +static int +hash_sum_i(VALUE key, VALUE value, VALUE arg) +{ + sum_iter(rb_assoc_new(key, value), (struct enum_sum_memo *) arg); + return ST_CONTINUE; +} + +static void +hash_sum(VALUE hash, struct enum_sum_memo *memo) +{ + assert(RB_TYPE_P(hash, T_HASH)); + assert(memo != NULL); + + rb_hash_foreach(hash, hash_sum_i, (VALUE)memo); +} + static VALUE int_range_sum(VALUE beg, VALUE end, int excl, VALUE init) { @@ -3743,7 +3766,11 @@ enum_sum(int argc, VALUE* argv, VALUE obj) } } - rb_block_call(obj, id_each, 0, 0, enum_sum_iter_i, (VALUE)&memo); + if (RB_TYPE_P(obj, T_HASH) && + rb_method_basic_definition_p(CLASS_OF(obj), id_each)) + hash_sum(obj, &memo); + else + rb_block_call(obj, id_each, 0, 0, enum_sum_i, (VALUE)&memo); if (memo.float_value) { return DBL2NUM(memo.f); |