summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c164
1 files changed, 94 insertions, 70 deletions
diff --git a/eval.c b/eval.c
index 42617c2b27..2452c68e79 100644
--- a/eval.c
+++ b/eval.c
@@ -6,7 +6,7 @@
$Date$
created at: Thu Jun 10 14:22:17 JST 1993
- Copyright (C) 1993-1997 Yukihiro Matsumoto
+ Copyright (C) 1993-1998 Yukihiro Matsumoto
************************************************/
@@ -43,6 +43,7 @@ static VALUE f_binding _((VALUE));
static void f_END _((void));
#define SCOPE_PRIVATE FL_USER4
+#define SCOPE_MODFUNC FL_USER5
#define CACHE_SIZE 0x200
#define CACHE_MASK 0x1ff
@@ -282,15 +283,15 @@ static struct FRAME *top_frame;
static struct SCOPE *top_scope;
#define PUSH_FRAME() { \
- struct FRAME *_frame = ALLOCA_N(struct FRAME,1);\
- _frame->prev = the_frame; \
- _frame->file = sourcefile; \
- _frame->line = sourceline; \
- _frame->iter = the_iter->iter; \
- _frame->cbase = the_frame->cbase; \
- the_frame = _frame; \
+ struct FRAME _frame; \
+ _frame.prev = the_frame; \
+ _frame.file = sourcefile; \
+ _frame.line = sourceline; \
+ _frame.iter = the_iter->iter; \
+ _frame.cbase = the_frame->cbase; \
+ the_frame = &_frame; \
-#define POP_FRAME() the_frame = _frame->prev; }
+#define POP_FRAME() the_frame = _frame.prev; }
struct BLOCK {
NODE *var;
@@ -309,29 +310,29 @@ struct BLOCK {
} *the_block;
#define PUSH_BLOCK(v,b) { \
- struct BLOCK *_block = ALLOCA_N(struct BLOCK,1);\
- _block->tag = prot_tag; \
- _block->var = v; \
- _block->body = b; \
- _block->self = self; \
- _block->frame = *the_frame; \
- _block->class = the_class; \
- _block->frame.file = sourcefile; \
- _block->frame.line = sourceline; \
- _block->scope = the_scope; \
- _block->d_vars = the_dyna_vars; \
- _block->prev = the_block; \
- _block->iter = the_iter->iter; \
- the_block = _block;
+ struct BLOCK _block; \
+ _block.tag = prot_tag; \
+ _block.var = v; \
+ _block.body = b; \
+ _block.self = self; \
+ _block.frame = *the_frame; \
+ _block.class = the_class; \
+ _block.frame.file = sourcefile; \
+ _block.frame.line = sourceline; \
+ _block.scope = the_scope; \
+ _block.d_vars = the_dyna_vars; \
+ _block.prev = the_block; \
+ _block.iter = the_iter->iter; \
+ the_block = &_block;
#define PUSH_BLOCK2(b) { \
- struct BLOCK *_block = ALLOCA_N(struct BLOCK,1);\
- *_block = *b; \
- _block->prev = the_block; \
- the_block = _block;
+ struct BLOCK _block; \
+ _block = *b; \
+ _block.prev = the_block; \
+ the_block = &_block;
#define POP_BLOCK() \
- the_block = the_block->prev; \
+ the_block = _block.prev; \
}
struct RVarmap *the_dyna_vars;
@@ -416,38 +417,26 @@ static struct iter {
the_iter = _iter.prev; \
}
-#ifdef C_ALLOCA
-/* need to protect retval in struct tag from GC. */
-#define tag_retval_dcl VALUE *dd_retval
-#define tag_retval_init VALUE _tag_retval = Qnil;\
- _tag->dd_retval = &_tag_retval;
-#define tag_retval dd_retval[0]
-#else
-#define tag_retval_dcl VALUE retval
-#define tag_retval_init _tag->retval = Qnil
-#define tag_retval retval
-#endif
-
static struct tag {
jmp_buf buf;
struct FRAME *frame;
struct iter *iter;
ID tag;
- tag_retval_dcl;
+ VALUE retval;
ID dst;
struct tag *prev;
} *prot_tag;
#define PUSH_TAG(ptag) { \
- struct tag *_tag = ALLOCA_N(struct tag,1);\
- tag_retval_init; \
- _tag->frame = the_frame; \
- _tag->iter = the_iter; \
- _tag->prev = prot_tag; \
- _tag->tag_retval = Qnil; \
- _tag->tag = ptag; \
- _tag->dst = 0; \
- prot_tag = _tag;
+ struct tag _tag; \
+ _tag.retval = Qnil; \
+ _tag.frame = the_frame; \
+ _tag.iter = the_iter; \
+ _tag.prev = prot_tag; \
+ _tag.retval = Qnil; \
+ _tag.tag = ptag; \
+ _tag.dst = 0; \
+ prot_tag = &_tag;
#define PROT_NONE 0
#define PROT_FUNC -1
@@ -462,7 +451,7 @@ static struct tag {
}
#define POP_TAG() \
- prot_tag = _tag->prev; \
+ prot_tag = _tag.prev; \
}
#define TAG_RETURN 0x1
@@ -717,6 +706,7 @@ ruby_init()
top_scope = the_scope;
/* default visibility is private at toplevel */
FL_SET(top_scope, SCOPE_PRIVATE);
+ FL_UNSET(top_scope, SCOPE_MODFUNC);
PUSH_TAG(PROT_NONE)
if ((state = EXEC_TAG()) == 0) {
@@ -1113,6 +1103,17 @@ mod_alias_method(mod, new, old)
return mod;
}
+#if defined(C_ALLOCA) && defined(THREAD)
+# define TMP_PROTECT NODE *__protect_tmp=0
+# define ALLOCTMP(type,n) \
+ (__protect_tmp = node_newnode(NODE_ALLOCA, \
+ str_new(0,sizeof(type)*(n)),0,__protect_tmp), \
+ (void*)RSTRING(__protect_tmp->nd_head)->ptr)
+#else
+# define TMP_PROTECT typedef int foobazzz
+# define ALLOCTMP(type,n) ALLOCA_N(type,n)
+#endif
+
#define SETUP_ARGS(anode) {\
NODE *n = anode;\
if (!n) {\
@@ -1126,7 +1127,7 @@ mod_alias_method(mod, new, old)
int line = sourceline;\
int i;\
n = anode;\
- argv = ALLOCA_N(VALUE,argc);\
+ argv = ALLOCTMP(VALUE,argc);\
for (i=0;i<argc;i++) {\
argv[i] = rb_eval(self,n->nd_head);\
n=n->nd_next;\
@@ -1371,7 +1372,7 @@ call_trace_func(event, file, line, self, id)
prev = the_frame;
PUSH_FRAME();
- *the_frame = *_frame->prev;
+ *the_frame = *_frame.prev;
the_frame->prev = prev;
the_frame->line = sourceline = line;
@@ -1606,7 +1607,7 @@ rb_eval(self, node)
else if (the_block->tag->dst == state) {
state &= TAG_MASK;
if (state == TAG_RETURN) {
- result = prot_tag->tag_retval;
+ result = prot_tag->retval;
}
}
POP_TAG();
@@ -1767,6 +1768,7 @@ rb_eval(self, node)
{
VALUE recv;
int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
PUSH_ITER(ITER_NOT);
recv = rb_eval(self, node->nd_recv);
@@ -1779,6 +1781,7 @@ rb_eval(self, node)
case NODE_FCALL:
{
int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
PUSH_ITER(ITER_NOT);
SETUP_ARGS(node->nd_args);
@@ -1795,6 +1798,7 @@ rb_eval(self, node)
case NODE_ZSUPER:
{
int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
if (nd_type(node) == NODE_ZSUPER) {
argc = the_frame->argc;
@@ -1846,6 +1850,7 @@ rb_eval(self, node)
int argc; VALUE *argv; /* used in SETUP_ARGS */
VALUE recv, val;
NODE *rval;
+ TMP_PROTECT;
recv = rb_eval(self, node->nd_recv);
rval = node->nd_args->nd_head;
@@ -2112,13 +2117,19 @@ rb_eval(self, node)
rb_clear_cache_by_id(node->nd_mid);
}
- if (FL_TEST(the_scope,SCOPE_PRIVATE)) {
+ if (FL_TEST(the_scope,SCOPE_PRIVATE) || node->nd_mid == init) {
noex = NOEX_PRIVATE;
}
else {
noex = NOEX_PUBLIC;
}
rb_add_method(the_class, node->nd_mid, node->nd_defn, noex);
+ if (FL_TEST(the_scope,SCOPE_MODFUNC)) {
+ rb_add_method(rb_singleton_class(the_class),
+ node->nd_mid, node->nd_defn, NOEX_PUBLIC);
+ rb_funcall(the_class, rb_intern("singleton_method_added"),
+ 1, INT2FIX(node->nd_mid));
+ }
if (FL_TEST(the_class, FL_SINGLETON)) {
VALUE recv = rb_iv_get(the_class, "__attached__");
rb_funcall(recv, rb_intern("singleton_method_added"),
@@ -2281,9 +2292,9 @@ rb_eval(self, node)
}
if (FL_TEST(CLASS_OF(class), FL_SINGLETON)) {
rb_clear_cache();
- class = rb_singleton_class(class);
}
-
+ class = rb_singleton_class(class);
+
result = module_setup(class, node->nd_body);
}
break;
@@ -2326,6 +2337,7 @@ module_setup(module, node)
VALUE result; /* OK */
char *file = sourcefile;
int line = sourceline;
+ TMP_PROTECT;
/* fill c-ref */
node->nd_clss = module;
@@ -2337,7 +2349,7 @@ module_setup(module, node)
if (node->nd_rval) the_frame->cbase = node->nd_rval;
if (node->nd_tbl) {
- VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1);
+ VALUE *vars = ALLOCTMP(VALUE, node->nd_tbl[0]+1);
*vars++ = (VALUE)node;
the_scope->local_vars = vars;
memclear(the_scope->local_vars, node->nd_tbl[0]);
@@ -2568,7 +2580,7 @@ f_raise(argc, argv)
}
PUSH_FRAME(); /* fake frame */
- *the_frame = *_frame->prev->prev;
+ *the_frame = *_frame.prev->prev;
rb_longjmp(TAG_RAISE, mesg, arg3);
POP_FRAME();
}
@@ -2795,7 +2807,7 @@ rb_iterate(it_proc, data1, bl_proc, data2)
if (the_block->tag->dst == state) {
state &= TAG_MASK;
if (state == TAG_RETURN) {
- retval = prot_tag->tag_retval;
+ retval = prot_tag->retval;
}
}
POP_TAG();
@@ -2828,6 +2840,7 @@ handle_rescue(self, node)
NODE *node;
{
int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
if (!node->nd_args) {
return obj_is_kind_of(errinfo, eException);
@@ -2968,7 +2981,7 @@ f_missing(argc, argv, obj)
sourcefile = file;
sourceline = line;
PUSH_FRAME(); /* fake frame */
- *the_frame = *_frame->prev->prev;
+ *the_frame = *_frame.prev->prev;
NameError(format,
rb_id2name(id),
@@ -3037,6 +3050,7 @@ rb_call(class, recv, mid, argc, argv, scope)
int itr;
enum node_type type;
static int tick;
+ TMP_PROTECT;
again:
/* is it in the method cache? */
@@ -3225,7 +3239,7 @@ rb_call(class, recv, mid, argc, argv, scope)
if (body->nd_rval) the_frame->cbase = body->nd_rval;
if (body->nd_tbl) {
- local_vars = ALLOCA_N(VALUE, body->nd_tbl[0]+1);
+ local_vars = ALLOCTMP(VALUE, body->nd_tbl[0]+1);
*local_vars++ = (VALUE)body;
memclear(local_vars, body->nd_tbl[0]);
the_scope->local_tbl = body->nd_tbl;
@@ -3301,7 +3315,7 @@ rb_call(class, recv, mid, argc, argv, scope)
result = rb_eval(recv, body);
}
else if (state == TAG_RETURN) {
- result = prot_tag->tag_retval;
+ result = prot_tag->retval;
state = 0;
}
POP_VARS();
@@ -3644,8 +3658,8 @@ eval_under(under, self, src)
PUSH_CLASS();
the_class = under;
PUSH_FRAME();
- the_frame->last_func = _frame->last_func;
- the_frame->last_class = _frame->last_class;
+ the_frame->last_func = _frame.last_func;
+ the_frame->last_class = _frame.last_class;
the_frame->argc = 1;
the_frame->argv = &src;
the_frame->cbase = (VALUE)node_newnode(NODE_CREF,under,0,cbase);
@@ -3722,6 +3736,7 @@ f_load(obj, fname)
int state;
char *file;
volatile ID last_func;
+ TMP_PROTECT;
Check_SafeStr(fname);
if (RSTRING(fname)->ptr[0] == '~') {
@@ -3737,7 +3752,7 @@ f_load(obj, fname)
if (top_scope->local_tbl) {
int len = top_scope->local_tbl[0]+1;
ID *tbl = ALLOC_N(ID, len);
- VALUE *vars = ALLOCA_N(VALUE, len);
+ VALUE *vars = ALLOCTMP(VALUE, len);
*vars++ = 0;
MEMCPY(tbl, top_scope->local_tbl, ID, len);
MEMCPY(vars, top_scope->local_vars, ID, len-1);
@@ -3746,6 +3761,7 @@ f_load(obj, fname)
}
/* default visibility is private at loading toplevel */
FL_SET(the_scope, SCOPE_PRIVATE);
+ FL_UNSET(top_scope, SCOPE_MODFUNC);
state = EXEC_TAG();
last_func = the_frame->last_func;
@@ -3938,6 +3954,7 @@ mod_public(argc, argv, module)
{
if (argc == 0) {
FL_UNSET(the_scope, SCOPE_PRIVATE);
+ FL_UNSET(top_scope, SCOPE_MODFUNC);
}
else {
set_method_visibility(module, argc, argv, NOEX_PUBLIC);
@@ -3953,6 +3970,7 @@ mod_private(argc, argv, module)
{
if (argc == 0) {
FL_SET(the_scope, SCOPE_PRIVATE);
+ FL_UNSET(top_scope, SCOPE_MODFUNC);
}
else {
set_method_visibility(module, argc, argv, NOEX_PRIVATE);
@@ -4006,7 +4024,12 @@ mod_modfunc(argc, argv, module)
ID id;
NODE *body;
- rb_clear_cache();
+ if (argc == 0) {
+ FL_SET(the_scope, SCOPE_PRIVATE);
+ FL_SET(the_scope, SCOPE_MODFUNC);
+ return module;
+ }
+
set_method_visibility(module, argc, argv, NOEX_PRIVATE);
for (i=0; i<argc; i++) {
id = rb_to_id(argv[i]);
@@ -4015,6 +4038,7 @@ mod_modfunc(argc, argv, module)
NameError("undefined method `%s' for module `%s'",
rb_id2name(id), rb_class2name(module));
}
+ rb_clear_cache_by_id(id);
rb_add_method(rb_singleton_class(module), id, body->nd_body, NOEX_PUBLIC);
}
return module;
@@ -5721,7 +5745,7 @@ f_catch(dmy, tag)
val = rb_yield(tag);
}
else if (state == TAG_THROW && prot_tag->tag == prot_tag->dst) {
- val = prot_tag->tag_retval;
+ val = prot_tag->retval;
state = 0;
}
POP_TAG();
@@ -5745,7 +5769,7 @@ f_throw(argc, argv)
while (tt) {
if (tt->tag == t) {
tt->dst = t;
- tt->tag_retval = value;
+ tt->retval = value;
break;
}
#ifdef THREAD
@@ -5773,7 +5797,7 @@ return_value(val)
while (tt) {
if (tt->tag == PROT_FUNC) {
- tt->tag_retval = val;
+ tt->retval = val;
break;
}
#ifdef THREAD