diff options
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 164 |
1 files changed, 94 insertions, 70 deletions
@@ -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 |