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

* 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
parent 938eb46e80
commit 18bbd05709
17 changed files with 317 additions and 253 deletions

View file

@ -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> 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. * gem/bundled_gems: updated to test-unit 3.1.1 and minitest 5.7.0.

45
class.c
View file

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

View file

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

View file

@ -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); RB_OBJ_WRITE(cref, &cref->next, next_cref);
} }
static inline long typedef struct rb_scope_visi_struct {
CREF_VISI(const rb_cref_t *cref) 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 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 static inline VALUE
@ -282,7 +291,7 @@ CREF_OMOD_SHARED_UNSET(rb_cref_t *cref)
cref->flags &= ~NODE_FL_CREF_OMOD_SHARED_; 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_cleanup(void);
void rb_thread_wait_other_threads(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(VALUE, ID, int));
NORETURN(void rb_print_undef_str(VALUE, VALUE)); 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_localjump_error(const char *,VALUE, int));
NORETURN(void rb_vm_jump_tag_but_local_jump(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, NORETURN(void rb_raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv,

View file

@ -917,7 +917,7 @@ defineclass
vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS, vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS,
klass, 0, klass, 0,
VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()), 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->iseq_encoded, GET_SP(),
class_iseq->local_size, class_iseq->stack_max); class_iseq->local_size, class_iseq->stack_max);

View file

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

2
load.c
View file

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

View file

@ -21,27 +21,6 @@
# endif # endif
#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 */ /* method data type */
typedef struct rb_method_entry_struct { typedef struct rb_method_entry_struct {
@ -52,6 +31,13 @@ typedef struct rb_method_entry_struct {
const VALUE klass; /* should be marked */ const VALUE klass; /* should be marked */
} rb_method_entry_t; } 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 { typedef enum {
VM_METHOD_TYPE_ISEQ, VM_METHOD_TYPE_ISEQ,
VM_METHOD_TYPE_CFUNC, VM_METHOD_TYPE_CFUNC,
@ -92,10 +78,12 @@ typedef struct rb_method_alias_struct {
} rb_method_alias_t; } rb_method_alias_t;
typedef struct rb_method_definition_struct { 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 */ rb_method_type_t type; /* method type */
int *alias_count_ptr;
ID original_id;
union { union {
rb_method_iseq_t iseq; rb_method_iseq_t iseq;
@ -111,6 +99,9 @@ typedef struct rb_method_definition_struct {
} optimize_type; } optimize_type;
struct rb_method_entry_struct *orig_me; struct rb_method_entry_struct *orig_me;
} body; } body;
int *alias_count_ptr;
ID original_id;
} rb_method_definition_t; } rb_method_definition_t;
#define UNDEFINED_METHOD_ENTRY_P(me) (!(me) || !(me)->def || (me)->def->type == VM_METHOD_TYPE_UNDEF) #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 && \ ((def)->type == VM_METHOD_TYPE_REFINED && \
UNDEFINED_METHOD_ENTRY_P((def)->body.orig_me)) 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_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_flag_t noex); 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_flag_t noex); 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(VALUE klass, ID id, VALUE *define_class_ptr);
rb_method_entry_t *rb_method_entry_at(VALUE obj, ID id); rb_method_entry_t *rb_method_entry_at(VALUE obj, ID id);
void rb_add_refined_method_entry(VALUE refined_class, ID mid); 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); 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_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_arity(const rb_method_entry_t *me);
int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2); int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2);

View file

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

29
proc.c
View file

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

View file

@ -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 *); 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); 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); 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 *); 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); 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); RB_GC_GUARD(iseqval);
} }

17
vm.c
View file

@ -89,10 +89,10 @@ vm_cref_new(VALUE klass, long visi, const rb_cref_t *prev_cref)
static rb_cref_t * static rb_cref_t *
vm_cref_new_toplevel(rb_thread_t *th) 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) { 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; 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) rb_num_t is_singleton, rb_cref_t *cref)
{ {
VALUE klass = CREF_CLASS(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; rb_iseq_t *miseq;
GetISeqPtr(iseqval, miseq); GetISeqPtr(iseqval, miseq);
@ -2300,17 +2301,17 @@ vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval,
if (is_singleton) { if (is_singleton) {
klass = rb_singleton_class(obj); /* class and frozen checked in this API */ klass = rb_singleton_class(obj); /* class and frozen checked in this API */
noex = NOEX_PUBLIC; visi = METHOD_VISI_PUBLIC;
} }
/* dup */ /* dup */
RB_OBJ_WRITE(miseq->self, &miseq->klass, klass); RB_OBJ_WRITE(miseq->self, &miseq->klass, klass);
miseq->defined_method_id = id; 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); 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->self = th->top_self;
th->cfp->klass = Qnil; 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 * The Binding of the top level scope

View file

@ -167,7 +167,15 @@ typedef struct rb_call_info_struct {
union { union {
int opt_pc; /* used by iseq */ int opt_pc; /* used by iseq */
int index; /* used by ivar */ 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 */ int inc_sp; /* used by cfunc */
} aux; } aux;

View file

@ -15,7 +15,7 @@ struct local_var_list {
VALUE tbl; 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_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(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); 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); 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))) { 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); ret = method_missing(ci->recv, ci->mid, ci->argc, argv, ex);
goto success; 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; id = rb_vm_frame_method_entry(cfp)->def->original_id;
me = rb_method_entry(klass, id, &klass); me = rb_method_entry(klass, id, &klass);
if (!me) { 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); return vm_call0(th, recv, id, argc, argv, me, klass);
@ -321,8 +321,7 @@ stack_check(void)
static inline rb_method_entry_t * static inline rb_method_entry_t *
rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr); 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); static inline enum missing_reason rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self);
#define NOEX_OK NOEX_NOSUPER
/*! /*!
* \internal * \internal
@ -347,9 +346,9 @@ rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
rb_method_entry_t *me = rb_method_entry_t *me =
rb_search_method_entry(recv, mid, &defined_class); rb_search_method_entry(recv, mid, &defined_class);
rb_thread_t *th = GET_THREAD(); 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); return method_missing(recv, mid, argc, argv, call_status);
} }
stack_check(); stack_check();
@ -391,7 +390,7 @@ check_funcall_respond_to(rb_thread_t *th, VALUE klass, VALUE recv, ID mid)
VALUE defined_class; VALUE defined_class;
const rb_method_entry_t *me = rb_method_entry(klass, idRespond_to, &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; const rb_block_t *passed_block = th->passed_block;
VALUE args[2], result; VALUE args[2], result;
int arity = rb_method_entry_arity(me); 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 static int
check_funcall_callable(rb_thread_t *th, const rb_method_entry_t *me) 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 static VALUE
@ -450,7 +449,7 @@ rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
return Qundef; return Qundef;
me = rb_search_method_entry(recv, mid, &defined_class); 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); return check_funcall_missing(th, klass, recv, mid, argc, argv);
} }
stack_check(); stack_check();
@ -470,7 +469,7 @@ rb_check_funcall_with_hook(VALUE recv, ID mid, int argc, const VALUE *argv,
return Qundef; return Qundef;
me = rb_search_method_entry(recv, mid, &defined_class); 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); (*hook)(FALSE, recv, mid, argc, argv, arg);
return check_funcall_missing(th, klass, recv, mid, argc, argv); 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); 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) rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self)
{ {
VALUE klass; VALUE klass;
ID oid; ID oid;
int noex; rb_method_visibility_t visi;
if (UNDEFINED_METHOD_ENTRY_P(me)) { if (UNDEFINED_METHOD_ENTRY_P(me)) {
undefined: undefined:
return scope == CALL_VCALL ? NOEX_VCALL : 0; return scope == CALL_VCALL ? MISSING_VCALL : MISSING_NOENTRY;
} }
if (me->def->type == VM_METHOD_TYPE_REFINED) { if (me->def->type == VM_METHOD_TYPE_REFINED) {
me = rb_resolve_refined_method(Qnil, me, NULL); 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; klass = me->klass;
oid = me->def->original_id; oid = me->def->original_id;
noex = me->def->flag; visi = me->def->flags.visi;
if (oid != idMethodMissing) { if (oid != idMethodMissing) {
/* receiver specified form for private method */ /* receiver specified form for private method */
if (UNLIKELY(noex)) { if (UNLIKELY(visi != METHOD_VISI_PUBLIC)) {
if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == CALL_PUBLIC) { if (visi == METHOD_VISI_PRIVATE && scope == CALL_PUBLIC) {
return NOEX_PRIVATE; return MISSING_PRIVATE;
} }
/* self must be kind of a specified form for protected method */ /* 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; VALUE defined_class = klass;
if (RB_TYPE_P(defined_class, T_ICLASS)) { 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)) { if (self == Qundef || !rb_obj_is_kind_of(self, defined_class)) {
return NOEX_PROTECTED; return MISSING_PROTECTED;
} }
} }
if (NOEX_SAFE(noex) > th->safe_level) { if (me->def->flags.safe > th->safe_level) {
rb_raise(rb_eSecurityError, "calling insecure method: %"PRIsVALUE, rb_raise(rb_eSecurityError, "calling insecure method: %"PRIsVALUE, rb_id2str(me->called_id));
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, 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: * call-seq:
@ -668,8 +667,6 @@ rb_method_missing(int argc, const VALUE *argv, VALUE obj)
UNREACHABLE; UNREACHABLE;
} }
#define NOEX_MISSING 0x80
static VALUE static VALUE
make_no_method_exception(VALUE exc, const char *format, VALUE obj, int argc, const VALUE *argv) 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 static void
raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj, 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; VALUE exc = rb_eNoMethodError;
const char *format = 0; const char *format = 0;
@ -707,23 +704,23 @@ raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj,
stack_check(); stack_check();
if (last_call_status & NOEX_PRIVATE) { if (last_call_status & MISSING_PRIVATE) {
format = "private method `%s' called for %s"; 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"; 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"; format = "undefined local variable or method `%s' for %s";
exc = rb_eNameError; 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"; format = "super: no superclass method `%s' for %s";
} }
{ {
exc = make_no_method_exception(exc, format, obj, argc, argv); 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_vm_pop_cfunc_frame();
} }
rb_exc_raise(exc); 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 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; VALUE *nargv, result, work;
rb_thread_t *th = GET_THREAD(); 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; th->passed_block = 0;
if (id == idMethodMissing) { 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); 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); MEMCPY(nargv + 1, argv, VALUE, argc);
if (rb_method_basic_definition_p(CLASS_OF(obj) , idMethodMissing)) { 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; th->passed_block = blockptr;
result = rb_funcall2(obj, idMethodMissing, argc + 1, nargv); 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) VALUE obj, int call_status)
{ {
th->passed_block = 0; 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 (!cref && base_block->iseq) {
if (NIL_P(scope)) { if (NIL_P(scope)) {
orig_cref = rb_vm_get_cref(base_block->ep); 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; crefval = (VALUE) cref;
COPY_CREF(cref, orig_cref); COPY_CREF(cref, orig_cref);
} }
@ -1568,7 +1565,7 @@ yield_under(VALUE under, VALUE self, VALUE values)
block.self = self; block.self = self;
VM_CF_LEP(th->cfp)[0] = VM_ENVVAL_BLOCK_PTR(&block); 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); CREF_PUSHED_BY_EVAL_SET(cref);
if (values == Qundef) { if (values == Qundef) {
@ -1591,7 +1588,7 @@ rb_yield_refine_block(VALUE refinement, VALUE refinements)
block.self = refinement; block.self = refinement;
VM_CF_LEP(th->cfp)[0] = VM_ENVVAL_BLOCK_PTR(&block); 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_PUSHED_BY_EVAL_SET(cref);
CREF_REFINEMENTS_SET(cref, refinements); CREF_REFINEMENTS_SET(cref, refinements);
@ -1602,7 +1599,7 @@ rb_yield_refine_block(VALUE refinement, VALUE refinements)
static VALUE static VALUE
eval_under(VALUE under, VALUE self, VALUE src, VALUE file, int line) 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)) { if (SPECIAL_CONST_P(self) && !NIL_P(under)) {
CREF_PUSHED_BY_EVAL_SET(cref); CREF_PUSHED_BY_EVAL_SET(cref);
@ -2162,9 +2159,9 @@ Init_vm_eval(void)
#if 1 #if 1
rb_add_method(rb_cBasicObject, rb_intern("__send__"), 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"), 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 #else
rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1); rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
rb_define_method(rb_mKernel, "send", rb_f_send, -1); rb_define_method(rb_mKernel, "send", rb_f_send, -1);

View file

@ -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 * 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; const rb_cref_t *prev_cref = NULL;
rb_cref_t *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); 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? */ /* TODO: why CREF_NEXT(cref) is 1? */
if (CREF_NEXT(cref) && CREF_NEXT(cref) != (void *) 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, CI_SET_FASTPATH(ci,
(UNLIKELY(ci->flag & VM_CALL_TAILCALL) ? vm_call_iseq_setup_tailcall : vm_call_iseq_setup_normal), (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 { else {
ci->aux.opt_pc = setup_parameters_complex(th, iseq, ci, argv, arg_setup_method); 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); 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); 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->flag & VM_CALL_ARGS_SPLAT) &&
!(ci->kw_arg != NULL)) { !(ci->kw_arg != NULL)) {
CI_SET_FASTPATH(ci, vm_call_cfunc_latter, 1); 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); return vm_call_bmethod_body(th, ci, argv);
} }
static int static enum missing_reason
ci_missing_reason(const rb_call_info_t *ci) ci_missing_reason(const rb_call_info_t *ci)
{ {
int stat = 0; enum missing_reason stat = MISSING_NOENTRY;
if (ci->flag & VM_CALL_VCALL) { if (ci->flag & VM_CALL_VCALL) stat |= MISSING_VCALL;
stat |= NOEX_VCALL; if (ci->flag & VM_CALL_SUPER) stat |= MISSING_SUPER;
}
if (ci->flag & VM_CALL_SUPER) {
stat |= NOEX_SUPER;
}
return stat; 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: start_method_dispatch:
if (ci->me != 0) { 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; VALUE klass;
normal_method_dispatch: 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); rb_bug("vm_call_method: unsupported method type (%d)", ci->me->def->type);
} }
else { else {
int noex_safe; int safe;
if (!(ci->flag & VM_CALL_FCALL) && (ci->me->def->flag & NOEX_MASK) & NOEX_PRIVATE) { if (!(ci->flag & VM_CALL_FCALL) && (ci->me->def->flags.visi == METHOD_VISI_PRIVATE)) {
int stat = NOEX_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->aux.missing_reason = stat;
CI_SET_FASTPATH(ci, vm_call_method_missing, 1); CI_SET_FASTPATH(ci, vm_call_method_missing, 1);
return vm_call_method_missing(th, cfp, ci); 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; enable_fastpath = 0;
if (!rb_obj_is_kind_of(cfp->self, ci->defined_class)) { 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); return vm_call_method_missing(th, cfp, ci);
} }
else { else {
goto normal_method_dispatch; 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)); rb_raise(rb_eSecurityError, "calling insecure method: %"PRIsVALUE, rb_id2str(ci->mid));
} }
else { 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) { if (!ci->klass) {
/* bound instance method of module */ /* 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); CI_SET_FASTPATH(ci, vm_call_method_missing, 1);
return; 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) { if (me) {
const rb_method_definition_t *def = me->def; 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; expr_type = DEFINED_METHOD;
break;
default:
rb_bug("unreachable");
} }
} }
else { else {

View file

@ -157,7 +157,7 @@ enum vm_regan_acttype {
rb_cref_t *__tmp_c2 = (c2); \ rb_cref_t *__tmp_c2 = (c2); \
COPY_CREF_OMOD((c1), __tmp_c2); \ COPY_CREF_OMOD((c1), __tmp_c2); \
CREF_CLASS_SET((c1), CREF_CLASS(__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));\ CREF_NEXT_SET((c1), CREF_NEXT(__tmp_c2));\
if (CREF_PUSHED_BY_EVAL(__tmp_c2)) { \ if (CREF_PUSHED_BY_EVAL(__tmp_c2)) { \
CREF_PUSHED_BY_EVAL_SET(c1); \ CREF_PUSHED_BY_EVAL_SET(c1); \

View file

@ -110,23 +110,23 @@ rb_f_notimplement(int argc, const VALUE *argv, VALUE obj)
} }
static void 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 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 (argc < -2 || 15 < argc) rb_raise(rb_eArgError, "arity out of range: %d for -2..15", argc);
if (func != rb_f_notimplement) { if (func != rb_f_notimplement) {
rb_method_cfunc_t opt; rb_method_cfunc_t opt;
opt.func = func; opt.func = func;
opt.argc = argc; 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 { 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 * 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); rb_method_definition_t *def = ZALLOC(rb_method_definition_t);
/* def->alias_count_ptr = NULL; already cleared */ /* 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->type = type;
def->original_id = mid; def->original_id = mid;
if (opts != NULL) rb_method_definition_set(def, opts); 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) rb_method_definition_clone(rb_method_definition_t *src_def)
{ {
int *iptr = src_def->alias_count_ptr; 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)); memcpy(&def->body, &src_def->body, sizeof(def->body));
def->alias_count_ptr = src_def->alias_count_ptr; 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); 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); 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); rb_clear_method_cache_by_class(refined_class);
} }
else { 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 * 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; rb_method_entry_t *me;
#if NOEX_NOREDEF #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_clone:
case idInitialize_dup: case idInitialize_dup:
case idRespond_to_missing: 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); 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); rb_clear_method_cache_by_class(klass);
@ -537,10 +543,10 @@ method_added(VALUE klass, ID mid)
} }
rb_method_entry_t * 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_definition_t *def = rb_method_definition_create(visi, type, mid, opts);
rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, def, noex, klass); 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? */ 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); 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 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; rb_iseq_t *iseq;
GetISeqPtr(iseqval, iseq); GetISeqPtr(iseqval, iseq);
{ {
rb_method_iseq_t iseq_body = {iseq, cref}; 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 * static rb_method_entry_t *
method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, 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); method_added(klass, mid);
return newme; return newme;
} }
rb_method_entry_t * 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) #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 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; rb_method_entry_t *me;
VALUE defined_class; 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); 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); rb_vm_check_redefinition_opt_method(me, klass);
if (klass == defined_class || RCLASS_ORIGIN(klass) == defined_class) { 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) { 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); rb_clear_method_cache_by_class(klass);
} }
else { 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 int
rb_method_boundp(VALUE klass, ID id, int ex) 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) { if (me != 0) {
rb_method_definition_t *def = me->def; rb_method_definition_t *def = me->def;
if ((ex & ~NOEX_RESPONDS) && if ((ex & ~BOUND_RESPONDS) &&
((def->flag & NOEX_PRIVATE) || ((def->flags.visi == METHOD_VISI_PRIVATE) ||
((ex & NOEX_RESPONDS) && (def->flag & NOEX_PROTECTED)))) { ((ex & BOUND_RESPONDS) && (def->flags.visi == METHOD_VISI_PROTECTED)))) {
return 0; return 0;
} }
if (def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { if (def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
if (ex & NOEX_RESPONDS) return 2; if (ex & BOUND_RESPONDS) return 2;
return 0; return 0;
} }
return 1; return 1;
@ -923,29 +934,39 @@ rb_method_boundp(VALUE klass, ID id, int ex)
extern ID rb_check_attr_id(ID id); extern ID rb_check_attr_id(ID id);
static int 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_thread_t *th = GET_THREAD();
rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
if (!vm_env_cref_by_cref(cfp->ep)) { if (!vm_env_cref_by_cref(cfp->ep)) {
return NOEX_PUBLIC & flag; return METHOD_VISI_PUBLIC == visi;
} }
else { else {
return CREF_VISI(rb_vm_cref()) & flag; return CREF_SCOPE_VISI(rb_vm_cref())->method_visi == visi;
} }
} }
static int 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 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 void
@ -953,23 +974,23 @@ rb_attr(VALUE klass, ID id, int read, int write, int ex)
{ {
VALUE attriv; VALUE attriv;
VALUE aname; VALUE aname;
rb_method_flag_t noex; rb_method_visibility_t visi;
if (!ex) { if (!ex) {
noex = NOEX_PUBLIC; visi = METHOD_VISI_PUBLIC;
} }
else { else {
if (rb_frame_visibility_test(NOEX_PRIVATE)) { if (rb_frame_visibility_test(METHOD_VISI_PRIVATE)) {
noex = NOEX_PRIVATE; visi = METHOD_VISI_PRIVATE;
if (rb_frame_visibility_check(NOEX_MODFUNC)) { if (rb_frame_module_func_check()) {
rb_warning("attribute accessor as module_function"); rb_warning("attribute accessor as module_function");
} }
} }
else if (rb_frame_visibility_test(NOEX_PROTECTED)) { else if (rb_frame_visibility_test(METHOD_VISI_PROTECTED)) {
noex = NOEX_PROTECTED; visi = METHOD_VISI_PROTECTED;
} }
else { 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)); attriv = (VALUE)rb_intern_str(rb_sprintf("@%"PRIsVALUE, aname));
if (read) { 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) { 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)); 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); 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 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; const rb_method_entry_t *me;
ID id = rb_check_id(&mid); ID id = rb_check_id(&mid);
if (!id) return Qfalse; if (!id) return Qfalse;
me = rb_method_entry_without_refinements(mod, id, 0); me = rb_method_entry_without_refinements(mod, id, 0);
if (me) { if (me) {
if (VISI_CHECK(me->def->flag, noex)) return Qtrue; if (me->def->flags.visi == visi) return Qtrue;
} }
return Qfalse; return Qfalse;
} }
@ -1171,7 +1190,7 @@ check_definition(VALUE mod, VALUE mid, rb_method_flag_t noex)
static VALUE static VALUE
rb_mod_public_method_defined(VALUE mod, VALUE mid) 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 static VALUE
rb_mod_private_method_defined(VALUE mod, VALUE mid) 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 static VALUE
rb_mod_protected_method_defined(VALUE mod, VALUE mid) 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 int
@ -1353,7 +1372,7 @@ rb_alias(VALUE klass, ID alias_name, ID original_name)
const VALUE target_klass = klass; const VALUE target_klass = klass;
VALUE defined_class; VALUE defined_class;
rb_method_entry_t *orig_me; 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)) { if (NIL_P(klass)) {
rb_raise(rb_eTypeError, "no class to make alias"); 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) { if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) {
klass = RCLASS_SUPER(klass); klass = RCLASS_SUPER(klass);
original_name = orig_me->def->original_id; original_name = orig_me->def->original_id;
flag = orig_me->def->flag; visi = orig_me->def->flags.visi;
goto again; 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 */ if (defined_class != target_klass) { /* inter class/module alias */
VALUE real_owner; VALUE real_owner;
@ -1397,13 +1416,14 @@ rb_alias(VALUE klass, ID alias_name, ID original_name)
} }
/* make mthod entry */ /* 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); RB_OBJ_WRITE(alias_me, &alias_me->klass, defined_class);
alias_me->def->original_id = orig_me->called_id; alias_me->def->original_id = orig_me->called_id;
*(ID *)&alias_me->def->body.alias.original_me->called_id = alias_name; *(ID *)&alias_me->def->body.alias.original_me->called_id = alias_name;
alias_me->def->flags.safe = orig_me->def->flags.safe;
} }
else { 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 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; int i;
@ -1457,18 +1477,18 @@ set_method_visibility(VALUE self, int argc, const VALUE *argv, rb_method_flag_t
if (!id) { if (!id) {
rb_print_undef_str(self, v); rb_print_undef_str(self, v);
} }
rb_export_method(self, id, ex); rb_export_method(self, id, visi);
} }
} }
static VALUE 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) { if (argc == 0) {
rb_frame_visibility_set(ex); rb_frame_visibility_set(visi);
} }
else { else {
set_method_visibility(module, argc, argv, ex); set_method_visibility(module, argc, argv, visi);
} }
return module; return module;
} }
@ -1488,7 +1508,7 @@ set_visibility(int argc, const VALUE *argv, VALUE module, rb_method_flag_t ex)
static VALUE static VALUE
rb_mod_public(int argc, VALUE *argv, VALUE module) 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 static VALUE
rb_mod_protected(int argc, VALUE *argv, VALUE module) 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 static VALUE
rb_mod_private(int argc, VALUE *argv, VALUE module) 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 static VALUE
rb_mod_public_method(int argc, VALUE *argv, VALUE obj) 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; return obj;
} }
@ -1575,7 +1595,7 @@ rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
static VALUE static VALUE
rb_mod_private_method(int argc, VALUE *argv, VALUE obj) 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; return obj;
} }
@ -1666,11 +1686,11 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
} }
if (argc == 0) { if (argc == 0) {
rb_frame_visibility_set(NOEX_MODFUNC); rb_frame_module_func_set();
return module; 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++) { for (i = 0; i < argc; i++) {
VALUE m = module; VALUE m = module;
@ -1691,7 +1711,7 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
if (!m) if (!m)
break; 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; return module;
} }
@ -1700,8 +1720,7 @@ int
rb_method_basic_definition_p(VALUE klass, ID id) rb_method_basic_definition_p(VALUE klass, ID id)
{ {
const rb_method_entry_t *me = rb_method_entry(klass, id, 0); const rb_method_entry_t *me = rb_method_entry(klass, id, 0);
if (me && (me->def->flag & NOEX_BASIC)) return 1; return (me && me->def->flags.basic) ? TRUE : FALSE;
return 0;
} }
static inline int static inline int
@ -1710,7 +1729,7 @@ basic_obj_respond_to(VALUE obj, ID id, int pub)
VALUE klass = CLASS_OF(obj); VALUE klass = CLASS_OF(obj);
VALUE args[2]; VALUE args[2];
switch (rb_method_boundp(klass, id, pub|NOEX_RESPONDS)) { switch (rb_method_boundp(klass, id, pub|BOUND_RESPONDS)) {
case 2: case 2:
return FALSE; return FALSE;
case 0: case 0:
@ -1885,12 +1904,11 @@ Init_eval_method(void)
"private", top_private, -1); "private", top_private, -1);
{ {
#define REPLICATE_METHOD(klass, id, noex) \ #define REPLICATE_METHOD(klass, id, visi) \
rb_method_entry_set((klass), (id), \ rb_method_entry_set((klass), (id), rb_method_entry((klass), (id), 0), (visi));
rb_method_entry((klass), (id), 0), \
(rb_method_flag_t)(noex | NOEX_BASIC | NOEX_NOREDEF)) REPLICATE_METHOD(rb_eException, idMethodMissing, METHOD_VISI_PRIVATE);
REPLICATE_METHOD(rb_eException, idMethodMissing, NOEX_PRIVATE); REPLICATE_METHOD(rb_eException, idRespond_to, METHOD_VISI_PUBLIC);
REPLICATE_METHOD(rb_eException, idRespond_to, NOEX_PUBLIC); REPLICATE_METHOD(rb_eException, idRespond_to_missing, METHOD_VISI_PUBLIC);
REPLICATE_METHOD(rb_eException, idRespond_to_missing, NOEX_PUBLIC);
} }
} }