mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* vm_insnhelper.c (vm_call_method0): do not propagate enable_fastpath,
but pass dummy CC to prevent wrong caching. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52100 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
e8ba0b7b04
commit
a00fc76ce5
2 changed files with 69 additions and 66 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
Sat Oct 10 18:35:12 2015 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
|
* vm_insnhelper.c (vm_call_method0): do not propagate enable_fastpath,
|
||||||
|
but pass dummy CC to prevent wrong caching.
|
||||||
|
|
||||||
Sat Oct 10 15:28:45 2015 Koichi Sasada <ko1@atdot.net>
|
Sat Oct 10 15:28:45 2015 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* import a github pull request
|
* import a github pull request
|
||||||
|
|
130
vm_insnhelper.c
130
vm_insnhelper.c
|
@ -1237,12 +1237,11 @@ static inline VALUE vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_
|
||||||
static inline VALUE vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc, int opt_pc);
|
static inline VALUE vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc, int opt_pc);
|
||||||
static VALUE vm_call_iseq_setup_normal_0start(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc);
|
static VALUE vm_call_iseq_setup_normal_0start(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc);
|
||||||
static VALUE vm_call_iseq_setup_tailcall_0start(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc);
|
static VALUE vm_call_iseq_setup_tailcall_0start(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc);
|
||||||
|
|
||||||
static VALUE vm_call_super_method(rb_thread_t *th, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc);
|
static VALUE vm_call_super_method(rb_thread_t *th, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc);
|
||||||
static VALUE vm_call_method_nome(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc);
|
static VALUE vm_call_method_nome(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc);
|
||||||
static VALUE vm_call_method0(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc,
|
static VALUE vm_call_method_each_type(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc);
|
||||||
const int enable_fastpath);
|
static inline VALUE vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc);
|
||||||
static VALUE vm_call_method_each_type(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc,
|
|
||||||
const int enable_fastpath);
|
|
||||||
|
|
||||||
static rb_method_definition_t *method_definition_create(rb_method_type_t type, ID mid);
|
static rb_method_definition_t *method_definition_create(rb_method_type_t type, ID mid);
|
||||||
static void method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts);
|
static void method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts);
|
||||||
|
@ -1836,7 +1835,7 @@ vm_call_opt_send(rb_thread_t *th, rb_control_frame_t *reg_cfp, struct rb_calling
|
||||||
|
|
||||||
cc->me = rb_callable_method_entry_without_refinements(CLASS_OF(calling->recv), ci->mid);
|
cc->me = rb_callable_method_entry_without_refinements(CLASS_OF(calling->recv), ci->mid);
|
||||||
ci->flag = VM_CALL_FCALL | VM_CALL_OPT_SEND;
|
ci->flag = VM_CALL_FCALL | VM_CALL_OPT_SEND;
|
||||||
return vm_call_method0(th, reg_cfp, calling, ci, cc, FALSE);
|
return vm_call_method(th, reg_cfp, calling, ci, cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -1889,17 +1888,17 @@ vm_call_method_missing(rb_thread_t *th, rb_control_frame_t *reg_cfp, struct rb_c
|
||||||
INC_SP(1);
|
INC_SP(1);
|
||||||
|
|
||||||
th->method_missing_reason = orig_cc->aux.method_missing_reason;
|
th->method_missing_reason = orig_cc->aux.method_missing_reason;
|
||||||
return vm_call_method0(th, reg_cfp, calling, ci, cc, FALSE);
|
return vm_call_method(th, reg_cfp, calling, ci, cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
vm_call_zsuper(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc, const int enable_fastpath, VALUE klass)
|
vm_call_zsuper(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc, VALUE klass)
|
||||||
{
|
{
|
||||||
klass = RCLASS_SUPER(klass);
|
klass = RCLASS_SUPER(klass);
|
||||||
cc->me = klass ? rb_callable_method_entry(klass, ci->mid) : NULL;
|
cc->me = klass ? rb_callable_method_entry(klass, ci->mid) : NULL;
|
||||||
|
|
||||||
if (cc->me != NULL) {
|
if (cc->me != NULL) {
|
||||||
return vm_call_method_each_type(th, cfp, calling, ci, cc, enable_fastpath);
|
return vm_call_method_each_type(th, cfp, calling, ci, cc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return vm_call_method_nome(th, cfp, calling, ci, cc);
|
return vm_call_method_nome(th, cfp, calling, ci, cc);
|
||||||
|
@ -2000,53 +1999,53 @@ refined_method_callable_without_refinement(const rb_callable_method_entry_t *me)
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
vm_call_method_each_type(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc, const int enable_fastpath)
|
vm_call_method_each_type(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc)
|
||||||
{
|
{
|
||||||
switch (cc->me->def->type) {
|
switch (cc->me->def->type) {
|
||||||
case VM_METHOD_TYPE_ISEQ:
|
case VM_METHOD_TYPE_ISEQ:
|
||||||
CI_SET_FASTPATH(cc, vm_call_iseq_setup, enable_fastpath);
|
CI_SET_FASTPATH(cc, vm_call_iseq_setup, TRUE);
|
||||||
return vm_call_iseq_setup(th, cfp, calling, ci, cc);
|
return vm_call_iseq_setup(th, cfp, calling, ci, cc);
|
||||||
|
|
||||||
case VM_METHOD_TYPE_NOTIMPLEMENTED:
|
case VM_METHOD_TYPE_NOTIMPLEMENTED:
|
||||||
case VM_METHOD_TYPE_CFUNC:
|
case VM_METHOD_TYPE_CFUNC:
|
||||||
CI_SET_FASTPATH(cc, vm_call_cfunc, enable_fastpath);
|
CI_SET_FASTPATH(cc, vm_call_cfunc, TRUE);
|
||||||
return vm_call_cfunc(th, cfp, calling, ci, cc);
|
return vm_call_cfunc(th, cfp, calling, ci, cc);
|
||||||
|
|
||||||
case VM_METHOD_TYPE_ATTRSET:
|
case VM_METHOD_TYPE_ATTRSET:
|
||||||
CALLER_SETUP_ARG(cfp, calling, ci);
|
CALLER_SETUP_ARG(cfp, calling, ci);
|
||||||
rb_check_arity(calling->argc, 1, 1);
|
rb_check_arity(calling->argc, 1, 1);
|
||||||
cc->aux.index = 0;
|
cc->aux.index = 0;
|
||||||
CI_SET_FASTPATH(cc, vm_call_attrset, enable_fastpath && !(ci->flag & VM_CALL_ARGS_SPLAT));
|
CI_SET_FASTPATH(cc, vm_call_attrset, !(ci->flag & VM_CALL_ARGS_SPLAT));
|
||||||
return vm_call_attrset(th, cfp, calling, ci, cc);
|
return vm_call_attrset(th, cfp, calling, ci, cc);
|
||||||
|
|
||||||
case VM_METHOD_TYPE_IVAR:
|
case VM_METHOD_TYPE_IVAR:
|
||||||
CALLER_SETUP_ARG(cfp, calling, ci);
|
CALLER_SETUP_ARG(cfp, calling, ci);
|
||||||
rb_check_arity(calling->argc, 0, 0);
|
rb_check_arity(calling->argc, 0, 0);
|
||||||
cc->aux.index = 0;
|
cc->aux.index = 0;
|
||||||
CI_SET_FASTPATH(cc, vm_call_ivar, enable_fastpath && !(ci->flag & VM_CALL_ARGS_SPLAT));
|
CI_SET_FASTPATH(cc, vm_call_ivar, !(ci->flag & VM_CALL_ARGS_SPLAT));
|
||||||
return vm_call_ivar(th, cfp, calling, ci, cc);
|
return vm_call_ivar(th, cfp, calling, ci, cc);
|
||||||
|
|
||||||
case VM_METHOD_TYPE_MISSING:
|
case VM_METHOD_TYPE_MISSING:
|
||||||
cc->aux.method_missing_reason = 0;
|
cc->aux.method_missing_reason = 0;
|
||||||
CI_SET_FASTPATH(cc, vm_call_method_missing, enable_fastpath);
|
CI_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
|
||||||
return vm_call_method_missing(th, cfp, calling, ci, cc);
|
return vm_call_method_missing(th, cfp, calling, ci, cc);
|
||||||
|
|
||||||
case VM_METHOD_TYPE_BMETHOD:
|
case VM_METHOD_TYPE_BMETHOD:
|
||||||
CI_SET_FASTPATH(cc, vm_call_bmethod, enable_fastpath);
|
CI_SET_FASTPATH(cc, vm_call_bmethod, TRUE);
|
||||||
return vm_call_bmethod(th, cfp, calling, ci, cc);
|
return vm_call_bmethod(th, cfp, calling, ci, cc);
|
||||||
|
|
||||||
case VM_METHOD_TYPE_ALIAS:
|
case VM_METHOD_TYPE_ALIAS:
|
||||||
cc->me = aliased_callable_method_entry(cc->me);
|
cc->me = aliased_callable_method_entry(cc->me);
|
||||||
VM_ASSERT(cc->me != NULL);
|
VM_ASSERT(cc->me != NULL);
|
||||||
return vm_call_method_each_type(th, cfp, calling, ci, cc, enable_fastpath);
|
return vm_call_method_each_type(th, cfp, calling, ci, cc);
|
||||||
|
|
||||||
case VM_METHOD_TYPE_OPTIMIZED:
|
case VM_METHOD_TYPE_OPTIMIZED:
|
||||||
switch (cc->me->def->body.optimize_type) {
|
switch (cc->me->def->body.optimize_type) {
|
||||||
case OPTIMIZED_METHOD_TYPE_SEND:
|
case OPTIMIZED_METHOD_TYPE_SEND:
|
||||||
CI_SET_FASTPATH(cc, vm_call_opt_send, enable_fastpath);
|
CI_SET_FASTPATH(cc, vm_call_opt_send, TRUE);
|
||||||
return vm_call_opt_send(th, cfp, calling, ci, cc);
|
return vm_call_opt_send(th, cfp, calling, ci, cc);
|
||||||
case OPTIMIZED_METHOD_TYPE_CALL:
|
case OPTIMIZED_METHOD_TYPE_CALL:
|
||||||
CI_SET_FASTPATH(cc, vm_call_opt_call, enable_fastpath);
|
CI_SET_FASTPATH(cc, vm_call_opt_call, TRUE);
|
||||||
return vm_call_opt_call(th, cfp, calling, ci, cc);
|
return vm_call_opt_call(th, cfp, calling, ci, cc);
|
||||||
default:
|
default:
|
||||||
rb_bug("vm_call_method: unsupported optimized method type (%d)",
|
rb_bug("vm_call_method: unsupported optimized method type (%d)",
|
||||||
|
@ -2057,7 +2056,7 @@ vm_call_method_each_type(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_cal
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VM_METHOD_TYPE_ZSUPER:
|
case VM_METHOD_TYPE_ZSUPER:
|
||||||
return vm_call_zsuper(th, cfp, calling, ci, cc, enable_fastpath, RCLASS_ORIGIN(cc->me->owner));
|
return vm_call_zsuper(th, cfp, calling, ci, cc, RCLASS_ORIGIN(cc->me->owner));
|
||||||
|
|
||||||
case VM_METHOD_TYPE_REFINED: {
|
case VM_METHOD_TYPE_REFINED: {
|
||||||
const rb_cref_t *cref = rb_vm_get_cref(cfp->ep);
|
const rb_cref_t *cref = rb_vm_get_cref(cfp->ep);
|
||||||
|
@ -2082,7 +2081,7 @@ vm_call_method_each_type(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_cal
|
||||||
}
|
}
|
||||||
cc->me = ref_me;
|
cc->me = ref_me;
|
||||||
if (ref_me->def->type != VM_METHOD_TYPE_REFINED) {
|
if (ref_me->def->type != VM_METHOD_TYPE_REFINED) {
|
||||||
return vm_call_method0(th, cfp, calling, ci, cc, enable_fastpath);
|
return vm_call_method(th, cfp, calling, ci, cc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2097,10 +2096,10 @@ vm_call_method_each_type(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_cal
|
||||||
if (UNDEFINED_METHOD_ENTRY_P(cc->me)) {
|
if (UNDEFINED_METHOD_ENTRY_P(cc->me)) {
|
||||||
cc->me = NULL;
|
cc->me = NULL;
|
||||||
}
|
}
|
||||||
return vm_call_method0(th, cfp, calling, ci, cc, enable_fastpath);
|
return vm_call_method(th, cfp, calling, ci, cc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return vm_call_zsuper(th, cfp, calling, ci, cc, enable_fastpath, cc->me->owner);
|
return vm_call_zsuper(th, cfp, calling, ci, cc, cc->me->owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2108,49 +2107,6 @@ vm_call_method_each_type(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_cal
|
||||||
rb_bug("vm_call_method: unsupported method type (%d)", cc->me->def->type);
|
rb_bug("vm_call_method: unsupported method type (%d)", cc->me->def->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
|
||||||
vm_call_method0(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc, const int enable_fastpath)
|
|
||||||
{
|
|
||||||
VM_ASSERT(callable_method_entry_p(cc->me));
|
|
||||||
|
|
||||||
if (cc->me != NULL) {
|
|
||||||
switch (METHOD_ENTRY_VISI(cc->me)) {
|
|
||||||
case METHOD_VISI_PUBLIC: /* likely */
|
|
||||||
return vm_call_method_each_type(th, cfp, calling, ci, cc, enable_fastpath);
|
|
||||||
|
|
||||||
case METHOD_VISI_PRIVATE:
|
|
||||||
if (!(ci->flag & VM_CALL_FCALL)) {
|
|
||||||
enum method_missing_reason stat = MISSING_PRIVATE;
|
|
||||||
if (ci->flag & VM_CALL_VCALL) stat |= MISSING_VCALL;
|
|
||||||
|
|
||||||
cc->aux.method_missing_reason = stat;
|
|
||||||
CI_SET_FASTPATH(cc, vm_call_method_missing, 1);
|
|
||||||
return vm_call_method_missing(th, cfp, calling, ci, cc);
|
|
||||||
}
|
|
||||||
return vm_call_method_each_type(th, cfp, calling, ci, cc, enable_fastpath);
|
|
||||||
|
|
||||||
case METHOD_VISI_PROTECTED:
|
|
||||||
if (!(ci->flag & VM_CALL_OPT_SEND)) {
|
|
||||||
if (!rb_obj_is_kind_of(cfp->self, cc->me->defined_class)) {
|
|
||||||
cc->aux.method_missing_reason = MISSING_PROTECTED;
|
|
||||||
return vm_call_method_missing(th, cfp, calling, ci, cc);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
VM_ASSERT(cc->me != NULL);
|
|
||||||
return vm_call_method_each_type(th, cfp, calling, ci, cc, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return vm_call_method_each_type(th, cfp, calling, ci, cc, enable_fastpath);
|
|
||||||
|
|
||||||
default:
|
|
||||||
rb_bug("unreachable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return vm_call_method_nome(th, cfp, calling, ci, cc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
vm_call_method_nome(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc)
|
vm_call_method_nome(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc)
|
||||||
{
|
{
|
||||||
|
@ -2172,7 +2128,49 @@ vm_call_method_nome(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc)
|
vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc)
|
||||||
{
|
{
|
||||||
return vm_call_method0(th, cfp, calling, ci, cc, TRUE);
|
VM_ASSERT(callable_method_entry_p(cc->me));
|
||||||
|
|
||||||
|
if (cc->me != NULL) {
|
||||||
|
switch (METHOD_ENTRY_VISI(cc->me)) {
|
||||||
|
case METHOD_VISI_PUBLIC: /* likely */
|
||||||
|
return vm_call_method_each_type(th, cfp, calling, ci, cc);
|
||||||
|
|
||||||
|
case METHOD_VISI_PRIVATE:
|
||||||
|
if (!(ci->flag & VM_CALL_FCALL)) {
|
||||||
|
enum method_missing_reason stat = MISSING_PRIVATE;
|
||||||
|
if (ci->flag & VM_CALL_VCALL) stat |= MISSING_VCALL;
|
||||||
|
|
||||||
|
cc->aux.method_missing_reason = stat;
|
||||||
|
CI_SET_FASTPATH(cc, vm_call_method_missing, 1);
|
||||||
|
return vm_call_method_missing(th, cfp, calling, ci, cc);
|
||||||
|
}
|
||||||
|
return vm_call_method_each_type(th, cfp, calling, ci, cc);
|
||||||
|
|
||||||
|
case METHOD_VISI_PROTECTED:
|
||||||
|
if (!(ci->flag & VM_CALL_OPT_SEND)) {
|
||||||
|
if (!rb_obj_is_kind_of(cfp->self, cc->me->defined_class)) {
|
||||||
|
cc->aux.method_missing_reason = MISSING_PROTECTED;
|
||||||
|
return vm_call_method_missing(th, cfp, calling, ci, cc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* caching method info to dummy cc */
|
||||||
|
struct rb_call_cache cc_entry;
|
||||||
|
cc_entry = *cc;
|
||||||
|
cc = &cc_entry;
|
||||||
|
|
||||||
|
VM_ASSERT(cc->me != NULL);
|
||||||
|
return vm_call_method_each_type(th, cfp, calling, ci, cc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vm_call_method_each_type(th, cfp, calling, ci, cc);
|
||||||
|
|
||||||
|
default:
|
||||||
|
rb_bug("unreachable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return vm_call_method_nome(th, cfp, calling, ci, cc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
|
Loading…
Add table
Reference in a new issue