From 218fd06328af866fb16cb2971844090f503e06bf Mon Sep 17 00:00:00 2001 From: mrkn Date: Wed, 18 May 2016 00:54:52 +0000 Subject: 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 --- ChangeLog | 5 +++++ enum.c | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 39ac789454..9fa9609fe0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed May 18 09:52:00 2016 Kenta Murata + + * enum.c (enum_sum, hash_sum, hash_sum_i, enum_sum_i, sum_iter): + Optimize for hashes when each method isn't redefined. + Wed May 18 09:14:00 2016 Kenta Murata * enum.c (enum_sum, int_range_sum): Extract int_range_sum from diff --git a/enum.c b/enum.c index 67cc301f02..33e4483787 100644 --- a/enum.c +++ b/enum.c @@ -13,6 +13,8 @@ #include "ruby/util.h" #include "id.h" +#include + 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); -- cgit v1.2.3