1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

use method cache on Object#respond_to?

rb_method_boundp (method_boundp) searches method_entry, but this
search did not use pCMC, so change to use it.
This commit is contained in:
Koichi Sasada 2020-12-14 14:51:39 +09:00
parent 0362b4c689
commit 53edb27bac
Notes: git 2020-12-14 15:28:33 +09:00
2 changed files with 36 additions and 14 deletions

View file

@ -389,7 +389,7 @@ check_funcall_failed(VALUE v, VALUE e)
struct rescue_funcall_args *args = (void *)v; struct rescue_funcall_args *args = (void *)v;
int ret = args->respond; int ret = args->respond;
if (!ret) { if (!ret) {
switch (rb_method_boundp(args->defined_class, args->mid, switch (method_boundp(args->defined_class, args->mid,
BOUND_PRIVATE|BOUND_RESPONDS)) { BOUND_PRIVATE|BOUND_RESPONDS)) {
case 2: case 2:
ret = TRUE; ret = TRUE;

View file

@ -1182,20 +1182,33 @@ rb_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
return method_entry_resolve_refinement(klass, id, TRUE, defined_class_ptr); return method_entry_resolve_refinement(klass, id, TRUE, defined_class_ptr);
} }
MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * static const rb_callable_method_entry_t *
rb_callable_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr) callable_method_entry_refeinements(VALUE klass, ID id, VALUE *defined_class_ptr, bool with_refinements)
{ {
const rb_callable_method_entry_t *cme = callable_method_entry(klass, id, defined_class_ptr); const rb_callable_method_entry_t *cme = callable_method_entry(klass, id, defined_class_ptr);
if (cme == NULL || cme->def->type != VM_METHOD_TYPE_REFINED) { if (cme == NULL || cme->def->type != VM_METHOD_TYPE_REFINED) {
return cme; return cme;
} }
else { else {
VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class; VALUE defined_class, *dcp = defined_class_ptr ? defined_class_ptr : &defined_class;
const rb_method_entry_t *me = method_entry_resolve_refinement(klass, id, TRUE, dcp); const rb_method_entry_t *me = method_entry_resolve_refinement(klass, id, with_refinements, dcp);
return prepare_callable_method_entry(*dcp, id, me, TRUE); return prepare_callable_method_entry(*dcp, id, me, TRUE);
} }
} }
MJIT_FUNC_EXPORTED const rb_callable_method_entry_t *
rb_callable_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
{
return callable_method_entry_refeinements(klass, id, defined_class_ptr, true);
}
static const rb_callable_method_entry_t *
callable_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
{
return callable_method_entry_refeinements(klass, id, defined_class_ptr, false);
}
const rb_method_entry_t * const rb_method_entry_t *
rb_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr) rb_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
{ {
@ -1377,21 +1390,23 @@ rb_export_method(VALUE klass, ID name, rb_method_visibility_t visi)
#define BOUND_PRIVATE 0x01 #define BOUND_PRIVATE 0x01
#define BOUND_RESPONDS 0x02 #define BOUND_RESPONDS 0x02
int static int
rb_method_boundp(VALUE klass, ID id, int ex) method_boundp(VALUE klass, ID id, int ex)
{ {
const rb_method_entry_t *me; const rb_callable_method_entry_t *cme;
VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_ICLASS));
if (ex & BOUND_RESPONDS) { if (ex & BOUND_RESPONDS) {
me = method_entry_resolve_refinement(klass, id, TRUE, NULL); cme = rb_callable_method_entry_with_refinements(klass, id, NULL);
} }
else { else {
me = rb_method_entry_without_refinements(klass, id, NULL); cme = callable_method_entry_without_refinements(klass, id, NULL);
} }
if (me != NULL) { if (cme != NULL) {
if (ex & ~BOUND_RESPONDS) { if (ex & ~BOUND_RESPONDS) {
switch (METHOD_ENTRY_VISI(me)) { switch (METHOD_ENTRY_VISI(cme)) {
case METHOD_VISI_PRIVATE: case METHOD_VISI_PRIVATE:
return 0; return 0;
case METHOD_VISI_PROTECTED: case METHOD_VISI_PROTECTED:
@ -1401,7 +1416,7 @@ rb_method_boundp(VALUE klass, ID id, int ex)
} }
} }
if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { if (cme->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
if (ex & BOUND_RESPONDS) return 2; if (ex & BOUND_RESPONDS) return 2;
return 0; return 0;
} }
@ -1410,6 +1425,13 @@ rb_method_boundp(VALUE klass, ID id, int ex)
return 0; return 0;
} }
// deprecated
int
rb_method_boundp(VALUE klass, ID id, int ex)
{
return method_boundp(klass, id, ex);
}
static void static void
vm_cref_set_visibility(rb_method_visibility_t method_visi, int module_func) vm_cref_set_visibility(rb_method_visibility_t method_visi, int module_func)
{ {
@ -2384,7 +2406,7 @@ basic_obj_respond_to(rb_execution_context_t *ec, VALUE klass, VALUE obj, ID id,
{ {
VALUE ret; VALUE ret;
switch (rb_method_boundp(klass, id, pub|BOUND_RESPONDS)) { switch (method_boundp(klass, id, pub|BOUND_RESPONDS)) {
case 2: case 2:
return FALSE; return FALSE;
case 0: case 0: