diff options
author | 卜部昌平 <shyouhei@ruby-lang.org> | 2019-10-03 12:26:41 +0900 |
---|---|---|
committer | 卜部昌平 <shyouhei@ruby-lang.org> | 2019-10-03 12:45:24 +0900 |
commit | eb92159d72fc711387f7e17ffbaca1678f23fd47 (patch) | |
tree | 13c5177b80fbd50c7113eee5aca5158652f24f1b /vm_method.c | |
parent | ef697388becedf36966a2edcdcf88baca342b9e2 (diff) |
Revert https://github.com/ruby/ruby/pull/2486
This reverts commits: 10d6a3aca7 8ba48c1b85 fba8627dc1 dd883de5ba
6c6a25feca 167e6b48f1 7cb96d41a5 3207979278 595b3c4fdd 1521f7cf89
c11c5e69ac cf33608203 3632a812c0 f56506be0d 86427a3219 .
The reason for the revert is that we observe ABA problem around
inline method cache. When a cache misshits, we search for a
method entry. And if the entry is identical to what was cached
before, we reuse the cache. But the commits we are reverting here
introduced situations where a method entry is freed, then the
identical memory region is used for another method entry. An
inline method cache cannot detect that ABA.
Here is a code that reproduce such situation:
```ruby
require 'prime'
class << Integer
alias org_sqrt sqrt
def sqrt(n)
raise
end
GC.stress = true
Prime.each(7*37){} rescue nil # <- Here we populate CC
class << Object.new; end
# These adjacent remove-then-alias maneuver
# frees a method entry, then immediately
# reuses it for another.
remove_method :sqrt
alias sqrt org_sqrt
end
Prime.each(7*37).to_a # <- SEGV
```
Diffstat (limited to 'vm_method.c')
-rw-r--r-- | vm_method.c | 570 |
1 files changed, 213 insertions, 357 deletions
diff --git a/vm_method.c b/vm_method.c index 1508b9a481..554d209110 100644 --- a/vm_method.c +++ b/vm_method.c @@ -41,7 +41,7 @@ struct cache_entry { rb_serial_t method_state; rb_serial_t class_serial; ID mid; - const rb_method_entry_t* me; + rb_method_entry_t* me; VALUE defined_class; }; @@ -132,7 +132,9 @@ rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_me { if (argc < -2 || 15 < argc) rb_raise(rb_eArgError, "arity out of range: %d for -2..15", argc); if (func != rb_f_notimplement) { - rb_method_cfunc_t opt = { func, 0, argc, }; + rb_method_cfunc_t opt; + opt.func = func; + opt.argc = argc; rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, visi); } else { @@ -140,11 +142,9 @@ rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_me } } -void -rb_free_method_entry(const rb_method_entry_t *me) +static void +rb_method_definition_release(rb_method_definition_t *def, int complemented) { - rb_method_definition_t *def = me->def; - if (def != NULL) { const int alias_count = def->alias_count; const int complemented_count = def->complemented_count; @@ -158,7 +158,7 @@ rb_free_method_entry(const rb_method_entry_t *me) xfree(def); } else { - if (def->complemented_count > 0) def->complemented_count--; + if (complemented) def->complemented_count--; else if (def->alias_count > 0) def->alias_count--; if (METHOD_DEBUG) fprintf(stderr, "-%p-%s:%d->%d,%d->%d (dec)\n", (void *)def, rb_id2name(def->original_id), @@ -167,17 +167,23 @@ rb_free_method_entry(const rb_method_entry_t *me) } } -static inline const rb_method_entry_t *search_method(VALUE klass, ID id, VALUE *defined_class_ptr); +void +rb_free_method_entry(const rb_method_entry_t *me) +{ + rb_method_definition_release(me->def, METHOD_ENTRY_COMPLEMENTED(me)); +} + +static inline rb_method_entry_t *search_method(VALUE klass, ID id, VALUE *defined_class_ptr); extern int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2); -static inline const rb_method_entry_t * +static inline rb_method_entry_t * lookup_method_table(VALUE klass, ID id) { st_data_t body; struct rb_id_table *m_tbl = RCLASS_M_TBL(klass); if (rb_id_table_lookup(m_tbl, id, &body)) { - return (const rb_method_entry_t *) body; + return (rb_method_entry_t *) body; } else { return 0; @@ -212,9 +218,97 @@ static VALUE } static void +setup_method_cfunc_struct(rb_method_cfunc_t *cfunc, VALUE (*func)(), int argc) +{ + cfunc->func = func; + cfunc->argc = argc; + cfunc->invoker = call_cfunc_invoker_func(argc); +} + +MJIT_FUNC_EXPORTED void +rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts) +{ + *(rb_method_definition_t **)&me->def = def; + + if (opts != NULL) { + switch (def->type) { + case VM_METHOD_TYPE_ISEQ: + { + rb_method_iseq_t *iseq_body = (rb_method_iseq_t *)opts; + rb_cref_t *method_cref, *cref = iseq_body->cref; + + /* setup iseq first (before invoking GC) */ + RB_OBJ_WRITE(me, &def->body.iseq.iseqptr, iseq_body->iseqptr); + + if (0) vm_cref_dump("rb_method_definition_create", cref); + + if (cref) { + method_cref = cref; + } + else { + method_cref = vm_cref_new_toplevel(GET_EC()); /* TODO: can we reuse? */ + } + + RB_OBJ_WRITE(me, &def->body.iseq.cref, method_cref); + return; + } + case VM_METHOD_TYPE_CFUNC: + { + rb_method_cfunc_t *cfunc = (rb_method_cfunc_t *)opts; + setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def, body.cfunc), cfunc->func, cfunc->argc); + return; + } + case VM_METHOD_TYPE_ATTRSET: + case VM_METHOD_TYPE_IVAR: + { + const rb_execution_context_t *ec = GET_EC(); + rb_control_frame_t *cfp; + int line; + + def->body.attr.id = (ID)(VALUE)opts; + + cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp); + + if (cfp && (line = rb_vm_get_sourceline(cfp))) { + VALUE location = rb_ary_new3(2, rb_iseq_path(cfp->iseq), INT2FIX(line)); + RB_OBJ_WRITE(me, &def->body.attr.location, rb_ary_freeze(location)); + } + else { + VM_ASSERT(def->body.attr.location == 0); + } + return; + } + case VM_METHOD_TYPE_BMETHOD: + RB_OBJ_WRITE(me, &def->body.bmethod.proc, (VALUE)opts); + return; + case VM_METHOD_TYPE_NOTIMPLEMENTED: + setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def, body.cfunc), rb_f_notimplement, -1); + return; + case VM_METHOD_TYPE_OPTIMIZED: + def->body.optimize_type = (enum method_optimized_type)opts; + return; + case VM_METHOD_TYPE_REFINED: + { + const rb_method_refined_t *refined = (rb_method_refined_t *)opts; + RB_OBJ_WRITE(me, &def->body.refined.orig_me, refined->orig_me); + RB_OBJ_WRITE(me, &def->body.refined.owner, refined->owner); + return; + } + case VM_METHOD_TYPE_ALIAS: + RB_OBJ_WRITE(me, &def->body.alias.original_me, (rb_method_entry_t *)opts); + return; + case VM_METHOD_TYPE_ZSUPER: + case VM_METHOD_TYPE_UNDEF: + case VM_METHOD_TYPE_MISSING: + return; + } + } +} + +static void method_definition_reset(const rb_method_entry_t *me) { - const rb_method_definition_t *def = me->def; + rb_method_definition_t *def = me->def; switch(def->type) { case VM_METHOD_TYPE_ISEQ: @@ -247,218 +341,14 @@ method_definition_reset(const rb_method_entry_t *me) } } -static rb_cref_t* -the_top_cref(void) +MJIT_FUNC_EXPORTED rb_method_definition_t * +rb_method_definition_create(rb_method_type_t type, ID mid) { - static rb_cref_t *top = NULL; - if (!top) { - top = vm_cref_new_toplevel(GET_EC()); - rb_gc_register_mark_object((VALUE)top); // cref is an IMEMO. - } - return top; -} - -static rb_method_iseq_t -the_method_iseq(const rb_method_iseq_t *p) -{ - return (rb_method_iseq_t) { - .iseqptr = p->iseqptr, - .cref = p->cref ? p->cref : the_top_cref(), - }; -} - -static rb_method_cfunc_t -the_method_cfunc(const rb_method_cfunc_t *p) -{ - return (rb_method_cfunc_t) { - .func = p->func, - .invoker = call_cfunc_invoker_func(p->argc), - .argc = p->argc, - }; -} - -static VALUE -the_location(void) -{ - const rb_execution_context_t *ec = GET_EC(); - const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp); - int line; - - if (!cfp) { - return Qfalse; - } - else if (! (line = rb_vm_get_sourceline(cfp))) { - return Qfalse; - } - else { - VALUE loc = rb_ary_new3(2, rb_iseq_path(cfp->iseq), INT2FIX(line)); - rb_ary_freeze(loc); - return loc; - } -} - -static rb_method_attr_t -the_method_attr(const void *p) -{ - return (rb_method_attr_t) { - .id = (ID)(VALUE)p, - .location = the_location(), - }; -} - -static rb_method_bmethod_t -the_method_bmethod(const void *p) -{ - return (rb_method_bmethod_t) { - .proc = (VALUE)p, - .hooks = NULL, - }; -} - -static rb_method_cfunc_t -the_method_notimplemented(void) -{ - return (rb_method_cfunc_t) { - .func = rb_f_notimplement, - .invoker = call_cfunc_m1, - .argc = -1, - }; -} - -static enum method_optimized_type -the_method_optimized(const void *p) -{ - return (enum method_optimized_type)p; -} - -static rb_method_refined_t -the_method_refined(const rb_method_refined_t *p) -{ - if (!p) { - return (rb_method_refined_t) { 0, }; - } - else { - return (rb_method_refined_t) { - .orig_me = p->orig_me, - .owner = p->owner, - }; - } -} - -static rb_method_alias_t -the_method_alias(const rb_method_entry_t *p) -{ - return (rb_method_alias_t) { - .original_me = p, - }; -} - -static rb_method_definition_t -rb_method_definition_new(rb_method_type_t type, ID mid, const void *opts) -{ - switch (type) { - case VM_METHOD_TYPE_ISEQ: - return (rb_method_definition_t) { - .type = type, - .original_id = mid, - .body = { - .iseq = the_method_iseq(opts), - } - }; - - case VM_METHOD_TYPE_CFUNC: - return (rb_method_definition_t) { - .type = type, - .original_id = mid, - .body = { - .cfunc = the_method_cfunc(opts), - } - }; - - case VM_METHOD_TYPE_ATTRSET: - case VM_METHOD_TYPE_IVAR: - return (rb_method_definition_t) { - .type = type, - .original_id = mid, - .body = { - .attr = the_method_attr(opts), - } - }; - - case VM_METHOD_TYPE_BMETHOD: - return (rb_method_definition_t) { - .type = type, - .original_id = mid, - .body = { - .bmethod = the_method_bmethod(opts), - } - }; - - case VM_METHOD_TYPE_NOTIMPLEMENTED: - return (rb_method_definition_t) { - .type = type, - .original_id = mid, - .body = { - .cfunc = the_method_notimplemented(), - } - }; - - case VM_METHOD_TYPE_OPTIMIZED: - return (rb_method_definition_t) { - .type = type, - .original_id = mid, - .body = { - .optimize_type = the_method_optimized(opts), - } - }; - - case VM_METHOD_TYPE_REFINED: - return (rb_method_definition_t) { - .type = type, - .original_id = mid, - .body = { - .refined = the_method_refined(opts), - } - }; - - case VM_METHOD_TYPE_ALIAS: - return (rb_method_definition_t) { - .type = type, - .original_id = mid, - .body = { - .alias = the_method_alias(opts), - } - }; - - case VM_METHOD_TYPE_ZSUPER: - case VM_METHOD_TYPE_UNDEF: - case VM_METHOD_TYPE_MISSING: - return (rb_method_definition_t) { - .type = type, - .original_id = mid, - }; - } - - UNREACHABLE_RETURN((rb_method_definition_t){0}); -} - -MJIT_FUNC_EXPORTED void -rb_method_entry_spoof(const rb_method_entry_t *me) -{ - VALUE v = (VALUE)me; - VALUE o = me->owner; - rb_id_table_insert(RCLASS_M_TBL(o), me->called_id, v); - RB_OBJ_WRITTEN(o, Qundef, v); - rb_clear_method_cache_by_class(o); -} - -static const rb_method_definition_t * -rb_method_definition_create(rb_method_type_t type, ID mid, const void *opts) -{ - rb_method_definition_t template = rb_method_definition_new(type, mid, opts); - void *ptr = ALLOC(rb_method_definition_t); - memcpy(ptr, &template, sizeof template); - return ptr; + rb_method_definition_t *def; + def = ZALLOC(rb_method_definition_t); + def->type = type; + def->original_id = mid; + return def; } static rb_method_definition_t * @@ -477,15 +367,10 @@ method_definition_addref_complement(rb_method_definition_t *def) return def; } -static const rb_method_entry_t * -rb_method_entry_alloc(VALUE flags, ID called_id, VALUE owner, VALUE defined_class, const rb_method_definition_t *def) -{ - VALUE v = rb_imemo_new(imemo_ment, (VALUE)def, (VALUE)called_id, owner, defined_class); - RBASIC(v)->flags = - (RBASIC(v)->flags & ~(IMEMO_FL_USER0|IMEMO_FL_USER1|IMEMO_FL_USER2)) | - (flags & (IMEMO_FL_USER0|IMEMO_FL_USER1|IMEMO_FL_USER2)); - const rb_method_entry_t *me = (void *)v; - method_definition_reset(me); +static rb_method_entry_t * +rb_method_entry_alloc(ID called_id, VALUE owner, VALUE defined_class, const rb_method_definition_t *def) +{ + rb_method_entry_t *me = (rb_method_entry_t *)rb_imemo_new(imemo_ment, (VALUE)def, (VALUE)called_id, owner, defined_class); return me; } @@ -503,58 +388,33 @@ filter_defined_class(VALUE klass) rb_bug("filter_defined_class: %s", rb_obj_info(klass)); } -static inline VALUE -method_entry_flags(rb_method_visibility_t visi) -{ - return (visi << (IMEMO_FL_USHIFT+0)) | - ((!ruby_running) << (IMEMO_FL_USHIFT+2)); -} - -MJIT_FUNC_EXPORTED const rb_method_entry_t * -rb_method_entry_from_template( - const rb_method_entry_t *me, - const void *body) -{ - return rb_method_entry_alloc( - me->flags, - me->called_id, - me->owner, - me->defined_class, - rb_method_definition_create( - me->def->type, - me->def->original_id, - body)); -} - -const rb_method_entry_t * -rb_method_entry_for_missing(ID mid, VALUE klass) +rb_method_entry_t * +rb_method_entry_create(ID called_id, VALUE klass, rb_method_visibility_t visi, const rb_method_definition_t *def) { - return rb_method_entry_alloc( - method_entry_flags(METHOD_VISI_UNDEF), - mid, - klass, - filter_defined_class(klass), - rb_method_definition_create( - VM_METHOD_TYPE_MISSING, - mid, - NULL)); + rb_method_entry_t *me = rb_method_entry_alloc(called_id, klass, filter_defined_class(klass), def); + METHOD_ENTRY_FLAGS_SET(me, visi, ruby_running ? FALSE : TRUE); + if (def != NULL) method_definition_reset(me); + return me; } const rb_method_entry_t * rb_method_entry_clone(const rb_method_entry_t *src_me) { - return rb_method_entry_alloc( - src_me->flags, - src_me->called_id, - src_me->owner, - src_me->defined_class, - method_definition_addref(src_me->def)); + rb_method_entry_t *me = rb_method_entry_alloc(src_me->called_id, src_me->owner, src_me->defined_class, + method_definition_addref(src_me->def)); + METHOD_ENTRY_FLAGS_COPY(me, src_me); + return me; } MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * rb_method_entry_complement_defined_class(const rb_method_entry_t *src_me, ID called_id, VALUE defined_class) { - const rb_method_definition_t *def = src_me->def; + rb_method_definition_t *def = src_me->def; + rb_method_entry_t *me; + struct { + const struct rb_method_entry_struct *orig_me; + VALUE owner; + } refined = {0}; if (!src_me->defined_class && def->type == VM_METHOD_TYPE_REFINED && @@ -562,69 +422,73 @@ rb_method_entry_complement_defined_class(const rb_method_entry_t *src_me, ID cal const rb_method_entry_t *orig_me = rb_method_entry_clone(def->body.refined.orig_me); RB_OBJ_WRITE((VALUE)orig_me, &orig_me->defined_class, defined_class); - def = rb_method_definition_create( - VM_METHOD_TYPE_REFINED, - called_id, - &(rb_method_refined_t) { - .orig_me = orig_me, - .owner = orig_me->owner}); - + refined.orig_me = orig_me; + refined.owner = orig_me->owner; + def = NULL; } else { - def = method_definition_addref_complement((rb_method_definition_t *)def); + def = method_definition_addref_complement(def); + } + me = rb_method_entry_alloc(called_id, src_me->owner, defined_class, def); + METHOD_ENTRY_FLAGS_COPY(me, src_me); + METHOD_ENTRY_COMPLEMENTED_SET(me); + if (!def) { + def = rb_method_definition_create(VM_METHOD_TYPE_REFINED, called_id); + rb_method_definition_set(me, def, &refined); } - const rb_method_entry_t *me = - rb_method_entry_alloc( - src_me->flags, - called_id, - src_me->owner, - defined_class, - def); VM_ASSERT(RB_TYPE_P(me->owner, T_MODULE)); - return (const rb_callable_method_entry_t *)me; + return (rb_callable_method_entry_t *)me; } -static const rb_method_entry_t* -make_method_entry_refined(VALUE owner, const rb_method_entry_t *me) +void +rb_method_entry_copy(rb_method_entry_t *dst, const rb_method_entry_t *src) +{ + *(rb_method_definition_t **)&dst->def = method_definition_addref(src->def); + method_definition_reset(dst); + dst->called_id = src->called_id; + RB_OBJ_WRITE((VALUE)dst, &dst->owner, src->owner); + RB_OBJ_WRITE((VALUE)dst, &dst->defined_class, src->defined_class); + METHOD_ENTRY_FLAGS_COPY(dst, src); +} + +static void +make_method_entry_refined(VALUE owner, rb_method_entry_t *me) { if (me->def->type == VM_METHOD_TYPE_REFINED) { - return me; + return; } else { + struct { + struct rb_method_entry_struct *orig_me; + VALUE owner; + } refined; + rb_method_definition_t *def; + rb_vm_check_redefinition_opt_method(me, me->owner); - /* :FIXME: can rb_method_entry_from_template be tweaked to also be - * applicable here? */ - return rb_method_entry_alloc( - method_entry_flags(METHOD_VISI_PUBLIC), - me->called_id, - me->owner, - me->defined_class, - rb_method_definition_create( - VM_METHOD_TYPE_REFINED, - me->called_id, - &(rb_method_refined_t) { - .owner = owner, - .orig_me = - rb_method_entry_alloc( - me->flags, - me->called_id, - me->owner, - me->defined_class ? - me->defined_class : owner, - method_definition_addref(me->def))})); + + refined.orig_me = + rb_method_entry_alloc(me->called_id, me->owner, + me->defined_class ? + me->defined_class : owner, + method_definition_addref(me->def)); + METHOD_ENTRY_FLAGS_COPY(refined.orig_me, me); + refined.owner = owner; + + def = rb_method_definition_create(VM_METHOD_TYPE_REFINED, me->called_id); + rb_method_definition_set(me, def, (void *)&refined); + METHOD_ENTRY_VISI_SET(me, METHOD_VISI_PUBLIC); } } void rb_add_refined_method_entry(VALUE refined_class, ID mid) { - const rb_method_entry_t *me = lookup_method_table(refined_class, mid); + rb_method_entry_t *me = lookup_method_table(refined_class, mid); if (me) { - me = make_method_entry_refined(refined_class, me); - rb_method_entry_spoof(me); + make_method_entry_refined(refined_class, me); rb_clear_method_cache_by_class(refined_class); } else { @@ -654,10 +518,11 @@ check_override_opt_method(VALUE klass, VALUE arg) * If def is given (!= NULL), then just use it and ignore original_id and otps. * If not given, then make a new def with original_id and opts. */ -static const rb_method_entry_t * +static rb_method_entry_t * rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibility_t visi, - rb_method_type_t type, const rb_method_definition_t *def, ID original_id, void *opts) + rb_method_type_t type, rb_method_definition_t *def, ID original_id, void *opts) { + rb_method_entry_t *me; struct rb_id_table *mtbl; st_data_t data; int make_refined = 0; @@ -685,7 +550,7 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil rb_add_refined_method_entry(refined_class, mid); } if (type == VM_METHOD_TYPE_REFINED) { - const rb_method_entry_t *old_me = lookup_method_table(RCLASS_ORIGIN(klass), mid); + rb_method_entry_t *old_me = lookup_method_table(RCLASS_ORIGIN(klass), mid); if (old_me) rb_vm_check_redefinition_opt_method(old_me, klass); } else { @@ -695,8 +560,8 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil /* check re-definition */ if (rb_id_table_lookup(mtbl, mid, &data)) { - const rb_method_entry_t *old_me = (const rb_method_entry_t *)data; - const rb_method_definition_t *old_def = old_me->def; + rb_method_entry_t *old_me = (rb_method_entry_t *)data; + rb_method_definition_t *old_def = old_me->def; if (rb_method_definition_eq(old_def, def)) return old_me; rb_vm_check_redefinition_opt_method(old_me, klass); @@ -733,16 +598,9 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil } /* create method entry */ - if (!def) { - def = rb_method_definition_create(type, original_id, opts); - } - const rb_method_entry_t *me = - rb_method_entry_alloc( - method_entry_flags(visi), - mid, - defined_class, - filter_defined_class(defined_class), - def); + me = rb_method_entry_create(mid, defined_class, visi, NULL); + if (def == NULL) def = rb_method_definition_create(type, original_id); + rb_method_definition_set(me, def, opts); rb_clear_method_cache_by_class(klass); @@ -764,7 +622,7 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil } if (make_refined) { - me = make_method_entry_refined(klass, me); + make_method_entry_refined(klass, me); } rb_id_table_insert(mtbl, mid, (VALUE)me); @@ -812,21 +670,27 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_ MJIT_FUNC_EXPORTED void rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi) { - rb_method_iseq_t iseq_body = { iseq, cref }; + struct { /* should be same fields with rb_method_iseq_struct */ + const rb_iseq_t *iseqptr; + rb_cref_t *cref; + } iseq_body; + + iseq_body.iseqptr = iseq; + iseq_body.cref = cref; rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, &iseq_body, visi); } -static const rb_method_entry_t * +static rb_method_entry_t * method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_visibility_t visi, VALUE defined_class) { - const rb_method_entry_t *newme = rb_method_entry_make(klass, mid, defined_class, visi, + rb_method_entry_t *newme = rb_method_entry_make(klass, mid, defined_class, visi, me->def->type, method_definition_addref(me->def), 0, NULL); method_added(klass, mid); return newme; } -const rb_method_entry_t * +rb_method_entry_t * rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_visibility_t visi) { return method_entry_set(klass, mid, me, visi, klass); @@ -860,10 +724,10 @@ rb_get_alloc_func(VALUE klass) return 0; } -static inline const rb_method_entry_t* +static inline rb_method_entry_t* search_method(VALUE klass, ID id, VALUE *defined_class_ptr) { - const rb_method_entry_t *me; + rb_method_entry_t *me; for (; klass; klass = RCLASS_SUPER(klass)) { RB_DEBUG_COUNTER_INC(mc_search_super); @@ -887,12 +751,12 @@ rb_method_entry_at(VALUE klass, ID id) * if you need method entry with method cache (normal case), use * rb_method_entry() simply. */ -static const rb_method_entry_t * +static rb_method_entry_t * method_entry_get_without_cache(VALUE klass, ID id, VALUE *defined_class_ptr) { VALUE defined_class; - const rb_method_entry_t *me = search_method(klass, id, &defined_class); + rb_method_entry_t *me = search_method(klass, id, &defined_class); if (ruby_running) { if (OPT_GLOBAL_METHOD_CACHE) { @@ -924,11 +788,11 @@ method_entry_get_without_cache(VALUE klass, ID id, } static void -verify_method_cache(VALUE klass, ID id, VALUE defined_class, const rb_method_entry_t *me) +verify_method_cache(VALUE klass, ID id, VALUE defined_class, rb_method_entry_t *me) { if (!VM_DEBUG_VERIFY_METHOD_CACHE) return; VALUE actual_defined_class; - const rb_method_entry_t *actual_me = + rb_method_entry_t *actual_me = method_entry_get_without_cache(klass, id, &actual_defined_class); if (me != actual_me || defined_class != actual_defined_class) { @@ -936,7 +800,7 @@ verify_method_cache(VALUE klass, ID id, VALUE defined_class, const rb_method_ent } } -static const rb_method_entry_t * +static rb_method_entry_t * method_entry_get(VALUE klass, ID id, VALUE *defined_class_ptr) { struct cache_entry *ent; @@ -977,7 +841,7 @@ prepare_callable_method_entry(VALUE defined_class, ID id, const rb_method_entry_ if (mtbl && rb_id_table_lookup(mtbl, id, (VALUE *)&me)) { RB_DEBUG_COUNTER_INC(mc_cme_complement_hit); - cme = (const rb_callable_method_entry_t *)me; + cme = (rb_callable_method_entry_t *)me; VM_ASSERT(callable_method_entry_p(cme)); } else { @@ -1001,7 +865,7 @@ MJIT_FUNC_EXPORTED const rb_callable_method_entry_t * rb_callable_method_entry(VALUE klass, ID id) { VALUE defined_class; - const rb_method_entry_t *me = method_entry_get(klass, id, &defined_class); + rb_method_entry_t *me = method_entry_get(klass, id, &defined_class); return prepare_callable_method_entry(defined_class, id, me); } @@ -1115,7 +979,7 @@ static void remove_method(VALUE klass, ID mid) { VALUE data; - const rb_method_entry_t *me = NULL; + rb_method_entry_t *me = 0; VALUE self = klass; klass = RCLASS_ORIGIN(klass); @@ -1125,7 +989,7 @@ remove_method(VALUE klass, ID mid) } if (!rb_id_table_lookup(RCLASS_M_TBL(klass), mid, &data) || - !(me = (const rb_method_entry_t *)data) || + !(me = (rb_method_entry_t *)data) || (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF) || UNDEFINED_REFINED_METHOD_P(me->def)) { rb_name_err_raise("method `%1$s' not defined in %2$s", @@ -1183,18 +1047,10 @@ rb_mod_remove_method(int argc, VALUE *argv, VALUE mod) return mod; } -static inline void -METHOD_ENTRY_VISI_SET(rb_method_entry_t *me, rb_method_visibility_t visi) -{ - VM_ASSERT((int)visi >= 0 && visi <= 3); - VALUE flags = (me->flags & ~(IMEMO_FL_USER0 | IMEMO_FL_USER1)) | (visi << (IMEMO_FL_USHIFT+0)); - memcpy((void *)&me->flags, &flags, sizeof flags); -} - static void rb_export_method(VALUE klass, ID name, rb_method_visibility_t visi) { - const rb_method_entry_t *me; + rb_method_entry_t *me; VALUE defined_class; VALUE origin_class = RCLASS_ORIGIN(klass); @@ -1212,7 +1068,7 @@ rb_export_method(VALUE klass, ID name, rb_method_visibility_t visi) rb_vm_check_redefinition_opt_method(me, klass); if (klass == defined_class || origin_class == defined_class) { - METHOD_ENTRY_VISI_SET((rb_method_entry_t *)me, visi); + METHOD_ENTRY_VISI_SET(me, visi); if (me->def->type == VM_METHOD_TYPE_REFINED && me->def->body.refined.orig_me) { METHOD_ENTRY_VISI_SET((rb_method_entry_t *)me->def->body.refined.orig_me, visi); @@ -1740,7 +1596,7 @@ rb_alias(VALUE klass, ID alias_name, ID original_name) method_added(target_klass, alias_name); } else { - const rb_method_entry_t *alias_me; + rb_method_entry_t *alias_me; alias_me = method_entry_set(target_klass, alias_name, orig_me, visi, orig_me->owner); RB_OBJ_WRITE(alias_me, &alias_me->owner, target_klass); @@ -1931,7 +1787,7 @@ rb_mod_ruby2_keywords(int argc, VALUE *argv, VALUE module) for (i = 0; i < argc; i++) { VALUE v = argv[i]; ID name = rb_check_id(&v); - const rb_method_entry_t *me; + rb_method_entry_t *me; VALUE defined_class; if (!name) { |