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
Родитель 0362b4c689
Коммит 53edb27bac
2 изменённых файлов: 36 добавлений и 14 удалений

Просмотреть файл

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

Просмотреть файл

@ -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);
}
MJIT_FUNC_EXPORTED const rb_callable_method_entry_t *
rb_callable_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class_ptr)
static const rb_callable_method_entry_t *
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);
if (cme == NULL || cme->def->type != VM_METHOD_TYPE_REFINED) {
return cme;
}
else {
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);
}
}
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 *
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_RESPONDS 0x02
int
rb_method_boundp(VALUE klass, ID id, int ex)
static int
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) {
me = method_entry_resolve_refinement(klass, id, TRUE, NULL);
cme = rb_callable_method_entry_with_refinements(klass, id, NULL);
}
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) {
switch (METHOD_ENTRY_VISI(me)) {
switch (METHOD_ENTRY_VISI(cme)) {
case METHOD_VISI_PRIVATE:
return 0;
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;
return 0;
}
@ -1410,6 +1425,13 @@ rb_method_boundp(VALUE klass, ID id, int ex)
return 0;
}
// deprecated
int
rb_method_boundp(VALUE klass, ID id, int ex)
{
return method_boundp(klass, id, ex);
}
static void
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;
switch (rb_method_boundp(klass, id, pub|BOUND_RESPONDS)) {
switch (method_boundp(klass, id, pub|BOUND_RESPONDS)) {
case 2:
return FALSE;
case 0: