summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2022-12-15 10:46:24 -0800
committerJohn Hawthorn <john@hawthorn.email>2022-12-17 14:51:49 -0800
commitfbaa5db44a3b0622e2755fd00e0519a603aa9bcb (patch)
tree8333e59e1fd500adc85a563f6ea5e81bda66e756 /hash.c
parent632beec01f6a293aa03da06f5f0e6f9a7c22a8c5 (diff)
downloadruby-fbaa5db44a3b0622e2755fd00e0519a603aa9bcb.tar.gz
Use a BOP for Hash#default
On a hash miss we need to call default if it is redefined in order to return the default value to be used. Previously we checked this with rb_method_basic_definition_p, which avoids the method call but requires a method lookup. This commit replaces the previous check with BASIC_OP_UNREDEFINED_P and a new BOP_DEFAULT. We still need to fall back to rb_method_basic_definition_p when called on a subclasss of hash. | |compare-ruby|built-ruby| |:---------------|-----------:|---------:| |hash_aref_miss | 2.692| 3.531| | | -| 1.31x| Co-authored-by: Daniel Colson <danieljamescolson@gmail.com> Co-authored-by: "Ian C. Anderson" <ian@iancanderson.com> Co-authored-by: Jack McCracken <me@jackmc.xyz>
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/hash.c b/hash.c
index a577e77985..1923c63eb3 100644
--- a/hash.c
+++ b/hash.c
@@ -28,6 +28,7 @@
#include "internal.h"
#include "internal/array.h"
#include "internal/bignum.h"
+#include "internal/basic_operators.h"
#include "internal/class.h"
#include "internal/cont.h"
#include "internal/error.h"
@@ -93,9 +94,11 @@ rb_hash_freeze(VALUE hash)
VALUE rb_cHash;
static VALUE envtbl;
-static ID id_hash, id_default, id_flatten_bang;
+static ID id_hash, id_flatten_bang;
static ID id_hash_iter_lev;
+#define id_default idDefault
+
VALUE
rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
{
@@ -2070,10 +2073,22 @@ call_default_proc(VALUE proc, VALUE hash, VALUE key)
return rb_proc_call_with_block(proc, 2, args, Qnil);
}
+static bool
+rb_hash_default_unredefined(VALUE hash)
+{
+ VALUE klass = RBASIC_CLASS(hash);
+ if (LIKELY(klass == rb_cHash)) {
+ return !!BASIC_OP_UNREDEFINED_P(BOP_DEFAULT, HASH_REDEFINED_OP_FLAG);
+ }
+ else {
+ return LIKELY(rb_method_basic_definition_p(klass, id_default));
+ }
+}
+
VALUE
rb_hash_default_value(VALUE hash, VALUE key)
{
- if (LIKELY(rb_method_basic_definition_p(CLASS_OF(hash), id_default))) {
+ if (LIKELY(rb_hash_default_unredefined(hash))) {
VALUE ifnone = RHASH_IFNONE(hash);
if (!FL_TEST(hash, RHASH_PROC_DEFAULT)) return ifnone;
if (UNDEF_P(key)) return Qnil;
@@ -7164,7 +7179,6 @@ void
Init_Hash(void)
{
id_hash = rb_intern_const("hash");
- id_default = rb_intern_const("default");
id_flatten_bang = rb_intern_const("flatten!");
id_hash_iter_lev = rb_make_internal_id();