summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorglass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-07-29 05:58:36 +0000
committerglass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-07-29 05:58:36 +0000
commit3f8e82b421de15760133e5ec7fded086e26ca913 (patch)
tree94698490fe368382170522f362e3e3335d13f8fd
parentfcb58bdb3826a3ba6eaeb133313fea148d843926 (diff)
* hash.c (rb_hash_assoc): performance improvement by replacing
compare function in RHASH(hash)->ntbl->type temporarily. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42224 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--hash.c59
2 files changed, 50 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 7709123933..a0ed168061 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Mon Jul 29 14:54:44 2013 Masaki Matsushita <glass.saga@gmail.com>
+
+ * hash.c (rb_hash_assoc): performance improvement by replacing
+ compare function in RHASH(hash)->ntbl->type temporarily.
+
Mon Jul 29 14:52:46 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/mkmf.rb (xsystem): expand environment variable in all macros not
diff --git a/hash.c b/hash.c
index 3c448c0b0e..d346a520aa 100644
--- a/hash.c
+++ b/hash.c
@@ -2115,15 +2115,34 @@ rb_hash_merge(VALUE hash1, VALUE hash2)
}
static int
-assoc_i(VALUE key, VALUE val, VALUE arg)
+assoc_cmp(VALUE a, VALUE b)
{
- VALUE *args = (VALUE *)arg;
+ return !RTEST(rb_equal(a, b));
+}
- if (RTEST(rb_equal(args[0], key))) {
- args[1] = rb_assoc_new(key, val);
- return ST_STOP;
- }
- return ST_CONTINUE;
+struct lookup2_arg {
+ VALUE hash;
+ VALUE key;
+};
+
+static VALUE
+lookup2_call(VALUE arg)
+{
+ struct lookup2_arg *p = (struct lookup2_arg *)arg;
+ return rb_hash_lookup2(p->hash, p->key, Qundef);
+}
+
+struct reset_hash_type_arg {
+ VALUE hash;
+ const struct st_hash_type *orighash;
+};
+
+static VALUE
+reset_hash_type(VALUE arg)
+{
+ struct reset_hash_type_arg *p = (struct reset_hash_type_arg *)arg;
+ RHASH(p->hash)->ntbl->type = p->orighash;
+ return Qundef;
}
/*
@@ -2141,14 +2160,26 @@ assoc_i(VALUE key, VALUE val, VALUE arg)
*/
VALUE
-rb_hash_assoc(VALUE hash, VALUE obj)
+rb_hash_assoc(VALUE hash, VALUE key)
{
- VALUE args[2];
-
- args[0] = obj;
- args[1] = Qnil;
- rb_hash_foreach(hash, assoc_i, (VALUE)args);
- return args[1];
+ VALUE value;
+ st_table *table = hash_tbl(hash);
+ struct lookup2_arg arg;
+ struct reset_hash_type_arg ensure_arg;
+ const struct st_hash_type *orighash = table->type;
+ const struct st_hash_type assochash = {
+ assoc_cmp,
+ orighash->hash,
+ };
+
+ table->type = &assochash;
+ arg.hash = hash;
+ arg.key = key;
+ ensure_arg.hash = hash;
+ ensure_arg.orighash = orighash;
+ value = rb_ensure(lookup2_call, (VALUE)&arg, reset_hash_type, (VALUE)&ensure_arg);
+ if (value == Qundef) return Qnil;
+ return rb_assoc_new(key, value);
}
static int