* method.h: split rb_method_definition_t::flag to several flags.

`flag' contains several categories of attributes and it makes us
  confusion (at least, I had confused).
  * rb_method_visibility_t (flags::visi)
    * NOEX_UNDEF     -> METHOD_VISI_UNDEF     = 0
    * NOEX_PUBLIC    -> METHOD_VISI_PUBLIC    = 1
    * NOEX_PRIVATE   -> METHOD_VISI_PRIVATE   = 2
    * NOEX_PROTECTED -> METHOD_VISI_PROTECTED = 3
  * NOEX_SAFE(flag)) -> safe (flags::safe, 2 bits)
  * NOEX_BASIC       -> basic (flags::basic, 1 bit)
  * NOEX_MODFUNC     -> rb_scope_visibility_t in CREF
  * NOEX_SUPER       -> MISSING_SUPER (enum missing_reason)
  * NOEX_VCALL       -> MISSING_VCALL (enum missing_reason)
  * NOEX_RESPONDS    -> BOUND_RESPONDS (macro)
  Now, NOEX_NOREDEF is not supported (I'm not sure it is needed).
  Background:
    I did not know what "NOEX" stands for.
    I asked Matz (who made this name) and his answer was "Nothing".
    "At first, it meant NO EXport (private), but the original
    meaning was gone."
    This is why I remove the mysterious word "NOEX" from MRI.
* vm_core.h: introduce `enum missing_reason' to represent
  method_missing (NoMethodError) reason.
* eval_intern.h: introduce rb_scope_visibility_t to represent
  scope visibility.
  It has 3 method visibilities (public/private/protected)
  and `module_function`.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50743 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2015-06-03 01:39:16 +00:00
Родитель 938eb46e80
Коммит 18bbd05709
17 изменённых файлов: 317 добавлений и 253 удалений

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

@ -1,3 +1,39 @@
Wed Jun 03 10:35:45 2015 Koichi Sasada <ko1@atdot.net>
* method.h: split rb_method_definition_t::flag to several flags.
`flag' contains several categories of attributes and it makes us
confusion (at least, I had confused).
* rb_method_visibility_t (flags::visi)
* NOEX_UNDEF -> METHOD_VISI_UNDEF = 0
* NOEX_PUBLIC -> METHOD_VISI_PUBLIC = 1
* NOEX_PRIVATE -> METHOD_VISI_PRIVATE = 2
* NOEX_PROTECTED -> METHOD_VISI_PROTECTED = 3
* NOEX_SAFE(flag)) -> safe (flags::safe, 2 bits)
* NOEX_BASIC -> basic (flags::basic, 1 bit)
* NOEX_MODFUNC -> rb_scope_visibility_t in CREF
* NOEX_SUPER -> MISSING_SUPER (enum missing_reason)
* NOEX_VCALL -> MISSING_VCALL (enum missing_reason)
* NOEX_RESPONDS -> BOUND_RESPONDS (macro)
Now, NOEX_NOREDEF is not supported (I'm not sure it is needed).
Background:
I did not know what "NOEX" stands for.
I asked Matz (who made this name) and his answer was "Nothing".
"At first, it meant NO EXport (private), but the original
meaning was gone."
This is why I remove the mysterious word "NOEX" from MRI.
* vm_core.h: introduce `enum missing_reason' to represent
method_missing (NoMethodError) reason.
* eval_intern.h: introduce rb_scope_visibility_t to represent
scope visibility.
It has 3 method visibilities (public/private/protected)
and `module_function`.
Wed Jun 3 08:06:30 2015 NAKAMURA Usaku <usa@ruby-lang.org>
* gem/bundled_gems: updated to test-unit 3.1.1 and minitest 5.7.0.

45
class.c
Просмотреть файл

@ -249,11 +249,11 @@ clone_method(VALUE klass, ID mid, const rb_method_entry_t *me)
rb_cref_t *new_cref;
newiseqval = rb_iseq_clone(me->def->body.iseq.iseqptr->self, klass);
rb_vm_rewrite_cref_stack(me->def->body.iseq.cref, me->klass, klass, &new_cref);
rb_add_method_iseq(klass, mid, newiseqval, new_cref, me->def->flag);
rb_add_method_iseq(klass, mid, newiseqval, new_cref, me->def->flags.visi);
RB_GC_GUARD(newiseqval);
}
else {
rb_method_entry_set(klass, mid, me, me->def->flag);
rb_method_entry_set(klass, mid, me, me->def->flags.visi);
}
}
else {
@ -1055,22 +1055,21 @@ rb_mod_ancestors(VALUE mod)
return ary;
}
#define VISI(x) ((x)&NOEX_MASK)
#define VISI_CHECK(x,f) (VISI(x) == (f))
static int
ins_methods_push(ID name, long type, VALUE ary, long visi)
{
if (type == -1) return ST_CONTINUE;
if (type == METHOD_VISI_UNDEF) return ST_CONTINUE;
switch (visi) {
case NOEX_PRIVATE:
case NOEX_PROTECTED:
case NOEX_PUBLIC:
switch ((rb_method_visibility_t)visi) {
case METHOD_VISI_UNDEF:
return ST_CONTINUE;
case METHOD_VISI_PRIVATE:
case METHOD_VISI_PROTECTED:
case METHOD_VISI_PUBLIC:
visi = (type == visi);
break;
default:
visi = (type != NOEX_PRIVATE);
visi = (type != METHOD_VISI_PRIVATE);
break;
}
if (visi) {
@ -1088,19 +1087,19 @@ ins_methods_i(st_data_t name, st_data_t type, st_data_t ary)
static int
ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary)
{
return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PROTECTED);
return ins_methods_push((ID)name, (long)type, (VALUE)ary, METHOD_VISI_PROTECTED);
}
static int
ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary)
{
return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PRIVATE);
return ins_methods_push((ID)name, (long)type, (VALUE)ary, METHOD_VISI_PRIVATE);
}
static int
ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary)
{
return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC);
return ins_methods_push((ID)name, (long)type, (VALUE)ary, METHOD_VISI_PUBLIC);
}
struct method_entry_arg {
@ -1113,7 +1112,7 @@ method_entry_i(st_data_t key, st_data_t value, st_data_t data)
{
const rb_method_entry_t *me = (const rb_method_entry_t *)value;
struct method_entry_arg *arg = (struct method_entry_arg *)data;
long type;
rb_method_visibility_t type;
if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
VALUE klass = me->klass;
@ -1123,12 +1122,12 @@ method_entry_i(st_data_t key, st_data_t value, st_data_t data)
}
if (!st_lookup(arg->list, key, 0)) {
if (UNDEFINED_METHOD_ENTRY_P(me)) {
type = -1; /* none */
type = METHOD_VISI_UNDEF; /* none */
}
else {
type = VISI(me->def->flag);
type = me->def->flags.visi;
}
st_add_direct(arg->list, key, type);
st_add_direct(arg->list, key, (long)type);
}
return ST_CONTINUE;
}
@ -1469,31 +1468,31 @@ rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj)
void
rb_define_method_id(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc)
{
rb_add_method_cfunc(klass, mid, func, argc, NOEX_PUBLIC);
rb_add_method_cfunc(klass, mid, func, argc, METHOD_VISI_PUBLIC);
}
void
rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
{
rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PUBLIC);
rb_add_method_cfunc(klass, rb_intern(name), func, argc, METHOD_VISI_PUBLIC);
}
void
rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
{
rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PROTECTED);
rb_add_method_cfunc(klass, rb_intern(name), func, argc, METHOD_VISI_PROTECTED);
}
void
rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
{
rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PRIVATE);
rb_add_method_cfunc(klass, rb_intern(name), func, argc, METHOD_VISI_PRIVATE);
}
void
rb_undef_method(VALUE klass, const char *name)
{
rb_add_method(klass, rb_intern(name), VM_METHOD_TYPE_UNDEF, 0, NOEX_UNDEF);
rb_add_method(klass, rb_intern(name), VM_METHOD_TYPE_UNDEF, 0, METHOD_VISI_UNDEF);
}
/*!

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

@ -209,23 +209,22 @@ ruby_error_print(void)
}
static const char *
method_scope_name(int scope)
method_visibility_name(rb_method_visibility_t visi)
{
const char *v;
switch (scope) {
default:
case NOEX_PUBLIC: v = ""; break;
case NOEX_PRIVATE: v = " private"; break;
case NOEX_PROTECTED: v = " protected"; break;
switch (visi) {
case METHOD_VISI_UNDEF:
case METHOD_VISI_PUBLIC: return "";
case METHOD_VISI_PRIVATE: return " private";
case METHOD_VISI_PROTECTED: return " protected";
}
return v;
rb_bug("method_visibility_name: unreachable (%d)", (int)visi);
}
void
rb_print_undef(VALUE klass, ID id, int scope)
rb_print_undef(VALUE klass, ID id, int visi)
{
const char *v = method_scope_name(scope);
const char *v = method_visibility_name(visi);
rb_name_error(id, "undefined%s method `%"PRIsVALUE"' for %s `% "PRIsVALUE"'", v,
QUOTE_ID(id),
(RB_TYPE_P(klass, T_MODULE)) ? "module" : "class",
@ -242,9 +241,9 @@ rb_print_undef_str(VALUE klass, VALUE name)
}
void
rb_print_inaccessible(VALUE klass, ID id, int scope)
rb_print_inaccessible(VALUE klass, ID id, rb_method_visibility_t visi)
{
const char *v = method_scope_name(scope);
const char *v = method_visibility_name(visi);
rb_name_error(id, "method `%"PRIsVALUE"' for %s `% "PRIsVALUE"' is %s",
QUOTE_ID(id),
(RB_TYPE_P(klass, T_MODULE)) ? "module" : "class",

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

@ -228,16 +228,25 @@ CREF_NEXT_SET(rb_cref_t *cref, const rb_cref_t *next_cref)
RB_OBJ_WRITE(cref, &cref->next, next_cref);
}
static inline long
CREF_VISI(const rb_cref_t *cref)
typedef struct rb_scope_visi_struct {
rb_method_visibility_t method_visi : 3;
unsigned int module_func : 1;
} rb_scope_visibility_t;
static inline const rb_scope_visibility_t *
CREF_SCOPE_VISI(const rb_cref_t *cref)
{
return (long)cref->visi;
return (const rb_scope_visibility_t *)&cref->scope_visi;
}
static inline void
CREF_VISI_SET(rb_cref_t *cref, long v)
CREF_SCOPE_VISI_COPY(const rb_cref_t *dst_cref, rb_cref_t *src_cref)
{
cref->visi = v;
rb_scope_visibility_t *src = (rb_scope_visibility_t *)&src_cref->scope_visi;
rb_scope_visibility_t *dst = (rb_scope_visibility_t *)&dst_cref->scope_visi;
dst->method_visi = src->method_visi;
dst->module_func = src->module_func;
}
static inline VALUE
@ -282,7 +291,7 @@ CREF_OMOD_SHARED_UNSET(rb_cref_t *cref)
cref->flags &= ~NODE_FL_CREF_OMOD_SHARED_;
}
void rb_frame_visibility_set(rb_method_flag_t);
void rb_frame_visibility_set(rb_method_visibility_t);
void rb_thread_cleanup(void);
void rb_thread_wait_other_threads(void);
@ -308,7 +317,7 @@ NORETURN(void rb_fiber_start(void));
NORETURN(void rb_print_undef(VALUE, ID, int));
NORETURN(void rb_print_undef_str(VALUE, VALUE));
NORETURN(void rb_print_inaccessible(VALUE, ID, int));
NORETURN(void rb_print_inaccessible(VALUE, ID, rb_method_visibility_t));
NORETURN(void rb_vm_localjump_error(const char *,VALUE, int));
NORETURN(void rb_vm_jump_tag_but_local_jump(int));
NORETURN(void rb_raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv,

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

@ -917,7 +917,7 @@ defineclass
vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS,
klass, 0,
VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()),
(VALUE)vm_cref_push(th, klass, NOEX_PUBLIC, NULL),
(VALUE)vm_cref_push(th, klass, NULL),
class_iseq->iseq_encoded, GET_SP(),
class_iseq->local_size, class_iseq->stack_max);

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

@ -551,7 +551,7 @@ typedef struct rb_cref_struct {
VALUE flags;
const VALUE refinements;
const VALUE klass;
VALUE visi;
VALUE scope_visi;
struct rb_cref_struct * const next;
} rb_cref_t;

2
load.c
Просмотреть файл

@ -935,7 +935,7 @@ load_failed(VALUE fname)
static VALUE
load_ext(VALUE path)
{
rb_frame_visibility_set(NOEX_PUBLIC);
rb_frame_visibility_set(METHOD_VISI_PUBLIC);
return (VALUE)dln_load(RSTRING_PTR(path));
}

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

@ -21,27 +21,6 @@
# endif
#endif
typedef enum {
NOEX_PUBLIC = 0x00,
NOEX_NOSUPER = 0x01,
NOEX_PRIVATE = 0x02,
NOEX_PROTECTED = 0x04,
NOEX_MASK = 0x06,
NOEX_BASIC = 0x08,
NOEX_UNDEF = NOEX_NOSUPER,
NOEX_MODFUNC = 0x12,
NOEX_SUPER = 0x20,
NOEX_VCALL = 0x40,
NOEX_RESPONDS = 0x80,
NOEX_BIT_WIDTH = 8,
NOEX_SAFE_SHIFT_OFFSET = ((NOEX_BIT_WIDTH+3)/4)*4 /* round up to nibble */
} rb_method_flag_t;
#define NOEX_SAFE(n) ((int)((n) >> NOEX_SAFE_SHIFT_OFFSET) & 0x0F)
#define NOEX_WITH(n, s) (((s) << NOEX_SAFE_SHIFT_OFFSET) | (n) | (ruby_running ? 0 : NOEX_BASIC))
#define NOEX_WITH_SAFE(n) NOEX_WITH((n), rb_safe_level())
/* method data type */
typedef struct rb_method_entry_struct {
@ -52,6 +31,13 @@ typedef struct rb_method_entry_struct {
const VALUE klass; /* should be marked */
} rb_method_entry_t;
typedef enum {
METHOD_VISI_UNDEF = 0x00,
METHOD_VISI_PUBLIC = 0x01,
METHOD_VISI_PRIVATE = 0x02,
METHOD_VISI_PROTECTED = 0x03
} rb_method_visibility_t;
typedef enum {
VM_METHOD_TYPE_ISEQ,
VM_METHOD_TYPE_CFUNC,
@ -92,10 +78,12 @@ typedef struct rb_method_alias_struct {
} rb_method_alias_t;
typedef struct rb_method_definition_struct {
rb_method_flag_t flag;
struct {
rb_method_visibility_t visi: 3;
unsigned int basic: 1;
unsigned int safe: 3;
} flags;
rb_method_type_t type; /* method type */
int *alias_count_ptr;
ID original_id;
union {
rb_method_iseq_t iseq;
@ -111,6 +99,9 @@ typedef struct rb_method_definition_struct {
} optimize_type;
struct rb_method_entry_struct *orig_me;
} body;
int *alias_count_ptr;
ID original_id;
} rb_method_definition_t;
#define UNDEFINED_METHOD_ENTRY_P(me) (!(me) || !(me)->def || (me)->def->type == VM_METHOD_TYPE_UNDEF)
@ -118,9 +109,9 @@ typedef struct rb_method_definition_struct {
((def)->type == VM_METHOD_TYPE_REFINED && \
UNDEFINED_METHOD_ENTRY_P((def)->body.orig_me))
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex);
void rb_add_method_iseq(VALUE klass, ID mid, VALUE iseqval, rb_cref_t *cref, rb_method_flag_t noex);
rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_flag_t noex);
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_visibility_t visi);
void rb_add_method_iseq(VALUE klass, ID mid, VALUE iseqval, rb_cref_t *cref, rb_method_visibility_t visi);
rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_visibility_t visi);
rb_method_entry_t *rb_method_entry(VALUE klass, ID id, VALUE *define_class_ptr);
rb_method_entry_t *rb_method_entry_at(VALUE obj, ID id);
void rb_add_refined_method_entry(VALUE refined_class, ID mid);
@ -133,7 +124,7 @@ rb_method_entry_t *rb_method_entry_without_refinements(VALUE klass, ID id,
VALUE *defined_class_ptr);
rb_method_entry_t *rb_method_entry_get_without_cache(VALUE klass, ID id, VALUE *define_class_ptr);
rb_method_entry_t *rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_flag_t noex);
rb_method_entry_t *rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_visibility_t noex);
int rb_method_entry_arity(const rb_method_entry_t *me);
int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2);

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

@ -3012,7 +3012,7 @@ primary : literal
/*%%%*/
NODE *body = remove_begin($5);
reduce_nodes(&body);
$$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE);
$$ = NEW_DEFN($2, $4, body, METHOD_VISI_PRIVATE);
nd_set_line($$, $<num>1);
/*%
$$ = dispatch3(def, $2, $4, $5);

29
proc.c
Просмотреть файл

@ -1161,7 +1161,7 @@ mnew_missing(VALUE rclass, VALUE klass, VALUE obj, ID id, ID rid, VALUE mclass)
data->id = rid;
def = ZALLOC(rb_method_definition_t);
def->flag = 0;
def->flags.visi = METHOD_VISI_UNDEF;
def->type = VM_METHOD_TYPE_MISSING;
def->original_id = id;
@ -1182,7 +1182,7 @@ mnew_internal(const rb_method_entry_t *me, VALUE defined_class, VALUE klass,
VALUE method;
ID rid = id;
rb_method_definition_t *def = 0;
rb_method_flag_t flag = NOEX_UNDEF;
rb_method_visibility_t visi = METHOD_VISI_UNDEF;
again:
if (UNDEFINED_METHOD_ENTRY_P(me)) {
@ -1193,11 +1193,11 @@ mnew_internal(const rb_method_entry_t *me, VALUE defined_class, VALUE klass,
rb_print_undef(klass, id, 0);
}
def = me->def;
if (flag == NOEX_UNDEF) {
flag = def->flag;
if (scope && (flag & NOEX_MASK) != NOEX_PUBLIC) {
if (visi == METHOD_VISI_UNDEF) {
visi = def->flags.visi;
if (scope && (visi != METHOD_VISI_PUBLIC)) {
if (!error) return Qnil;
rb_print_inaccessible(klass, id, flag & NOEX_MASK);
rb_print_inaccessible(klass, id, visi);
}
}
if (def->type == VM_METHOD_TYPE_ZSUPER) {
@ -1658,11 +1658,12 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
{
ID id;
VALUE body;
rb_method_flag_t noex = NOEX_PUBLIC;
const rb_cref_t *cref = rb_vm_cref_in_context(mod, mod);
const rb_scope_visibility_t default_scope_visi = {METHOD_VISI_PUBLIC, FALSE};
const rb_scope_visibility_t *scope_visi = &default_scope_visi;
if (cref) {
noex = (rb_method_flag_t)CREF_VISI(cref);
scope_visi = CREF_SCOPE_VISI(cref);
}
if (argc == 1) {
@ -1695,9 +1696,9 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
rb_class_name(rclass));
}
}
rb_method_entry_set(mod, id, method->me, noex);
if (noex == NOEX_MODFUNC) {
rb_method_entry_set(rb_singleton_class(mod), id, method->me, NOEX_PUBLIC);
rb_method_entry_set(mod, id, method->me, scope_visi->method_visi);
if (scope_visi->module_func) {
rb_method_entry_set(rb_singleton_class(mod), id, method->me, METHOD_VISI_PUBLIC);
}
RB_GC_GUARD(body);
}
@ -1712,9 +1713,9 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
proc->is_from_method = TRUE;
proc->block.klass = mod;
}
rb_add_method(mod, id, VM_METHOD_TYPE_BMETHOD, (void *)body, noex);
if (noex == NOEX_MODFUNC) {
rb_add_method(rb_singleton_class(mod), id, VM_METHOD_TYPE_BMETHOD, (void *)body, NOEX_PUBLIC);
rb_add_method(mod, id, VM_METHOD_TYPE_BMETHOD, (void *)body, scope_visi->method_visi);
if (scope_visi->module_func) {
rb_add_method(rb_singleton_class(mod), id, VM_METHOD_TYPE_BMETHOD, (void *)body, METHOD_VISI_PUBLIC);
}
}
else {

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

@ -177,7 +177,7 @@ define_aref_method(VALUE nstr, VALUE name, VALUE off)
rb_control_frame_t *FUNC_FASTCALL(rb_vm_opt_struct_aref)(rb_thread_t *, rb_control_frame_t *);
VALUE iseqval = rb_method_for_self_aref(name, off, rb_vm_opt_struct_aref);
rb_add_method_iseq(nstr, SYM2ID(name), iseqval, NULL, NOEX_PUBLIC);
rb_add_method_iseq(nstr, SYM2ID(name), iseqval, NULL, METHOD_VISI_PUBLIC);
RB_GC_GUARD(iseqval);
}
@ -187,7 +187,7 @@ define_aset_method(VALUE nstr, VALUE name, VALUE off)
rb_control_frame_t *FUNC_FASTCALL(rb_vm_opt_struct_aset)(rb_thread_t *, rb_control_frame_t *);
VALUE iseqval = rb_method_for_self_aset(name, off, rb_vm_opt_struct_aset);
rb_add_method_iseq(nstr, SYM2ID(name), iseqval, NULL, NOEX_PUBLIC);
rb_add_method_iseq(nstr, SYM2ID(name), iseqval, NULL, METHOD_VISI_PUBLIC);
RB_GC_GUARD(iseqval);
}

17
vm.c
Просмотреть файл

@ -89,10 +89,10 @@ vm_cref_new(VALUE klass, long visi, const rb_cref_t *prev_cref)
static rb_cref_t *
vm_cref_new_toplevel(rb_thread_t *th)
{
rb_cref_t *cref = vm_cref_new(rb_cObject, NOEX_PRIVATE /* toplevel visibility is private */, NULL);
rb_cref_t *cref = vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE /* toplevel visibility is private */, NULL);
if (th->top_wrapper) {
cref = vm_cref_new(th->top_wrapper, NOEX_PRIVATE, cref);
cref = vm_cref_new(th->top_wrapper, METHOD_VISI_PRIVATE, cref);
}
return cref;
@ -2285,7 +2285,8 @@ vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval,
rb_num_t is_singleton, rb_cref_t *cref)
{
VALUE klass = CREF_CLASS(cref);
rb_method_flag_t noex = (rb_method_flag_t)CREF_VISI(cref);
const rb_scope_visibility_t *scope_visi = CREF_SCOPE_VISI(cref);
rb_method_visibility_t visi = scope_visi->method_visi;
rb_iseq_t *miseq;
GetISeqPtr(iseqval, miseq);
@ -2300,17 +2301,17 @@ vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval,
if (is_singleton) {
klass = rb_singleton_class(obj); /* class and frozen checked in this API */
noex = NOEX_PUBLIC;
visi = METHOD_VISI_PUBLIC;
}
/* dup */
RB_OBJ_WRITE(miseq->self, &miseq->klass, klass);
miseq->defined_method_id = id;
rb_add_method_iseq(klass, id, iseqval, cref, noex);
rb_add_method_iseq(klass, id, iseqval, cref, visi);
if (!is_singleton && noex == NOEX_MODFUNC) {
if (!is_singleton && scope_visi->module_func) {
klass = rb_singleton_class(klass);
rb_add_method_iseq(klass, id, iseqval, cref, NOEX_PUBLIC);
rb_add_method_iseq(klass, id, iseqval, cref, METHOD_VISI_PUBLIC);
}
}
@ -2797,7 +2798,7 @@ Init_VM(void)
th->cfp->self = th->top_self;
th->cfp->klass = Qnil;
th->cfp->ep[-1] = (VALUE)vm_cref_new(rb_cObject, NOEX_PRIVATE, NULL);
th->cfp->ep[-1] = (VALUE)vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE, NULL);
/*
* The Binding of the top level scope

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

@ -167,7 +167,15 @@ typedef struct rb_call_info_struct {
union {
int opt_pc; /* used by iseq */
int index; /* used by ivar */
int missing_reason; /* used by method_missing */
enum missing_reason {
MISSING_NOENTRY = 0x00,
MISSING_PRIVATE = 0x01,
MISSING_PROTECTED = 0x02,
MISSING_VCALL = 0x04,
MISSING_SUPER = 0x08,
MISSING_MISSING = 0x10,
MISSING_NONE = 0x20
} missing_reason; /* used by method_missing */
int inc_sp; /* used by cfunc */
} aux;

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

@ -15,7 +15,7 @@ struct local_var_list {
VALUE tbl;
};
static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status);
static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum missing_reason call_status);
static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const rb_cref_t *cref);
static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
static inline VALUE vm_yield_with_block(rb_thread_t *th, int argc, const VALUE *argv, const rb_block_t *blockargptr);
@ -208,7 +208,7 @@ vm_call0_body(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv)
ci->defined_class = RCLASS_SUPER(ci->defined_class);
if (!ci->defined_class || !(ci->me = rb_method_entry(ci->defined_class, ci->mid, &ci->defined_class))) {
int ex = type == VM_METHOD_TYPE_ZSUPER ? NOEX_SUPER : 0;
enum missing_reason ex = (type == VM_METHOD_TYPE_ZSUPER) ? MISSING_SUPER : 0;
ret = method_missing(ci->recv, ci->mid, ci->argc, argv, ex);
goto success;
}
@ -285,7 +285,7 @@ vm_call_super(rb_thread_t *th, int argc, const VALUE *argv)
id = rb_vm_frame_method_entry(cfp)->def->original_id;
me = rb_method_entry(klass, id, &klass);
if (!me) {
return method_missing(recv, id, argc, argv, NOEX_SUPER);
return method_missing(recv, id, argc, argv, MISSING_SUPER);
}
return vm_call0(th, recv, id, argc, argv, me, klass);
@ -321,8 +321,7 @@ stack_check(void)
static inline rb_method_entry_t *
rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr);
static inline int rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self);
#define NOEX_OK NOEX_NOSUPER
static inline enum missing_reason rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self);
/*!
* \internal
@ -347,9 +346,9 @@ rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
rb_method_entry_t *me =
rb_search_method_entry(recv, mid, &defined_class);
rb_thread_t *th = GET_THREAD();
int call_status = rb_method_call_status(th, me, scope, self);
enum missing_reason call_status = rb_method_call_status(th, me, scope, self);
if (call_status != NOEX_OK) {
if (call_status != MISSING_NONE) {
return method_missing(recv, mid, argc, argv, call_status);
}
stack_check();
@ -391,7 +390,7 @@ check_funcall_respond_to(rb_thread_t *th, VALUE klass, VALUE recv, ID mid)
VALUE defined_class;
const rb_method_entry_t *me = rb_method_entry(klass, idRespond_to, &defined_class);
if (me && !(me->def->flag & NOEX_BASIC)) {
if (me && !me->def->flags.basic) {
const rb_block_t *passed_block = th->passed_block;
VALUE args[2], result;
int arity = rb_method_entry_arity(me);
@ -415,7 +414,7 @@ check_funcall_respond_to(rb_thread_t *th, VALUE klass, VALUE recv, ID mid)
static int
check_funcall_callable(rb_thread_t *th, const rb_method_entry_t *me)
{
return rb_method_call_status(th, me, CALL_FCALL, th->cfp->self) == NOEX_OK;
return rb_method_call_status(th, me, CALL_FCALL, th->cfp->self) == MISSING_NONE;
}
static VALUE
@ -450,7 +449,7 @@ rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
return Qundef;
me = rb_search_method_entry(recv, mid, &defined_class);
if (check_funcall_callable(th, me) != NOEX_OK) {
if (!check_funcall_callable(th, me)) {
return check_funcall_missing(th, klass, recv, mid, argc, argv);
}
stack_check();
@ -470,7 +469,7 @@ rb_check_funcall_with_hook(VALUE recv, ID mid, int argc, const VALUE *argv,
return Qundef;
me = rb_search_method_entry(recv, mid, &defined_class);
if (check_funcall_callable(th, me) != NOEX_OK) {
if (!check_funcall_callable(th, me)) {
(*hook)(FALSE, recv, mid, argc, argv, arg);
return check_funcall_missing(th, klass, recv, mid, argc, argv);
}
@ -557,16 +556,16 @@ rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr)
return rb_method_entry(klass, mid, defined_class_ptr);
}
static inline int
static inline enum missing_reason
rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self)
{
VALUE klass;
ID oid;
int noex;
rb_method_visibility_t visi;
if (UNDEFINED_METHOD_ENTRY_P(me)) {
undefined:
return scope == CALL_VCALL ? NOEX_VCALL : 0;
return scope == CALL_VCALL ? MISSING_VCALL : MISSING_NOENTRY;
}
if (me->def->type == VM_METHOD_TYPE_REFINED) {
me = rb_resolve_refined_method(Qnil, me, NULL);
@ -574,17 +573,17 @@ rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type sc
}
klass = me->klass;
oid = me->def->original_id;
noex = me->def->flag;
visi = me->def->flags.visi;
if (oid != idMethodMissing) {
/* receiver specified form for private method */
if (UNLIKELY(noex)) {
if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == CALL_PUBLIC) {
return NOEX_PRIVATE;
if (UNLIKELY(visi != METHOD_VISI_PUBLIC)) {
if (visi == METHOD_VISI_PRIVATE && scope == CALL_PUBLIC) {
return MISSING_PRIVATE;
}
/* self must be kind of a specified form for protected method */
if (((noex & NOEX_MASK) & NOEX_PROTECTED) && scope == CALL_PUBLIC) {
if (visi == METHOD_VISI_PROTECTED && scope == CALL_PUBLIC) {
VALUE defined_class = klass;
if (RB_TYPE_P(defined_class, T_ICLASS)) {
@ -592,17 +591,17 @@ rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type sc
}
if (self == Qundef || !rb_obj_is_kind_of(self, defined_class)) {
return NOEX_PROTECTED;
return MISSING_PROTECTED;
}
}
if (NOEX_SAFE(noex) > th->safe_level) {
rb_raise(rb_eSecurityError, "calling insecure method: %"PRIsVALUE,
rb_id2str(me->called_id));
if (me->def->flags.safe > th->safe_level) {
rb_raise(rb_eSecurityError, "calling insecure method: %"PRIsVALUE, rb_id2str(me->called_id));
}
}
}
return NOEX_OK;
return MISSING_NONE;
}
@ -625,7 +624,7 @@ rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
}
NORETURN(static void raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv,
VALUE obj, int call_status));
VALUE obj, enum missing_reason call_status));
/*
* call-seq:
@ -668,8 +667,6 @@ rb_method_missing(int argc, const VALUE *argv, VALUE obj)
UNREACHABLE;
}
#define NOEX_MISSING 0x80
static VALUE
make_no_method_exception(VALUE exc, const char *format, VALUE obj, int argc, const VALUE *argv)
{
@ -696,7 +693,7 @@ make_no_method_exception(VALUE exc, const char *format, VALUE obj, int argc, con
static void
raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj,
int last_call_status)
enum missing_reason last_call_status)
{
VALUE exc = rb_eNoMethodError;
const char *format = 0;
@ -707,23 +704,23 @@ raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj,
stack_check();
if (last_call_status & NOEX_PRIVATE) {
if (last_call_status & MISSING_PRIVATE) {
format = "private method `%s' called for %s";
}
else if (last_call_status & NOEX_PROTECTED) {
else if (last_call_status & MISSING_PROTECTED) {
format = "protected method `%s' called for %s";
}
else if (last_call_status & NOEX_VCALL) {
else if (last_call_status & MISSING_VCALL) {
format = "undefined local variable or method `%s' for %s";
exc = rb_eNameError;
}
else if (last_call_status & NOEX_SUPER) {
else if (last_call_status & MISSING_SUPER) {
format = "super: no superclass method `%s' for %s";
}
{
exc = make_no_method_exception(exc, format, obj, argc, argv);
if (!(last_call_status & NOEX_MISSING)) {
if (!(last_call_status & MISSING_MISSING)) {
rb_vm_pop_cfunc_frame();
}
rb_exc_raise(exc);
@ -731,7 +728,7 @@ raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj,
}
static inline VALUE
method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum missing_reason call_status)
{
VALUE *nargv, result, work;
rb_thread_t *th = GET_THREAD();
@ -741,7 +738,7 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
th->passed_block = 0;
if (id == idMethodMissing) {
raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING);
raise_method_missing(th, argc, argv, obj, call_status | MISSING_MISSING);
}
nargv = ALLOCV_N(VALUE, work, argc + 1);
@ -749,7 +746,7 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
MEMCPY(nargv + 1, argv, VALUE, argc);
if (rb_method_basic_definition_p(CLASS_OF(obj) , idMethodMissing)) {
raise_method_missing(th, argc+1, nargv, obj, call_status | NOEX_MISSING);
raise_method_missing(th, argc+1, nargv, obj, call_status | MISSING_MISSING);
}
th->passed_block = blockptr;
result = rb_funcall2(obj, idMethodMissing, argc + 1, nargv);
@ -762,7 +759,7 @@ rb_raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv,
VALUE obj, int call_status)
{
th->passed_block = 0;
raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING);
raise_method_missing(th, argc, argv, obj, call_status | MISSING_MISSING);
}
/*!
@ -1310,7 +1307,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_
if (!cref && base_block->iseq) {
if (NIL_P(scope)) {
orig_cref = rb_vm_get_cref(base_block->ep);
cref = vm_cref_new(Qnil, 0, NULL);
cref = vm_cref_new(Qnil, METHOD_VISI_PUBLIC, NULL);
crefval = (VALUE) cref;
COPY_CREF(cref, orig_cref);
}
@ -1568,7 +1565,7 @@ yield_under(VALUE under, VALUE self, VALUE values)
block.self = self;
VM_CF_LEP(th->cfp)[0] = VM_ENVVAL_BLOCK_PTR(&block);
}
cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
cref = vm_cref_push(th, under, blockptr);
CREF_PUSHED_BY_EVAL_SET(cref);
if (values == Qundef) {
@ -1591,7 +1588,7 @@ rb_yield_refine_block(VALUE refinement, VALUE refinements)
block.self = refinement;
VM_CF_LEP(th->cfp)[0] = VM_ENVVAL_BLOCK_PTR(&block);
}
cref = vm_cref_push(th, refinement, NOEX_PUBLIC, blockptr);
cref = vm_cref_push(th, refinement, blockptr);
CREF_PUSHED_BY_EVAL_SET(cref);
CREF_REFINEMENTS_SET(cref, refinements);
@ -1602,7 +1599,7 @@ rb_yield_refine_block(VALUE refinement, VALUE refinements)
static VALUE
eval_under(VALUE under, VALUE self, VALUE src, VALUE file, int line)
{
rb_cref_t *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL);
rb_cref_t *cref = vm_cref_push(GET_THREAD(), under, NULL);
if (SPECIAL_CONST_P(self) && !NIL_P(under)) {
CREF_PUSHED_BY_EVAL_SET(cref);
@ -2162,9 +2159,9 @@ Init_vm_eval(void)
#if 1
rb_add_method(rb_cBasicObject, rb_intern("__send__"),
VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, METHOD_VISI_PUBLIC);
rb_add_method(rb_mKernel, rb_intern("send"),
VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, METHOD_VISI_PUBLIC);
#else
rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
rb_define_method(rb_mKernel, "send", rb_f_send, -1);

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

@ -487,7 +487,7 @@ rb_vm_rewrite_cref_stack(rb_cref_t *node, VALUE old_klass, VALUE new_klass, rb_c
}
static rb_cref_t *
vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
vm_cref_push(rb_thread_t *th, VALUE klass, rb_block_t *blockptr)
{
const rb_cref_t *prev_cref = NULL;
rb_cref_t *cref = NULL;
@ -502,7 +502,7 @@ vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
prev_cref = vm_env_cref(cfp->ep);
}
}
cref = vm_cref_new(klass, noex, prev_cref);
cref = vm_cref_new(klass, METHOD_VISI_PUBLIC, prev_cref);
/* TODO: why CREF_NEXT(cref) is 1? */
if (CREF_NEXT(cref) && CREF_NEXT(cref) != (void *) 1 &&
@ -1315,7 +1315,7 @@ vm_callee_setup_arg(rb_thread_t *th, rb_call_info_t *ci, const rb_iseq_t *iseq,
CI_SET_FASTPATH(ci,
(UNLIKELY(ci->flag & VM_CALL_TAILCALL) ? vm_call_iseq_setup_tailcall : vm_call_iseq_setup_normal),
(!IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) && !(ci->me->def->flag & NOEX_PROTECTED)));
(!IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) && !(ci->me->def->flags.visi == METHOD_VISI_PROTECTED)));
}
else {
ci->aux.opt_pc = setup_parameters_complex(th, iseq, ci, argv, arg_setup_method);
@ -1659,7 +1659,7 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, me->klass, me->called_id);
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass, Qnil);
if (!(ci->me->def->flag & NOEX_PROTECTED) &&
if (!(ci->me->def->flag & METHOD_VISI_PROTECTED) &&
!(ci->flag & VM_CALL_ARGS_SPLAT) &&
!(ci->kw_arg != NULL)) {
CI_SET_FASTPATH(ci, vm_call_cfunc_latter, 1);
@ -1740,16 +1740,12 @@ vm_call_bmethod(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
return vm_call_bmethod_body(th, ci, argv);
}
static int
static enum missing_reason
ci_missing_reason(const rb_call_info_t *ci)
{
int stat = 0;
if (ci->flag & VM_CALL_VCALL) {
stat |= NOEX_VCALL;
}
if (ci->flag & VM_CALL_SUPER) {
stat |= NOEX_SUPER;
}
enum missing_reason stat = MISSING_NOENTRY;
if (ci->flag & VM_CALL_VCALL) stat |= MISSING_VCALL;
if (ci->flag & VM_CALL_SUPER) stat |= MISSING_SUPER;
return stat;
}
@ -1915,7 +1911,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
start_method_dispatch:
if (ci->me != 0) {
if ((ci->me->def->flag == 0)) {
if (ci->me->def->flags.visi == METHOD_VISI_PUBLIC && ci->me->def->flags.safe == 0) {
VALUE klass;
normal_method_dispatch:
@ -2042,28 +2038,27 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
rb_bug("vm_call_method: unsupported method type (%d)", ci->me->def->type);
}
else {
int noex_safe;
if (!(ci->flag & VM_CALL_FCALL) && (ci->me->def->flag & NOEX_MASK) & NOEX_PRIVATE) {
int stat = NOEX_PRIVATE;
int safe;
if (!(ci->flag & VM_CALL_FCALL) && (ci->me->def->flags.visi == METHOD_VISI_PRIVATE)) {
enum missing_reason stat = MISSING_PRIVATE;
bp();
if (ci->flag & VM_CALL_VCALL) stat |= MISSING_VCALL;
if (ci->flag & VM_CALL_VCALL) {
stat |= NOEX_VCALL;
}
ci->aux.missing_reason = stat;
CI_SET_FASTPATH(ci, vm_call_method_missing, 1);
return vm_call_method_missing(th, cfp, ci);
}
else if (!(ci->flag & VM_CALL_OPT_SEND) && (ci->me->def->flag & NOEX_MASK) & NOEX_PROTECTED) {
else if (!(ci->flag & VM_CALL_OPT_SEND) && (ci->me->def->flags.visi == METHOD_VISI_PROTECTED)) {
enable_fastpath = 0;
if (!rb_obj_is_kind_of(cfp->self, ci->defined_class)) {
ci->aux.missing_reason = NOEX_PROTECTED;
ci->aux.missing_reason = MISSING_PROTECTED;
return vm_call_method_missing(th, cfp, ci);
}
else {
goto normal_method_dispatch;
}
}
else if ((noex_safe = NOEX_SAFE(ci->me->def->flag)) > th->safe_level && (noex_safe > 2)) {
else if ((safe = ci->me->def->flags.safe) > th->safe_level && safe > 2) {
rb_raise(rb_eSecurityError, "calling insecure method: %"PRIsVALUE, rb_id2str(ci->mid));
}
else {
@ -2216,7 +2211,7 @@ vm_search_super_method(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_inf
}
if (!ci->klass) {
/* bound instance method of module */
ci->aux.missing_reason = NOEX_SUPER;
ci->aux.missing_reason = MISSING_SUPER;
CI_SET_FASTPATH(ci, vm_call_method_missing, 1);
return;
}
@ -2475,9 +2470,19 @@ vm_defined(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE
if (me) {
const rb_method_definition_t *def = me->def;
if (!(def->flag & NOEX_PRIVATE) &&
!((def->flag & NOEX_PROTECTED) && !rb_obj_is_kind_of(GET_SELF(), rb_class_real(klass)))) {
switch ((unsigned int)def->flags.visi) {
case METHOD_VISI_PRIVATE:
break;
case METHOD_VISI_PROTECTED:
if (!rb_obj_is_kind_of(GET_SELF(), rb_class_real(klass))) {
break;
}
case METHOD_VISI_PUBLIC:
expr_type = DEFINED_METHOD;
break;
default:
rb_bug("unreachable");
}
}
else {

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

@ -157,7 +157,7 @@ enum vm_regan_acttype {
rb_cref_t *__tmp_c2 = (c2); \
COPY_CREF_OMOD((c1), __tmp_c2); \
CREF_CLASS_SET((c1), CREF_CLASS(__tmp_c2));\
CREF_VISI_SET((c1), CREF_VISI(__tmp_c2));\
CREF_SCOPE_VISI_COPY((c1), __tmp_c2);\
CREF_NEXT_SET((c1), CREF_NEXT(__tmp_c2));\
if (CREF_PUSHED_BY_EVAL(__tmp_c2)) { \
CREF_PUSHED_BY_EVAL_SET(c1); \

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

@ -110,23 +110,23 @@ rb_f_notimplement(int argc, const VALUE *argv, VALUE obj)
}
static void
rb_define_notimplement_method_id(VALUE mod, ID id, rb_method_flag_t noex)
rb_define_notimplement_method_id(VALUE mod, ID id, rb_method_visibility_t visi)
{
rb_add_method(mod, id, VM_METHOD_TYPE_NOTIMPLEMENTED, (void *)1, noex);
rb_add_method(mod, id, VM_METHOD_TYPE_NOTIMPLEMENTED, (void *)1, visi);
}
void
rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex)
rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_visibility_t visi)
{
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;
opt.func = func;
opt.argc = argc;
rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, noex);
rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, visi);
}
else {
rb_define_notimplement_method_id(klass, mid, noex);
rb_define_notimplement_method_id(klass, mid, visi);
}
}
@ -293,11 +293,13 @@ rb_method_definition_set(rb_method_definition_t *def, void *opts)
}
static rb_method_definition_t *
rb_method_definition_create(rb_method_flag_t flag, rb_method_type_t type, ID mid, void *opts)
rb_method_definition_create(rb_method_visibility_t visi, rb_method_type_t type, ID mid, void *opts)
{
rb_method_definition_t *def = ZALLOC(rb_method_definition_t);
/* def->alias_count_ptr = NULL; already cleared */
def->flag = flag;
def->flags.visi = visi;
def->flags.basic = ruby_running ? FALSE : TRUE;
def->flags.safe = rb_safe_level();
def->type = type;
def->original_id = mid;
if (opts != NULL) rb_method_definition_set(def, opts);
@ -335,7 +337,10 @@ static rb_method_definition_t *
rb_method_definition_clone(rb_method_definition_t *src_def)
{
int *iptr = src_def->alias_count_ptr;
rb_method_definition_t *def = rb_method_definition_create(src_def->flag, src_def->type, src_def->original_id, NULL);
rb_method_definition_t *def = rb_method_definition_create(src_def->flags.visi, src_def->type, src_def->original_id, NULL);
def->flags.basic = src_def->flags.basic;
def->flags.safe = src_def->flags.safe;
memcpy(&def->body, &src_def->body, sizeof(def->body));
def->alias_count_ptr = src_def->alias_count_ptr;
@ -383,7 +388,7 @@ make_method_entry_refined(rb_method_entry_t *me)
rb_vm_check_redefinition_opt_method(me, me->klass);
new_def = rb_method_definition_create(NOEX_WITH_SAFE(NOEX_PUBLIC), VM_METHOD_TYPE_REFINED, me->called_id, rb_method_entry_clone(me));
new_def = rb_method_definition_create(METHOD_VISI_PUBLIC, VM_METHOD_TYPE_REFINED, me->called_id, rb_method_entry_clone(me));
rb_method_definition_reset(me, new_def);
}
@ -397,12 +402,12 @@ rb_add_refined_method_entry(VALUE refined_class, ID mid)
rb_clear_method_cache_by_class(refined_class);
}
else {
rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0, NOEX_PUBLIC);
rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0, METHOD_VISI_PUBLIC);
}
}
static rb_method_entry_t *
rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, rb_method_definition_t *def, rb_method_flag_t noex, VALUE defined_class)
rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, rb_method_definition_t *def, rb_method_visibility_t visi, VALUE defined_class)
{
rb_method_entry_t *me;
#if NOEX_NOREDEF
@ -424,7 +429,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, rb_method_defin
case idInitialize_clone:
case idInitialize_dup:
case idRespond_to_missing:
noex |= NOEX_PRIVATE;
visi = METHOD_VISI_PRIVATE;
}
}
@ -492,7 +497,8 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, rb_method_defin
}
me = rb_method_entry_create(mid, defined_class, def);
def->flag = NOEX_WITH_SAFE(noex);;
def->flags.visi = visi;
def->flags.safe = rb_safe_level(); /* TODO: maybe we need to remove it. */
rb_clear_method_cache_by_class(klass);
@ -537,10 +543,10 @@ method_added(VALUE klass, ID mid)
}
rb_method_entry_t *
rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex)
rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_visibility_t visi)
{
rb_method_definition_t *def = rb_method_definition_create(noex, type, mid, opts);
rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, def, noex, klass);
rb_method_definition_t *def = rb_method_definition_create(visi, type, mid, opts);
rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, def, visi, klass);
if (me->def->type == VM_METHOD_TYPE_REFINED && me->def->body.orig_me) { /* TODO: really needed? */
rb_method_definition_reset(me->def->body.orig_me, def);
@ -553,29 +559,31 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_
}
void
rb_add_method_iseq(VALUE klass, ID mid, VALUE iseqval, rb_cref_t *cref, rb_method_flag_t noex)
rb_add_method_iseq(VALUE klass, ID mid, VALUE iseqval, rb_cref_t *cref, rb_method_visibility_t visi)
{
rb_iseq_t *iseq;
GetISeqPtr(iseqval, iseq);
{
rb_method_iseq_t iseq_body = {iseq, cref};
rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, &iseq_body, noex);
rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, &iseq_body, visi);
}
}
static rb_method_entry_t *
method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me,
rb_method_flag_t noex, VALUE defined_class)
rb_method_visibility_t visi, VALUE defined_class)
{
rb_method_entry_t *newme = rb_method_entry_make(klass, mid, me->def->type, rb_method_definition_clone(me->def), noex, defined_class);
rb_method_definition_t *def = rb_method_definition_clone(me->def);
rb_method_entry_t *newme = rb_method_entry_make(klass, mid, me->def->type, def, visi, defined_class);
def->flags.safe = me->def->flags.safe;
method_added(klass, mid);
return newme;
}
rb_method_entry_t *
rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_flag_t noex)
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, noex, klass);
return method_entry_set(klass, mid, me, visi, klass);
}
#define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1)
@ -864,7 +872,7 @@ rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
}
static void
rb_export_method(VALUE klass, ID name, rb_method_flag_t noex)
rb_export_method(VALUE klass, ID name, rb_method_visibility_t visi)
{
rb_method_entry_t *me;
VALUE defined_class;
@ -879,23 +887,26 @@ rb_export_method(VALUE klass, ID name, rb_method_flag_t noex)
rb_print_undef(klass, name, 0);
}
if (me->def->flag != noex) {
if (me->def->flags.visi != visi) {
rb_vm_check_redefinition_opt_method(me, klass);
if (klass == defined_class || RCLASS_ORIGIN(klass) == defined_class) {
me->def->flag = noex;
me->def->flags.visi = visi;
if (me->def->type == VM_METHOD_TYPE_REFINED && me->def->body.orig_me) {
me->def->body.orig_me->def->flag = noex;
me->def->body.orig_me->def->flags.visi = visi;
}
rb_clear_method_cache_by_class(klass);
}
else {
rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, noex);
rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, visi);
}
}
}
#define BOUND_PRIVATE 0x01
#define BOUND_RESPONDS 0x02
int
rb_method_boundp(VALUE klass, ID id, int ex)
{
@ -905,14 +916,14 @@ rb_method_boundp(VALUE klass, ID id, int ex)
if (me != 0) {
rb_method_definition_t *def = me->def;
if ((ex & ~NOEX_RESPONDS) &&
((def->flag & NOEX_PRIVATE) ||
((ex & NOEX_RESPONDS) && (def->flag & NOEX_PROTECTED)))) {
if ((ex & ~BOUND_RESPONDS) &&
((def->flags.visi == METHOD_VISI_PRIVATE) ||
((ex & BOUND_RESPONDS) && (def->flags.visi == METHOD_VISI_PROTECTED)))) {
return 0;
}
if (def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
if (ex & NOEX_RESPONDS) return 2;
if (ex & BOUND_RESPONDS) return 2;
return 0;
}
return 1;
@ -923,29 +934,39 @@ rb_method_boundp(VALUE klass, ID id, int ex)
extern ID rb_check_attr_id(ID id);
static int
rb_frame_visibility_test(rb_method_flag_t flag)
rb_frame_visibility_test(rb_method_visibility_t visi)
{
rb_thread_t *th = GET_THREAD();
rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
if (!vm_env_cref_by_cref(cfp->ep)) {
return NOEX_PUBLIC & flag;
return METHOD_VISI_PUBLIC == visi;
}
else {
return CREF_VISI(rb_vm_cref()) & flag;
return CREF_SCOPE_VISI(rb_vm_cref())->method_visi == visi;
}
}
static int
rb_frame_visibility_check(rb_method_flag_t flag)
rb_frame_module_func_check(void)
{
return CREF_VISI(rb_vm_cref()) == (long)flag;
return CREF_SCOPE_VISI(rb_vm_cref())->module_func;
}
void
rb_frame_visibility_set(rb_method_flag_t flag)
rb_frame_visibility_set(rb_method_visibility_t visi)
{
CREF_VISI_SET(rb_vm_cref(), flag);
rb_scope_visibility_t *scope_visi = (rb_scope_visibility_t *)&rb_vm_cref()->scope_visi;
scope_visi->method_visi = visi;
scope_visi->module_func = FALSE;
}
void
rb_frame_module_func_set(void)
{
rb_scope_visibility_t *scope_visi = (rb_scope_visibility_t *)&rb_vm_cref()->scope_visi;
scope_visi->method_visi = METHOD_VISI_PRIVATE;
scope_visi->module_func = TRUE;
}
void
@ -953,23 +974,23 @@ rb_attr(VALUE klass, ID id, int read, int write, int ex)
{
VALUE attriv;
VALUE aname;
rb_method_flag_t noex;
rb_method_visibility_t visi;
if (!ex) {
noex = NOEX_PUBLIC;
visi = METHOD_VISI_PUBLIC;
}
else {
if (rb_frame_visibility_test(NOEX_PRIVATE)) {
noex = NOEX_PRIVATE;
if (rb_frame_visibility_check(NOEX_MODFUNC)) {
if (rb_frame_visibility_test(METHOD_VISI_PRIVATE)) {
visi = METHOD_VISI_PRIVATE;
if (rb_frame_module_func_check()) {
rb_warning("attribute accessor as module_function");
}
}
else if (rb_frame_visibility_test(NOEX_PROTECTED)) {
noex = NOEX_PROTECTED;
else if (rb_frame_visibility_test(METHOD_VISI_PROTECTED)) {
visi = METHOD_VISI_PROTECTED;
}
else {
noex = NOEX_PUBLIC;
visi = METHOD_VISI_PUBLIC;
}
}
@ -979,10 +1000,10 @@ rb_attr(VALUE klass, ID id, int read, int write, int ex)
}
attriv = (VALUE)rb_intern_str(rb_sprintf("@%"PRIsVALUE, aname));
if (read) {
rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, noex);
rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, visi);
}
if (write) {
rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, noex);
rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, visi);
}
}
@ -1021,7 +1042,7 @@ rb_undef(VALUE klass, ID id)
QUOTE_ID(id), s0, rb_class_name(c));
}
rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC);
rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, METHOD_VISI_PUBLIC);
CALL_METHOD_HOOK(klass, undefined, id);
}
@ -1125,17 +1146,15 @@ rb_mod_method_defined(VALUE mod, VALUE mid)
}
#define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
static VALUE
check_definition(VALUE mod, VALUE mid, rb_method_flag_t noex)
check_definition(VALUE mod, VALUE mid, rb_method_visibility_t visi)
{
const rb_method_entry_t *me;
ID id = rb_check_id(&mid);
if (!id) return Qfalse;
me = rb_method_entry_without_refinements(mod, id, 0);
if (me) {
if (VISI_CHECK(me->def->flag, noex)) return Qtrue;
if (me->def->flags.visi == visi) return Qtrue;
}
return Qfalse;
}
@ -1171,7 +1190,7 @@ check_definition(VALUE mod, VALUE mid, rb_method_flag_t noex)
static VALUE
rb_mod_public_method_defined(VALUE mod, VALUE mid)
{
return check_definition(mod, mid, NOEX_PUBLIC);
return check_definition(mod, mid, METHOD_VISI_PUBLIC);
}
/*
@ -1205,7 +1224,7 @@ rb_mod_public_method_defined(VALUE mod, VALUE mid)
static VALUE
rb_mod_private_method_defined(VALUE mod, VALUE mid)
{
return check_definition(mod, mid, NOEX_PRIVATE);
return check_definition(mod, mid, METHOD_VISI_PRIVATE);
}
/*
@ -1239,7 +1258,7 @@ rb_mod_private_method_defined(VALUE mod, VALUE mid)
static VALUE
rb_mod_protected_method_defined(VALUE mod, VALUE mid)
{
return check_definition(mod, mid, NOEX_PROTECTED);
return check_definition(mod, mid, METHOD_VISI_PROTECTED);
}
int
@ -1353,7 +1372,7 @@ rb_alias(VALUE klass, ID alias_name, ID original_name)
const VALUE target_klass = klass;
VALUE defined_class;
rb_method_entry_t *orig_me;
rb_method_flag_t flag = NOEX_UNDEF;
rb_method_visibility_t visi = METHOD_VISI_UNDEF;
if (NIL_P(klass)) {
rb_raise(rb_eTypeError, "no class to make alias");
@ -1379,11 +1398,11 @@ rb_alias(VALUE klass, ID alias_name, ID original_name)
if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) {
klass = RCLASS_SUPER(klass);
original_name = orig_me->def->original_id;
flag = orig_me->def->flag;
visi = orig_me->def->flags.visi;
goto again;
}
if (flag == NOEX_UNDEF) flag = orig_me->def->flag;
if (visi == METHOD_VISI_UNDEF) visi = orig_me->def->flags.visi;
if (defined_class != target_klass) { /* inter class/module alias */
VALUE real_owner;
@ -1397,13 +1416,14 @@ rb_alias(VALUE klass, ID alias_name, ID original_name)
}
/* make mthod entry */
alias_me = rb_add_method(target_klass, alias_name, VM_METHOD_TYPE_ALIAS, rb_method_entry_clone(orig_me), flag);
alias_me = rb_add_method(target_klass, alias_name, VM_METHOD_TYPE_ALIAS, rb_method_entry_clone(orig_me), visi);
RB_OBJ_WRITE(alias_me, &alias_me->klass, defined_class);
alias_me->def->original_id = orig_me->called_id;
*(ID *)&alias_me->def->body.alias.original_me->called_id = alias_name;
alias_me->def->flags.safe = orig_me->def->flags.safe;
}
else {
method_entry_set(target_klass, alias_name, orig_me, flag, defined_class);
method_entry_set(target_klass, alias_name, orig_me, visi, defined_class);
}
}
@ -1441,7 +1461,7 @@ rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
}
static void
set_method_visibility(VALUE self, int argc, const VALUE *argv, rb_method_flag_t ex)
set_method_visibility(VALUE self, int argc, const VALUE *argv, rb_method_visibility_t visi)
{
int i;
@ -1457,18 +1477,18 @@ set_method_visibility(VALUE self, int argc, const VALUE *argv, rb_method_flag_t
if (!id) {
rb_print_undef_str(self, v);
}
rb_export_method(self, id, ex);
rb_export_method(self, id, visi);
}
}
static VALUE
set_visibility(int argc, const VALUE *argv, VALUE module, rb_method_flag_t ex)
set_visibility(int argc, const VALUE *argv, VALUE module, rb_method_visibility_t visi)
{
if (argc == 0) {
rb_frame_visibility_set(ex);
rb_frame_visibility_set(visi);
}
else {
set_method_visibility(module, argc, argv, ex);
set_method_visibility(module, argc, argv, visi);
}
return module;
}
@ -1488,7 +1508,7 @@ set_visibility(int argc, const VALUE *argv, VALUE module, rb_method_flag_t ex)
static VALUE
rb_mod_public(int argc, VALUE *argv, VALUE module)
{
return set_visibility(argc, argv, module, NOEX_PUBLIC);
return set_visibility(argc, argv, module, METHOD_VISI_PUBLIC);
}
/*
@ -1506,7 +1526,7 @@ rb_mod_public(int argc, VALUE *argv, VALUE module)
static VALUE
rb_mod_protected(int argc, VALUE *argv, VALUE module)
{
return set_visibility(argc, argv, module, NOEX_PROTECTED);
return set_visibility(argc, argv, module, METHOD_VISI_PROTECTED);
}
/*
@ -1533,7 +1553,7 @@ rb_mod_protected(int argc, VALUE *argv, VALUE module)
static VALUE
rb_mod_private(int argc, VALUE *argv, VALUE module)
{
return set_visibility(argc, argv, module, NOEX_PRIVATE);
return set_visibility(argc, argv, module, METHOD_VISI_PRIVATE);
}
/*
@ -1549,7 +1569,7 @@ rb_mod_private(int argc, VALUE *argv, VALUE module)
static VALUE
rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
{
set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PUBLIC);
set_method_visibility(rb_singleton_class(obj), argc, argv, METHOD_VISI_PUBLIC);
return obj;
}
@ -1575,7 +1595,7 @@ rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
static VALUE
rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
{
set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PRIVATE);
set_method_visibility(rb_singleton_class(obj), argc, argv, METHOD_VISI_PRIVATE);
return obj;
}
@ -1666,11 +1686,11 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
}
if (argc == 0) {
rb_frame_visibility_set(NOEX_MODFUNC);
rb_frame_module_func_set();
return module;
}
set_method_visibility(module, argc, argv, NOEX_PRIVATE);
set_method_visibility(module, argc, argv, METHOD_VISI_PRIVATE);
for (i = 0; i < argc; i++) {
VALUE m = module;
@ -1691,7 +1711,7 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
if (!m)
break;
}
rb_method_entry_set(rb_singleton_class(module), id, me, NOEX_PUBLIC);
rb_method_entry_set(rb_singleton_class(module), id, me, METHOD_VISI_PUBLIC);
}
return module;
}
@ -1700,8 +1720,7 @@ int
rb_method_basic_definition_p(VALUE klass, ID id)
{
const rb_method_entry_t *me = rb_method_entry(klass, id, 0);
if (me && (me->def->flag & NOEX_BASIC)) return 1;
return 0;
return (me && me->def->flags.basic) ? TRUE : FALSE;
}
static inline int
@ -1710,7 +1729,7 @@ basic_obj_respond_to(VALUE obj, ID id, int pub)
VALUE klass = CLASS_OF(obj);
VALUE args[2];
switch (rb_method_boundp(klass, id, pub|NOEX_RESPONDS)) {
switch (rb_method_boundp(klass, id, pub|BOUND_RESPONDS)) {
case 2:
return FALSE;
case 0:
@ -1885,12 +1904,11 @@ Init_eval_method(void)
"private", top_private, -1);
{
#define REPLICATE_METHOD(klass, id, noex) \
rb_method_entry_set((klass), (id), \
rb_method_entry((klass), (id), 0), \
(rb_method_flag_t)(noex | NOEX_BASIC | NOEX_NOREDEF))
REPLICATE_METHOD(rb_eException, idMethodMissing, NOEX_PRIVATE);
REPLICATE_METHOD(rb_eException, idRespond_to, NOEX_PUBLIC);
REPLICATE_METHOD(rb_eException, idRespond_to_missing, NOEX_PUBLIC);
#define REPLICATE_METHOD(klass, id, visi) \
rb_method_entry_set((klass), (id), rb_method_entry((klass), (id), 0), (visi));
REPLICATE_METHOD(rb_eException, idMethodMissing, METHOD_VISI_PRIVATE);
REPLICATE_METHOD(rb_eException, idRespond_to, METHOD_VISI_PUBLIC);
REPLICATE_METHOD(rb_eException, idRespond_to_missing, METHOD_VISI_PUBLIC);
}
}