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>
This commit is contained in:
parent
632beec01f
commit
fbaa5db44a
Notes:
git
2022-12-17 22:52:09 +00:00
@ -76,6 +76,7 @@ firstline, predefined = __LINE__+1, %[\
|
|||||||
"/*NULL*/" NULL
|
"/*NULL*/" NULL
|
||||||
empty?
|
empty?
|
||||||
eql?
|
eql?
|
||||||
|
default
|
||||||
respond_to? Respond_to
|
respond_to? Respond_to
|
||||||
respond_to_missing? Respond_to_missing
|
respond_to_missing? Respond_to_missing
|
||||||
<IFUNC>
|
<IFUNC>
|
||||||
|
20
hash.c
20
hash.c
@ -28,6 +28,7 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "internal/array.h"
|
#include "internal/array.h"
|
||||||
#include "internal/bignum.h"
|
#include "internal/bignum.h"
|
||||||
|
#include "internal/basic_operators.h"
|
||||||
#include "internal/class.h"
|
#include "internal/class.h"
|
||||||
#include "internal/cont.h"
|
#include "internal/cont.h"
|
||||||
#include "internal/error.h"
|
#include "internal/error.h"
|
||||||
@ -93,9 +94,11 @@ rb_hash_freeze(VALUE hash)
|
|||||||
VALUE rb_cHash;
|
VALUE rb_cHash;
|
||||||
|
|
||||||
static VALUE envtbl;
|
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;
|
static ID id_hash_iter_lev;
|
||||||
|
|
||||||
|
#define id_default idDefault
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
|
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);
|
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
|
VALUE
|
||||||
rb_hash_default_value(VALUE hash, VALUE key)
|
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);
|
VALUE ifnone = RHASH_IFNONE(hash);
|
||||||
if (!FL_TEST(hash, RHASH_PROC_DEFAULT)) return ifnone;
|
if (!FL_TEST(hash, RHASH_PROC_DEFAULT)) return ifnone;
|
||||||
if (UNDEF_P(key)) return Qnil;
|
if (UNDEF_P(key)) return Qnil;
|
||||||
@ -7164,7 +7179,6 @@ void
|
|||||||
Init_Hash(void)
|
Init_Hash(void)
|
||||||
{
|
{
|
||||||
id_hash = rb_intern_const("hash");
|
id_hash = rb_intern_const("hash");
|
||||||
id_default = rb_intern_const("default");
|
|
||||||
id_flatten_bang = rb_intern_const("flatten!");
|
id_flatten_bang = rb_intern_const("flatten!");
|
||||||
id_hash_iter_lev = rb_make_internal_id();
|
id_hash_iter_lev = rb_make_internal_id();
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ enum ruby_basic_operators {
|
|||||||
BOP_AND,
|
BOP_AND,
|
||||||
BOP_OR,
|
BOP_OR,
|
||||||
BOP_CMP,
|
BOP_CMP,
|
||||||
|
BOP_DEFAULT,
|
||||||
|
|
||||||
BOP_LAST_
|
BOP_LAST_
|
||||||
};
|
};
|
||||||
|
1
vm.c
1
vm.c
@ -2054,6 +2054,7 @@ vm_init_redefined_flag(void)
|
|||||||
OP(Or, OR), (C(Integer));
|
OP(Or, OR), (C(Integer));
|
||||||
OP(NilP, NIL_P), (C(NilClass));
|
OP(NilP, NIL_P), (C(NilClass));
|
||||||
OP(Cmp, CMP), (C(Integer), C(Float), C(String));
|
OP(Cmp, CMP), (C(Integer), C(Float), C(String));
|
||||||
|
OP(Default, DEFAULT), (C(Hash));
|
||||||
#undef C
|
#undef C
|
||||||
#undef OP
|
#undef OP
|
||||||
}
|
}
|
||||||
|
@ -418,21 +418,22 @@ pub const tNUMPARAM_6: ruby_method_ids = 234;
|
|||||||
pub const tNUMPARAM_7: ruby_method_ids = 235;
|
pub const tNUMPARAM_7: ruby_method_ids = 235;
|
||||||
pub const tNUMPARAM_8: ruby_method_ids = 236;
|
pub const tNUMPARAM_8: ruby_method_ids = 236;
|
||||||
pub const tNUMPARAM_9: ruby_method_ids = 237;
|
pub const tNUMPARAM_9: ruby_method_ids = 237;
|
||||||
pub const tTOKEN_LOCAL_END: ruby_method_ids = 238;
|
pub const tDefault: ruby_method_ids = 238;
|
||||||
pub const tTOKEN_INSTANCE_BEGIN: ruby_method_ids = 237;
|
pub const tTOKEN_LOCAL_END: ruby_method_ids = 239;
|
||||||
pub const tTOKEN_INSTANCE_END: ruby_method_ids = 238;
|
pub const tTOKEN_INSTANCE_BEGIN: ruby_method_ids = 238;
|
||||||
pub const tTOKEN_GLOBAL_BEGIN: ruby_method_ids = 237;
|
pub const tTOKEN_INSTANCE_END: ruby_method_ids = 239;
|
||||||
pub const tLASTLINE: ruby_method_ids = 238;
|
pub const tTOKEN_GLOBAL_BEGIN: ruby_method_ids = 238;
|
||||||
pub const tBACKREF: ruby_method_ids = 239;
|
pub const tLASTLINE: ruby_method_ids = 239;
|
||||||
pub const tERROR_INFO: ruby_method_ids = 240;
|
pub const tBACKREF: ruby_method_ids = 240;
|
||||||
pub const tTOKEN_GLOBAL_END: ruby_method_ids = 241;
|
pub const tERROR_INFO: ruby_method_ids = 241;
|
||||||
pub const tTOKEN_CONST_BEGIN: ruby_method_ids = 240;
|
pub const tTOKEN_GLOBAL_END: ruby_method_ids = 242;
|
||||||
pub const tTOKEN_CONST_END: ruby_method_ids = 241;
|
pub const tTOKEN_CONST_BEGIN: ruby_method_ids = 241;
|
||||||
pub const tTOKEN_CLASS_BEGIN: ruby_method_ids = 240;
|
pub const tTOKEN_CONST_END: ruby_method_ids = 242;
|
||||||
pub const tTOKEN_CLASS_END: ruby_method_ids = 241;
|
pub const tTOKEN_CLASS_BEGIN: ruby_method_ids = 241;
|
||||||
pub const tTOKEN_ATTRSET_BEGIN: ruby_method_ids = 240;
|
pub const tTOKEN_CLASS_END: ruby_method_ids = 242;
|
||||||
pub const tTOKEN_ATTRSET_END: ruby_method_ids = 241;
|
pub const tTOKEN_ATTRSET_BEGIN: ruby_method_ids = 241;
|
||||||
pub const tNEXT_ID: ruby_method_ids = 241;
|
pub const tTOKEN_ATTRSET_END: ruby_method_ids = 242;
|
||||||
|
pub const tNEXT_ID: ruby_method_ids = 242;
|
||||||
pub const idMax: ruby_method_ids = 2721;
|
pub const idMax: ruby_method_ids = 2721;
|
||||||
pub const idMin: ruby_method_ids = 2737;
|
pub const idMin: ruby_method_ids = 2737;
|
||||||
pub const idFreeze: ruby_method_ids = 2753;
|
pub const idFreeze: ruby_method_ids = 2753;
|
||||||
@ -501,9 +502,10 @@ pub const idNUMPARAM_6: ruby_method_ids = 3745;
|
|||||||
pub const idNUMPARAM_7: ruby_method_ids = 3761;
|
pub const idNUMPARAM_7: ruby_method_ids = 3761;
|
||||||
pub const idNUMPARAM_8: ruby_method_ids = 3777;
|
pub const idNUMPARAM_8: ruby_method_ids = 3777;
|
||||||
pub const idNUMPARAM_9: ruby_method_ids = 3793;
|
pub const idNUMPARAM_9: ruby_method_ids = 3793;
|
||||||
pub const idLASTLINE: ruby_method_ids = 3815;
|
pub const idDefault: ruby_method_ids = 3809;
|
||||||
pub const idBACKREF: ruby_method_ids = 3831;
|
pub const idLASTLINE: ruby_method_ids = 3831;
|
||||||
pub const idERROR_INFO: ruby_method_ids = 3847;
|
pub const idBACKREF: ruby_method_ids = 3847;
|
||||||
|
pub const idERROR_INFO: ruby_method_ids = 3863;
|
||||||
pub const tLAST_OP_ID: ruby_method_ids = 169;
|
pub const tLAST_OP_ID: ruby_method_ids = 169;
|
||||||
pub const idLAST_OP_ID: ruby_method_ids = 10;
|
pub const idLAST_OP_ID: ruby_method_ids = 10;
|
||||||
pub type ruby_method_ids = u32;
|
pub type ruby_method_ids = u32;
|
||||||
@ -537,7 +539,8 @@ pub const BOP_CALL: ruby_basic_operators = 26;
|
|||||||
pub const BOP_AND: ruby_basic_operators = 27;
|
pub const BOP_AND: ruby_basic_operators = 27;
|
||||||
pub const BOP_OR: ruby_basic_operators = 28;
|
pub const BOP_OR: ruby_basic_operators = 28;
|
||||||
pub const BOP_CMP: ruby_basic_operators = 29;
|
pub const BOP_CMP: ruby_basic_operators = 29;
|
||||||
pub const BOP_LAST_: ruby_basic_operators = 30;
|
pub const BOP_DEFAULT: ruby_basic_operators = 30;
|
||||||
|
pub const BOP_LAST_: ruby_basic_operators = 31;
|
||||||
pub type ruby_basic_operators = u32;
|
pub type ruby_basic_operators = u32;
|
||||||
pub type rb_serial_t = ::std::os::raw::c_ulonglong;
|
pub type rb_serial_t = ::std::os::raw::c_ulonglong;
|
||||||
pub const imemo_env: imemo_type = 0;
|
pub const imemo_env: imemo_type = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user