From 6b6bf4dd481f744faf54b5efcda5f32e4565bd7d Mon Sep 17 00:00:00 2001 From: ko1 Date: Thu, 12 Jul 2007 04:25:46 +0000 Subject: * blockinlining.c: remove "yarv" prefix. * array.c, numeric.c: ditto. * insnhelper.ci, insns.def, vm_evalbody.ci: ditto. * yarvcore.c: removed. * yarvcore.h: renamed to core.h. * cont.c, debug.c, error.c, process.c, signal.c : ditto. * ext/probeprofiler/probeprofiler.c: ditto. * id.c, id.h: added. * inits.c: ditto. * compile.c: rename internal functions. * compile.h: fix debug flag. * eval.c, object.c, vm.c: remove ruby_top_self. use rb_vm_top_self() instead. * eval_intern.h, eval_load: ditto. * gc.c: rename yarv_machine_stack_mark() to rb_gc_mark_machine_stack(). * insnhelper.h: remove unused macros. * iseq.c: add iseq_compile() to create iseq object from source string. * proc.c: rename a internal function. * template/insns.inc.tmpl: remove YARV prefix. * thread.c: * vm.c (rb_iseq_eval): added. * vm.c: move some functions from yarvcore.c. * vm_dump.c: fix to remove compiler warning. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12741 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 49 +++ array.c | 9 - blockinlining.c | 25 +- common.mk | 37 +- compile.c | 97 +++-- compile.h | 10 +- cont.c | 2 +- debug.c | 2 +- error.c | 6 +- eval.c | 29 +- eval_intern.h | 5 +- eval_load.c | 10 +- ext/probeprofiler/probeprofiler.c | 2 +- gc.c | 4 +- id.c | 68 ++++ id.h | 53 +++ inits.c | 4 + insnhelper.ci | 3 +- insnhelper.h | 5 - insns.def | 2 +- iseq.c | 72 ++-- numeric.c | 5 - object.c | 13 - proc.c | 12 +- process.c | 2 +- signal.c | 2 +- template/insns.inc.tmpl | 2 +- thread.c | 20 +- thread_pthread.ci | 2 +- vm.c | 433 +++++++++++++++++++++- vm.h | 20 +- vm_core.h | 689 ++++++++++++++++++++++++++++++++++ vm_dump.c | 36 +- vm_evalbody.ci | 4 +- yarvcore.c | 582 ----------------------------- yarvcore.h | 751 -------------------------------------- 36 files changed, 1468 insertions(+), 1599 deletions(-) create mode 100644 id.c create mode 100644 id.h create mode 100644 vm_core.h delete mode 100644 yarvcore.c delete mode 100644 yarvcore.h diff --git a/ChangeLog b/ChangeLog index f058a7b002..a45a4c1559 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,52 @@ +Thu Jul 12 12:58:21 2007 Koichi Sasada + + * blockinlining.c: remove "yarv" prefix. + + * array.c, numeric.c: ditto. + + * insnhelper.ci, insns.def, vm_evalbody.ci: ditto. + + * yarvcore.c: removed. + + * yarvcore.h: renamed to core.h. + + * cont.c, debug.c, error.c, process.c, signal.c : ditto. + + * ext/probeprofiler/probeprofiler.c: ditto. + + * id.c, id.h: added. + + * inits.c: ditto. + + * compile.c: rename internal functions. + + * compile.h: fix debug flag. + + * eval.c, object.c, vm.c: remove ruby_top_self. + use rb_vm_top_self() instead. + + * eval_intern.h, eval_load: ditto. + + * gc.c: rename yarv_machine_stack_mark() to + rb_gc_mark_machine_stack(). + + * insnhelper.h: remove unused macros. + + * iseq.c: add iseq_compile() to create iseq object + from source string. + + * proc.c: rename a internal function. + + * template/insns.inc.tmpl: remove YARV prefix. + + * thread.c: + + * vm.c (rb_iseq_eval): added. + + * vm.c: move some functions from yarvcore.c. + + * vm_dump.c: fix to remove compiler warning. + Thu Jul 12 12:24:29 2007 Nobuyoshi Nakada * insns.def (opt_succ): fixed typo. [ruby-dev:31189] diff --git a/array.c b/array.c index 6d469cba67..2dcb2b4856 100644 --- a/array.c +++ b/array.c @@ -1136,20 +1136,11 @@ each_i(VALUE ary) * a -- b -- c -- */ -VALUE yarv_invoke_Array_each_special_block(VALUE ary); - VALUE rb_ary_each(VALUE ary) { VALUE val; - RETURN_ENUMERATOR(ary, 0, 0); - - val = yarv_invoke_Array_each_special_block(ary); - if(val != Qundef){ - return val; - } - ITERATE(each_i, ary); return ary; } diff --git a/blockinlining.c b/blockinlining.c index 4f491c1ba1..35a9d6199f 100644 --- a/blockinlining.c +++ b/blockinlining.c @@ -11,13 +11,10 @@ #include "ruby/ruby.h" #include "ruby/node.h" -#include "yarvcore.h" - -VALUE yarv_new_iseqval(VALUE node, VALUE name, VALUE file, - VALUE parent, VALUE type, VALUE block_opt, VALUE opt); +#include "vm_core.h" static VALUE -yarv_iseq_special_block(rb_iseq_t *iseq, void *builder) +iseq_special_block(rb_iseq_t *iseq, void *builder) { #if OPT_BLOCKINLINING VALUE parent = Qfalse; @@ -181,14 +178,14 @@ build_Integer_times_node(rb_iseq_t *iseq, NODE * node, NODE * lnode, } VALUE -yarv_invoke_Integer_times_special_block(VALUE num) +invoke_Integer_times_special_block(VALUE num) { rb_thread_t *th = GET_THREAD(); rb_block_t *orig_block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]); if (orig_block && BUILTIN_TYPE(orig_block->iseq) != T_NODE) { - VALUE tsiseqval = yarv_iseq_special_block(orig_block->iseq, - build_Integer_times_node); + VALUE tsiseqval = iseq_special_block(orig_block->iseq, + build_Integer_times_node); rb_iseq_t *tsiseq; VALUE argv[2], val; @@ -297,8 +294,8 @@ build_Range_each_node_LT(rb_iseq_t *iseq, NODE * node, NODE * lnode, } VALUE -yarv_invoke_Range_each_special_block(VALUE range, - VALUE beg, VALUE end, int excl) +invoke_Range_each_special_block(VALUE range, + VALUE beg, VALUE end, int excl) { rb_thread_t *th = GET_THREAD(); rb_block_t *orig_block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]); @@ -306,7 +303,7 @@ yarv_invoke_Range_each_special_block(VALUE range, if (BUILTIN_TYPE(orig_block->iseq) != T_NODE) { void *builder = excl ? build_Range_each_node_LT : build_Range_each_node_LE; - VALUE tsiseqval = yarv_iseq_special_block(orig_block->iseq, builder); + VALUE tsiseqval = iseq_special_block(orig_block->iseq, builder); rb_iseq_t *tsiseq; VALUE argv[2]; @@ -429,14 +426,14 @@ build_Array_each_node(rb_iseq_t *iseq, NODE * node, NODE * lnode, } VALUE -yarv_invoke_Array_each_special_block(VALUE ary) +invoke_Array_each_special_block(VALUE ary) { rb_thread_t *th = GET_THREAD(); rb_block_t *orig_block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]); if (BUILTIN_TYPE(orig_block->iseq) != T_NODE) { - VALUE tsiseqval = yarv_iseq_special_block(orig_block->iseq, - build_Array_each_node); + VALUE tsiseqval = iseq_special_block(orig_block->iseq, + build_Array_each_node); rb_iseq_t *tsiseq; VALUE argv[2]; diff --git a/common.mk b/common.mk index 1f77bf6c33..de84d52842 100644 --- a/common.mk +++ b/common.mk @@ -73,9 +73,9 @@ OBJS = array.$(OBJEXT) \ iseq.$(OBJEXT) \ vm.$(OBJEXT) \ vm_dump.$(OBJEXT) \ - yarvcore.$(OBJEXT) \ thread.$(OBJEXT) \ cont.$(OBJEXT) \ + id.$(OBJEXT) \ $(MISSING) SCRIPT_ARGS = --dest-dir="$(DESTDIR)" \ @@ -404,13 +404,13 @@ enumerator.$(OBJEXT): {$(VPATH)}enumerator.c {$(VPATH)}ruby.h {$(VPATH)}config.h error.$(OBJEXT): {$(VPATH)}error.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ {$(VPATH)}st.h {$(VPATH)}vm_opts.h {$(VPATH)}signal.h \ - {$(VPATH)}yarvcore.h {$(VPATH)}node.h {$(VPATH)}debug.h \ + {$(VPATH)}vm_core.h {$(VPATH)}id.h {$(VPATH)}node.h {$(VPATH)}debug.h \ {$(VPATH)}thread_$(THREAD_MODEL).h euc_jp.$(OBJEXT): {$(VPATH)}euc_jp.c {$(VPATH)}regenc.h \ {$(VPATH)}oniguruma.h {$(VPATH)}config.h eval.$(OBJEXT): {$(VPATH)}eval.c {$(VPATH)}eval_error.ci {$(VPATH)}eval_intern.h \ {$(VPATH)}eval_method.ci {$(VPATH)}eval_safe.ci {$(VPATH)}eval_jump.ci \ - {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}yarvcore.h \ + {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}vm_core.h {$(VPATH)}id.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ {$(VPATH)}node.h {$(VPATH)}util.h {$(VPATH)}signal.h \ {$(VPATH)}st.h {$(VPATH)}dln.h {$(VPATH)}debug.h \ @@ -418,7 +418,7 @@ eval.$(OBJEXT): {$(VPATH)}eval.c {$(VPATH)}eval_error.ci {$(VPATH)}eval_intern.h eval_load.$(OBJEXT): {$(VPATH)}eval_load.c {$(VPATH)}eval_intern.h \ {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ - {$(VPATH)}node.h {$(VPATH)}util.h {$(VPATH)}yarvcore.h \ + {$(VPATH)}node.h {$(VPATH)}util.h {$(VPATH)}vm_core.h {$(VPATH)}id.h \ {$(VPATH)}signal.h {$(VPATH)}st.h {$(VPATH)}dln.h {$(VPATH)}debug.h \ {$(VPATH)}vm_opts.h {$(VPATH)}thread_$(THREAD_MODEL).h file.$(OBJEXT): {$(VPATH)}file.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ @@ -429,7 +429,7 @@ gc.$(OBJEXT): {$(VPATH)}gc.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ {$(VPATH)}signal.h {$(VPATH)}st.h {$(VPATH)}node.h \ {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}oniguruma.h \ - {$(VPATH)}yarvcore.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h \ + {$(VPATH)}vm_core.h {$(VPATH)}id.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h \ {$(VPATH)}thread_$(THREAD_MODEL).h hash.$(OBJEXT): {$(VPATH)}hash.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ @@ -461,7 +461,7 @@ parse.$(OBJEXT): {$(VPATH)}parse.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ prec.$(OBJEXT): {$(VPATH)}prec.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h proc.$(OBJEXT): {$(VPATH)}proc.c {$(VPATH)}eval_intern.h \ - {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}yarvcore.h \ + {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}vm_core.h {$(VPATH)}id.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ {$(VPATH)}node.h {$(VPATH)}util.h {$(VPATH)}gc.h \ {$(VPATH)}signal.h {$(VPATH)}st.h {$(VPATH)}dln.h \ @@ -469,7 +469,7 @@ proc.$(OBJEXT): {$(VPATH)}proc.c {$(VPATH)}eval_intern.h \ {$(VPATH)}thread_$(THREAD_MODEL).h process.$(OBJEXT): {$(VPATH)}process.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ - {$(VPATH)}signal.h {$(VPATH)}st.h {$(VPATH)}yarvcore.h + {$(VPATH)}signal.h {$(VPATH)}st.h {$(VPATH)}vm_core.h {$(VPATH)}id.h random.$(OBJEXT): {$(VPATH)}random.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h range.$(OBJEXT): {$(VPATH)}range.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ @@ -506,7 +506,7 @@ ruby.$(OBJEXT): {$(VPATH)}ruby.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}dln.h {$(VPATH)}node.h {$(VPATH)}util.h signal.$(OBJEXT): {$(VPATH)}signal.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ - {$(VPATH)}signal.h {$(VPATH)}yarvcore.h {$(VPATH)}node.h \ + {$(VPATH)}signal.h {$(VPATH)}vm_core.h {$(VPATH)}id.h {$(VPATH)}node.h \ {$(VPATH)}debug.h {$(VPATH)}vm_opts.h \ {$(VPATH)}thread_$(THREAD_MODEL).h sjis.$(OBJEXT): {$(VPATH)}sjis.c {$(VPATH)}regenc.h \ @@ -524,12 +524,12 @@ struct.$(OBJEXT): {$(VPATH)}struct.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ thread.$(OBJEXT): {$(VPATH)}thread.c {$(VPATH)}eval_intern.h \ {$(VPATH)}thread_win32.h {$(VPATH)}thread_pthread.h \ {$(VPATH)}thread_win32.ci {$(VPATH)}thread_pthread.ci \ - {$(VPATH)}ruby.h {$(VPATH)}yarvcore.h {$(VPATH)}config.h \ + {$(VPATH)}ruby.h {$(VPATH)}vm_core.h {$(VPATH)}id.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ {$(VPATH)}node.h {$(VPATH)}util.h \ {$(VPATH)}signal.h {$(VPATH)}st.h {$(VPATH)}dln.h cont.$(OBJEXT): {$(VPATH)}cont.c {$(VPATH)}eval_intern.h \ - {$(VPATH)}ruby.h {$(VPATH)}yarvcore.h {$(VPATH)}config.h \ + {$(VPATH)}ruby.h {$(VPATH)}vm_core.h {$(VPATH)}id.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ {$(VPATH)}node.h {$(VPATH)}util.h \ {$(VPATH)}signal.h {$(VPATH)}st.h {$(VPATH)}dln.h @@ -549,19 +549,19 @@ version.$(OBJEXT): {$(VPATH)}version.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ {$(VPATH)}version.h -compile.$(OBJEXT): {$(VPATH)}compile.c {$(VPATH)}yarvcore.h \ +compile.$(OBJEXT): {$(VPATH)}compile.c {$(VPATH)}vm_core.h {$(VPATH)}id.h \ {$(VPATH)}compile.h {$(VPATH)}debug.h {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \ {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}signal.h \ {$(VPATH)}insns_info.inc {$(VPATH)}optinsn.inc \ {$(VPATH)}opt_sc.inc {$(VPATH)}optunifs.inc {$(VPATH)}vm_opts.h \ {$(VPATH)}thread_$(THREAD_MODEL).h -iseq.$(OBJEXT): {$(VPATH)}iseq.c {$(VPATH)}yarvcore.h {$(VPATH)}debug.h \ +iseq.$(OBJEXT): {$(VPATH)}iseq.c {$(VPATH)}vm_core.h {$(VPATH)}id.h {$(VPATH)}debug.h \ {$(VPATH)}ruby.h {$(VPATH)}defines.h {$(VPATH)}missing.h \ {$(VPATH)}intern.h {$(VPATH)}st.h {$(VPATH)}signal.h \ {$(VPATH)}gc.h {$(VPATH)}vm_opts.h {$(VPATH)}config.h {$(VPATH)}node.h \ {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}insns_info.inc -vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}vm.h {$(VPATH)}yarvcore.h \ +vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}vm.h {$(VPATH)}vm_core.h {$(VPATH)}id.h \ {$(VPATH)}debug.h {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}node.h {$(VPATH)}util.h {$(VPATH)}signal.h {$(VPATH)}dln.h \ {$(VPATH)}insnhelper.h {$(VPATH)}insnhelper.ci {$(VPATH)}vm_evalbody.ci \ @@ -569,25 +569,20 @@ vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}vm.h {$(VPATH)}yarvcore.h \ {$(VPATH)}vm_opts.h {$(VPATH)}eval_intern.h \ {$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \ {$(VPATH)}gc.h {$(VPATH)}thread_$(THREAD_MODEL).h -vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c {$(VPATH)}yarvcore.h {$(VPATH)}vm.h \ +vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c {$(VPATH)}vm_core.h {$(VPATH)}id.h {$(VPATH)}vm.h \ {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}defines.h {$(VPATH)}missing.h \ {$(VPATH)}intern.h {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}debug.h \ {$(VPATH)}signal.h {$(VPATH)}vm_opts.h {$(VPATH)}thread_$(THREAD_MODEL).h -yarvcore.$(OBJEXT): {$(VPATH)}yarvcore.c {$(VPATH)}yarvcore.h \ - {$(VPATH)}debug.h {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}defines.h \ - {$(VPATH)}missing.h {$(VPATH)}intern.h {$(VPATH)}st.h \ - {$(VPATH)}signal.h {$(VPATH)}node.h {$(VPATH)}gc.h {$(VPATH)}vm_opts.h \ - {$(VPATH)}thread_$(THREAD_MODEL).h debug.$(OBJEXT): {$(VPATH)}debug.h {$(VPATH)}ruby.h {$(VPATH)}defines.h \ {$(VPATH)}missing.h {$(VPATH)}intern.h {$(VPATH)}st.h {$(VPATH)}config.h \ {$(VPATH)}st.h blockinlining.$(OBJEXT): {$(VPATH)}blockinlining.c \ {$(VPATH)}ruby.h {$(VPATH)}defines.h \ {$(VPATH)}missing.h {$(VPATH)}intern.h {$(VPATH)}st.h {$(VPATH)}config.h \ - {$(VPATH)}node.h {$(VPATH)}yarvcore.h {$(VPATH)}signal.h \ + {$(VPATH)}node.h {$(VPATH)}vm_core.h {$(VPATH)}id.h {$(VPATH)}signal.h \ {$(VPATH)}debug.h {$(VPATH)}vm_opts.h \ {$(VPATH)}thread_$(THREAD_MODEL).h - +id.$(OBJEXT): {$(VPATH)}id.c {$(VPATH)}ruby.h MATZRUBY = $(MATZRUBYDIR)ruby diff --git a/compile.c b/compile.c index a2cef37613..3ef895b950 100644 --- a/compile.c +++ b/compile.c @@ -1,6 +1,6 @@ /********************************************************************** - compile.c - ruby node tree -> yarv instruction sequence + compile.c - ruby node tree -> VM instruction sequence $Author$ $Date$ @@ -13,12 +13,11 @@ #include "ruby/ruby.h" #include "ruby/node.h" -#include "yarvcore.h" +#include "vm_core.h" #include "compile.h" #include "insns.inc" #include "insns_info.inc" - #ifdef HAVE_STDARG_PROTOTYPES #include #define va_init_list(a,b) va_start(a,b) @@ -27,8 +26,12 @@ #define va_init_list(a,b) va_start(a) #endif +/* iseq.c */ VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt); +/* vm.c */ +VALUE vm_eval(void *); + /* types */ #define ISEQ_ELEMENT_NONE INT2FIX(0x00) @@ -77,6 +80,10 @@ struct iseq_compile_data_ensure_node_stack { struct ensure_range *erange; }; +#include "optinsn.inc" +#if OPT_INSTRUCTIONS_UNIFICATION +#include "optunifs.inc" +#endif /* for debug */ #if CPDEBUG > 0 @@ -92,24 +99,22 @@ static int calc_sp_depth(int depth, INSN *iobj); static void ADD_ELEM(LINK_ANCHOR *anchor, LINK_ELEMENT *elem); -static INSN *new_insn_body(rb_iseq_t *iseq, int line_no, - int insn_id, int argc, ...); +static INSN *new_insn_body(rb_iseq_t *iseq, int line_no, int insn_id, int argc, ...); static LABEL *new_label_body(rb_iseq_t *iseq, int line); -static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *anchor, - NODE * n, int); +static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * n, int); static int iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor); - static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *anchor); static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor); -static int set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor); -static int set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor); -static int set_exception_table(rb_iseq_t *iseq); -static int set_local_table(rb_iseq_t *iseq, ID *tbl); -static int set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * node); -static int set_exception_tbl(rb_iseq_t *iseq); -static int set_optargs_table(rb_iseq_t *iseq); +static int iseq_set_local_table(rb_iseq_t *iseq, ID *tbl); +static int iseq_set_exception_local_table(rb_iseq_t *iseq); +static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * node); + +static int iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor); +static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor); +static int iseq_set_exception_table(rb_iseq_t *iseq); +static int iseq_set_optargs_table(rb_iseq_t *iseq); static int iseq_add_mark_object(rb_iseq_t *iseq, VALUE v) @@ -129,15 +134,8 @@ iseq_add_mark_object_compile_time(rb_iseq_t *iseq, VALUE v) return COMPILE_OK; } - -#include "optinsn.inc" - -#if OPT_INSTRUCTIONS_UNIFICATION -#include "optunifs.inc" -#endif - VALUE -rb_iseq_compile(VALUE self, NODE *node) +iseq_compile(VALUE self, NODE *node) { DECL_ANCHOR(ret); rb_iseq_t *iseq; @@ -148,8 +146,8 @@ rb_iseq_compile(VALUE self, NODE *node) } else if (nd_type(node) == NODE_SCOPE) { /* iseq type of top, method, class, block */ - set_local_table(iseq, node->nd_tbl); - set_arguments(iseq, ret, node->nd_args); + iseq_set_local_table(iseq, node->nd_tbl); + iseq_set_arguments(iseq, ret, node->nd_args); switch (iseq->type) { case ISEQ_TYPE_BLOCK: { @@ -195,11 +193,11 @@ rb_iseq_compile(VALUE self, NODE *node) __FILE__, __LINE__); break; case ISEQ_TYPE_RESCUE: - set_exception_tbl(iseq); + iseq_set_exception_local_table(iseq); COMPILE(ret, "rescue", node); break; case ISEQ_TYPE_ENSURE: - set_exception_tbl(iseq); + iseq_set_exception_local_table(iseq); COMPILE_POPED(ret, "ensure", node); break; case ISEQ_TYPE_DEFINED_GUARD: @@ -221,8 +219,6 @@ rb_iseq_compile(VALUE self, NODE *node) return iseq_setup(iseq, ret); } -VALUE vm_eval(void *); - int iseq_translate_threaded_code(rb_iseq_t *iseq) { @@ -678,22 +674,22 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor) } if (iseq->compile_data->option->stack_caching) { - debugs("[compile step 3.3 (set_sequence_stackcaching)]\n"); - set_sequence_stackcaching(iseq, anchor); + debugs("[compile step 3.3 (iseq_set_sequence_stackcaching)]\n"); + iseq_set_sequence_stackcaching(iseq, anchor); if (CPDEBUG > 5) dump_disasm_list(FIRST_ELEMENT(anchor)); } - debugs("[compile step 4.1 (set_sequence)]\n"); - set_sequence(iseq, anchor); + debugs("[compile step 4.1 (iseq_set_sequence)]\n"); + iseq_set_sequence(iseq, anchor); if (CPDEBUG > 5) dump_disasm_list(FIRST_ELEMENT(anchor)); - debugs("[compile step 4.2 (set_exception_table)]\n"); - set_exception_table(iseq); + debugs("[compile step 4.2 (iseq_set_exception_table)]\n"); + iseq_set_exception_table(iseq); debugs("[compile step 4.3 (set_optargs_table)] \n"); - set_optargs_table(iseq); + iseq_set_optargs_table(iseq); debugs("[compile step 5 (iseq_translate_threaded_code)] \n"); iseq_translate_threaded_code(iseq); @@ -708,15 +704,8 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor) return 0; } -VALUE -iseq_assemble_setup(VALUE self, VALUE args, VALUE locals, VALUE insn_ary) -{ - /* unsupported */ - return Qnil; -} - -int -set_exception_tbl(rb_iseq_t *iseq) +static int +iseq_set_exception_local_table(rb_iseq_t *iseq) { static ID id_dollar_bang; @@ -778,9 +767,9 @@ get_dyna_var_idx(rb_iseq_t *iseq, ID id, int *level, int *ls) } static int -set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) +iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) { - debugs("set_arguments: %s\n", node_args ? "" : "0"); + debugs("iseq_set_arguments: %s\n", node_args ? "" : "0"); if (node_args) { NODE *node_aux = node_args->nd_next; @@ -791,7 +780,7 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) NODE *node_init = 0; if (nd_type(node_args) != NODE_ARGS) { - rb_bug("set_arguments: NODE_ARGS is expected, but %s", + rb_bug("iseq_set_arguments: NODE_ARGS is expected, but %s", ruby_node_name(nd_type(node_args))); } @@ -925,7 +914,7 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) } static int -set_local_table(rb_iseq_t *iseq, ID *tbl) +iseq_set_local_table(rb_iseq_t *iseq, ID *tbl) { int size; @@ -950,7 +939,7 @@ set_local_table(rb_iseq_t *iseq, ID *tbl) iseq->local_size += 1 /* svar */; } - debugs("set_local_table: %d, %d\n", iseq->local_size, iseq->local_table_size); + debugs("iseq_set_local_table: %d, %d\n", iseq->local_size, iseq->local_table_size); return COMPILE_OK; } @@ -958,7 +947,7 @@ set_local_table(rb_iseq_t *iseq, ID *tbl) ruby insn object array -> raw instruction sequence */ static int -set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) +iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) { LABEL *lobj; INSN *iobj; @@ -1177,7 +1166,7 @@ label_get_sp(LABEL *lobj) } static int -set_exception_table(rb_iseq_t *iseq) +iseq_set_exception_table(rb_iseq_t *iseq) { VALUE *tptr, *ptr; int tlen, i; @@ -1235,7 +1224,7 @@ set_exception_table(rb_iseq_t *iseq) * expr2 */ static int -set_optargs_table(rb_iseq_t *iseq) +iseq_set_optargs_table(rb_iseq_t *iseq) { int i; @@ -1664,7 +1653,7 @@ label_set_sc_state(LABEL *lobj, int state) #endif static int -set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor) +iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor) { #if OPT_STACK_CACHING LINK_ELEMENT *list; diff --git a/compile.h b/compile.h index e298008e93..e40517e3d4 100644 --- a/compile.h +++ b/compile.h @@ -13,12 +13,6 @@ #ifndef RUBY_COMPILE_H #define RUBY_COMPILE_H - -#if YARVDEBUG > CPDEBUG -#undef CPDEBUG -#define CPDEBUG YARVDEBUG -#endif - /* */ /** * debug function(macro) interface depend on CPDEBUG @@ -32,6 +26,10 @@ * 10: show every AST array */ +#ifndef CPDEBUG +#define CPDEBUG 0 +#endif + #if 0 #undef CPDEBUG #define CPDEBUG 2 diff --git a/cont.c b/cont.c index 914eed4ccc..2924810b53 100644 --- a/cont.c +++ b/cont.c @@ -11,7 +11,7 @@ **********************************************************************/ #include "ruby/ruby.h" -#include "yarvcore.h" +#include "vm_core.h" #include "gc.h" #include "eval_intern.h" diff --git a/debug.c b/debug.c index cd1b80f58c..b5a014e1cb 100644 --- a/debug.c +++ b/debug.c @@ -12,7 +12,7 @@ #include "ruby/ruby.h" #include "debug.h" -#include "yarvcore.h" +#include "vm_core.h" void ruby_debug_print_indent(int level, int debug_level, int indent_level) diff --git a/error.c b/error.c index 4bdc028bd4..f12c89041a 100644 --- a/error.c +++ b/error.c @@ -12,7 +12,7 @@ #include "ruby/ruby.h" #include "ruby/st.h" -#include "yarvcore.h" +#include "vm_core.h" #include #include @@ -197,7 +197,7 @@ rb_warn_m(VALUE self, VALUE mesg) return Qnil; } -void yarv_bug(void); +void rb_vm_bugreport(void); static void report_bug(const char *file, int line, const char *fmt, va_list args) @@ -208,7 +208,7 @@ report_bug(const char *file, int line, const char *fmt, va_list args) if (fwrite(buf, 1, len, out) == len || fwrite(buf, 1, len, (out = stdout)) == len) { - yarv_bug(); + rb_vm_bugreport(); fputs("[BUG] ", out); vfprintf(out, fmt, args); fprintf(out, "\nruby %s (%s) [%s]\n\n", diff --git a/eval.c b/eval.c index 1f0228642c..53b4ab2025 100644 --- a/eval.c +++ b/eval.c @@ -32,8 +32,6 @@ VALUE rb_eSysStackError; VALUE exception_error; VALUE sysstack_error; -extern VALUE ruby_top_self; - static VALUE eval(VALUE, VALUE, VALUE, const char *, int); static inline VALUE rb_yield_0(int argc, VALUE *argv); @@ -63,7 +61,7 @@ void rb_call_inits _((void)); void Init_stack _((VALUE *)); void Init_heap _((void)); void Init_ext _((void)); -void Init_yarv(void); +void Init_BareVM(void); void ruby_init(void) @@ -82,7 +80,7 @@ ruby_init(void) #endif Init_stack((void *)&state); - Init_yarv(); + Init_BareVM(); Init_heap(); PUSH_TAG(); @@ -214,7 +212,7 @@ ruby_cleanup(int ex) } int -ruby_exec_node(void *n) +ruby_exec_node(void *n, char *file) { int state; VALUE val; @@ -226,8 +224,10 @@ ruby_exec_node(void *n) PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { SAVE_ROOT_JMPBUF(th, { + VALUE iseq = rb_iseq_new(n, rb_str_new2("
"), + rb_str_new2(file), Qfalse, ISEQ_TYPE_TOP); th->base_block = 0; - val = yarvcore_eval_parsed(node, rb_str_new2(node->nd_file)); + val = rb_iseq_eval(iseq); }); } POP_TAG(); @@ -243,17 +243,18 @@ ruby_stop(int ex) int ruby_run_node(void *n) { + NODE *node = (NODE *)n; if (!n) { return EXIT_FAILURE; } Init_stack((void *)&n); - return ruby_cleanup(ruby_exec_node(n)); + return ruby_cleanup(ruby_exec_node(node, node->nd_file)); } VALUE rb_eval_string(const char *str) { - return eval(ruby_top_self, rb_str_new2(str), Qnil, "(eval)", 1); + return eval(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1); } VALUE @@ -272,7 +273,7 @@ rb_eval_string_wrap(const char *str, int *state) VALUE val; th->top_wrapper = rb_module_new(); - th->top_self = rb_obj_clone(ruby_top_self); + th->top_self = rb_obj_clone(rb_vm_top_self()); rb_extend_object(th->top_self, th->top_wrapper); val = rb_eval_string_protect(str, &status); @@ -318,7 +319,7 @@ rb_eval_cmd(VALUE cmd, VALUE arg, int level) PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { - val = eval(ruby_top_self, cmd, Qnil, 0, 0); + val = eval(rb_vm_top_self(), cmd, Qnil, 0, 0); } POP_TAG(); @@ -1679,7 +1680,7 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line) /* make eval iseq */ th->parse_in_eval++; - iseqval = vm_compile(th, src, rb_str_new2(file), INT2FIX(line)); + iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line)); th->parse_in_eval--; rb_vm_set_eval_stack(th, iseqval); th->base_block = 0; @@ -2710,9 +2711,9 @@ Init_eval(void) rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0); rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1); - rb_define_singleton_method(ruby_top_self, "include", top_include, -1); - rb_define_singleton_method(ruby_top_self, "public", top_public, -1); - rb_define_singleton_method(ruby_top_self, "private", top_private, -1); + rb_define_singleton_method(rb_vm_top_self(), "include", top_include, -1); + rb_define_singleton_method(rb_vm_top_self(), "public", top_public, -1); + rb_define_singleton_method(rb_vm_top_self(), "private", top_private, -1); rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1); diff --git a/eval_intern.h b/eval_intern.h index 03281863a6..7b89ed3daf 100644 --- a/eval_intern.h +++ b/eval_intern.h @@ -10,7 +10,7 @@ #include "ruby/node.h" #include "ruby/util.h" #include "ruby/signal.h" -#include "yarvcore.h" +#include "vm_core.h" #ifdef HAVE_STDLIB_H #include @@ -195,8 +195,6 @@ NORETURN(void print_undef _((VALUE, ID))); NORETURN(void vm_localjump_error(const char *, VALUE, int)); NORETURN(void vm_jump_tag_but_local_jump(int, VALUE)); -VALUE vm_compile(rb_thread_t *th, VALUE str, VALUE file, VALUE line); - NODE *vm_get_cref(rb_thread_t *th, rb_iseq_t *iseq, rb_control_frame_t *cfp); NODE *vm_cref_push(rb_thread_t *th, VALUE, int); NODE *vm_set_special_cref(rb_thread_t *th, VALUE *lfp, NODE * cref_stack); @@ -228,6 +226,7 @@ void rb_vm_check_redefinition_opt_method(NODE *node); VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, rb_block_t *blockptr, VALUE filename); void rb_thread_terminate_all(void); void rb_vm_set_eval_stack(rb_thread_t *, VALUE iseq); +VALUE rb_vm_top_self(); #define ruby_cbase() vm_get_cbase(GET_THREAD()) diff --git a/eval_load.c b/eval_load.c index 3974513b16..d0cd5e2d41 100644 --- a/eval_load.c +++ b/eval_load.c @@ -4,8 +4,6 @@ #include "eval_intern.h" -extern VALUE ruby_top_self; - VALUE ruby_dln_librefs; #define IS_SOEXT(e) (strcmp(e, ".so") == 0 || strcmp(e, ".o") == 0) @@ -157,7 +155,7 @@ rb_load(VALUE fname, int wrap) } else { /* load in anonymous module as toplevel */ - th->top_self = rb_obj_clone(ruby_top_self); + th->top_self = rb_obj_clone(rb_vm_top_self()); th->top_wrapper = rb_module_new(); rb_extend_object(th->top_self, th->top_wrapper); } @@ -175,7 +173,7 @@ rb_load(VALUE fname, int wrap) loaded = Qtrue; iseq = rb_iseq_new(node, rb_str_new2(""), fname, Qfalse, ISEQ_TYPE_TOP); - rb_thread_eval(th, iseq); + rb_iseq_eval(iseq); } POP_TAG(); @@ -435,7 +433,7 @@ rb_require_safe(VALUE fname, int safe) break; case 's': - handle = (long)rb_vm_call_cfunc(ruby_top_self, load_ext, + handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext, path, 0, path); rb_ary_push(ruby_dln_librefs, LONG2NUM(handle)); break; @@ -482,7 +480,7 @@ void ruby_init_ext(const char *name, void (*init)(void)) { if (load_lock(name)) { - rb_vm_call_cfunc(ruby_top_self, init_ext_call, (VALUE)init, + rb_vm_call_cfunc(rb_vm_top_self(), init_ext_call, (VALUE)init, 0, rb_str_new2(name)); rb_provide(name); load_unlock(name); diff --git a/ext/probeprofiler/probeprofiler.c b/ext/probeprofiler/probeprofiler.c index cff793039e..473844c0a1 100644 --- a/ext/probeprofiler/probeprofiler.c +++ b/ext/probeprofiler/probeprofiler.c @@ -1,5 +1,5 @@ #include -#include +#include VALUE rb_thread_current_status(rb_thread_t *); void rb_add_event_hook(rb_event_hook_func_t, rb_event_flag_t, VALUE); diff --git a/gc.c b/gc.c index d596d10735..b4240c0229 100644 --- a/gc.c +++ b/gc.c @@ -17,7 +17,7 @@ #include "ruby/st.h" #include "ruby/node.h" #include "ruby/re.h" -#include "yarvcore.h" +#include "vm_core.h" #include "gc.h" #include #include @@ -1455,7 +1455,7 @@ garbage_collect(void) } void -yarv_machine_stack_mark(rb_thread_t *th) +rb_gc_mark_machine_stack(rb_thread_t *th) { #if STACK_GROW_DIRECTION < 0 rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start); diff --git a/id.c b/id.c new file mode 100644 index 0000000000..46853905fa --- /dev/null +++ b/id.c @@ -0,0 +1,68 @@ +/********************************************************************** + + id.c - + + $Author$ + $Date$ + created at: Thu Jul 12 04:37:51 2007 + + Copyright (C) 2004-2006 Koichi Sasada + +**********************************************************************/ + +#include "ruby/ruby.h" + +#define extern +#include "id.h" +#undef extern + +void +Init_id(void) +{ + /* Symbols */ + symIFUNC = ID2SYM(rb_intern("")); + symCFUNC = ID2SYM(rb_intern("")); + + /* IDs */ + idPLUS = rb_intern("+"); + idMINUS = rb_intern("-"); + idMULT = rb_intern("*"); + idDIV = rb_intern("/"); + idMOD = rb_intern("%"); + idLT = rb_intern("<"); + idLTLT = rb_intern("<<"); + idLE = rb_intern("<="); + idGT = rb_intern(">"); + idGE = rb_intern(">="); + idEq = rb_intern("=="); + idEqq = rb_intern("==="); + idBackquote = rb_intern("`"); + idEqTilde = rb_intern("=~"); + + idAREF = rb_intern("[]"); + idASET = rb_intern("[]="); + + idEach = rb_intern("each"); + idTimes = rb_intern("times"); + idLength = rb_intern("length"); + idLambda = rb_intern("lambda"); + idIntern = rb_intern("intern"); + idGets = rb_intern("gets"); + idSucc = rb_intern("succ"); + idEnd = rb_intern("end"); + idRangeEachLT = rb_intern("Range#each#LT"); + idRangeEachLE = rb_intern("Range#each#LE"); + idArrayEach = rb_intern("Array#each"); + idMethodMissing = rb_intern("method_missing"); + + idThrowState = rb_intern("#__ThrowState__"); + + idBitblt = rb_intern("bitblt"); + idAnswer = rb_intern("the_answer_to_life_the_universe_and_everything"); + + idSend = rb_intern("send"); + id__send__ = rb_intern("__send__"); + id__send = rb_intern("__send"); + idFuncall = rb_intern("funcall"); + id__send_bang = rb_intern("__send!"); +} diff --git a/id.h b/id.h new file mode 100644 index 0000000000..32f4e27d45 --- /dev/null +++ b/id.h @@ -0,0 +1,53 @@ +/********************************************************************** + + id.h - + + $Author: ko1 $ + $Date: $ + created at: Thu Jul 12 04:38:07 2007 + + Copyright (C) 2007 Koichi Sasada + +**********************************************************************/ + +extern VALUE symIFUNC; +extern VALUE symCFUNC; + +extern ID idPLUS; +extern ID idMINUS; +extern ID idMULT; +extern ID idDIV; +extern ID idMOD; +extern ID idLT; +extern ID idLTLT; +extern ID idLE; +extern ID idGT; +extern ID idGE; +extern ID idEq; +extern ID idEqq; +extern ID idBackquote; +extern ID idEqTilde; +extern ID idThrowState; +extern ID idAREF; +extern ID idASET; +extern ID idIntern; +extern ID idMethodMissing; +extern ID idLength; +extern ID idGets; +extern ID idSucc; +extern ID idEach; +extern ID idLambda; +extern ID idRangeEachLT; +extern ID idRangeEachLE; +extern ID idArrayEach; +extern ID idTimes; +extern ID idEnd; +extern ID idBitblt; +extern ID idAnswer; +extern ID idSend; +extern ID id__send__; +extern ID id__send; +extern ID idFuncall; +extern ID id__send_bang; + + diff --git a/inits.c b/inits.c index 3ace504244..302f1c65c9 100644 --- a/inits.c +++ b/inits.c @@ -35,6 +35,7 @@ void Init_Object(void); void Init_pack(void); void Init_Precision(void); void Init_sym(void); +void Init_id(void); void Init_process(void); void Init_Random(void); void Init_Range(void); @@ -49,13 +50,16 @@ void Init_ISeq(void); void Init_VM(void); void Init_Thread(void); void Init_Cont(void); +void Init_top_self(void); void rb_call_inits() { Init_sym(); + Init_id(); Init_var_tables(); Init_Object(); + Init_top_self(); Init_Comparable(); Init_Enumerable(); Init_Precision(); diff --git a/insnhelper.ci b/insnhelper.ci index c3c44cba28..e77a1449d3 100644 --- a/insnhelper.ci +++ b/insnhelper.ci @@ -11,7 +11,6 @@ **********************************************************************/ /* finish iseq array */ - #include "insns.inc" /* control stack frame */ @@ -1005,7 +1004,7 @@ vm_search_super_klass(VALUE klass, VALUE recv) } static void -call_yarv_end_proc(VALUE data) +call_end_proc(VALUE data) { rb_proc_call(data, rb_ary_new2(0)); } diff --git a/insnhelper.h b/insnhelper.h index 8ae9599423..f8439f7725 100644 --- a/insnhelper.h +++ b/insnhelper.h @@ -69,9 +69,6 @@ #define GET_DFP() (USAGE_ANALYSIS_REGISTER_HELPER(4, 0, REG_DFP)) #define SET_DFP(x) (REG_DFP = (USAGE_ANALYSIS_REGISTER_HELPER(4, 1, (x)))) -#define GET_CONTINUATION_FRAME_PTR(cfp) \ - ((struct continuation_frame *)((cfp) + CC_DIFF_WC())) - /* SP */ #define GET_SP() (USAGE_ANALYSIS_REGISTER_HELPER(1, 0, REG_SP)) #define SET_SP(x) (REG_SP = (USAGE_ANALYSIS_REGISTER_HELPER(1, 1, (x)))) @@ -84,13 +81,11 @@ /* instruction sequence C struct */ #define GET_ISEQ() (GET_CFP()->iseq) -#define CLEAR_ENV(env) (GET_ENV_CTRL(env)->is_orphan = Qundef) /**********************************************************/ /* deal with variables */ /**********************************************************/ -#define GET_CURRENT_DYNAMIC(idx) (*(GET_DFP() -(idx))) #define GET_PREV_DFP(dfp) ((VALUE *)((dfp)[0] & ~0x03)) #define GET_GLOBAL(entry) rb_gvar_get((struct global_entry*)entry) diff --git a/insns.def b/insns.def index 9116430f28..5e0f49b750 100644 --- a/insns.def +++ b/insns.def @@ -979,7 +979,7 @@ postexe blockptr->proc = 0; proc = vm_make_proc(th, GET_CFP(), blockptr); - rb_set_end_proc(call_yarv_end_proc, proc); + rb_set_end_proc(call_end_proc, proc); } /** diff --git a/iseq.c b/iseq.c index 55ff9952b3..c50a6d443d 100644 --- a/iseq.c +++ b/iseq.c @@ -13,12 +13,16 @@ #include "ruby/ruby.h" #include "ruby/node.h" -#include "yarvcore.h" +/* #define MARK_FREE_DEBUG 1 */ +#include "gc.h" +#include "vm_core.h" + #include "insns.inc" #include "insns_info.inc" -/* #define MARK_FREE_DEBUG 1 */ -#include "gc.h" +/* compile.c */ +void iseq_compile(VALUE self, NODE *node); +int iseq_translate_threaded_code(rb_iseq_t *iseq); VALUE rb_cISeq; @@ -289,7 +293,7 @@ rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename, iseq->self = self; prepare_iseq_build(iseq, name, filename, parent, type, bopt, option); - rb_iseq_compile(self, node); + iseq_compile(self, node); cleanup_iseq_build(iseq); return self; } @@ -418,22 +422,41 @@ compile_string(VALUE str, VALUE file, VALUE line) return node; } -static VALUE -iseq_s_compile(int argc, VALUE *argv, VALUE self) +VALUE +rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE line, VALUE opt) { - VALUE str, file = Qnil, line = INT2FIX(1), opt = Qnil; - NODE *node; rb_compile_option_t option; + NODE *node = compile_string(src, file, line); + rb_thread_t *th = GET_THREAD(); + make_compile_option(&option, opt); + + if (th->base_block) { + return rb_iseq_new_with_opt(node, th->base_block->iseq->name, + file, th->base_block->iseq->self, + ISEQ_TYPE_EVAL, &option); + } + else { + return rb_iseq_new_with_opt(node, rb_str_new2(""), file, Qfalse, + ISEQ_TYPE_TOP, &option); + } +} + +VALUE +rb_iseq_compile(VALUE src, VALUE file, VALUE line) +{ + return rb_iseq_compile_with_option(src, file, line, Qnil); +} - rb_scan_args(argc, argv, "13", &str, &file, &line, &opt); +static VALUE +iseq_s_compile(int argc, VALUE *argv, VALUE self) +{ + VALUE src, file = Qnil, line = INT2FIX(1), opt = Qnil; + rb_scan_args(argc, argv, "13", &src, &file, &line, &opt); file = file == Qnil ? rb_str_new2("") : file; line = line == Qnil ? INT2FIX(1) : line; - node = compile_string(str, file, line); - make_compile_option(&option, opt); - return rb_iseq_new_with_opt(node, rb_str_new2("
"), file, Qfalse, - ISEQ_TYPE_TOP, &option); + return rb_iseq_compile_with_option(src, file, line, opt); } static VALUE @@ -481,7 +504,7 @@ iseq_check(VALUE val) static VALUE iseq_eval(VALUE self) { - return rb_thread_eval(GET_THREAD(), self); + return rb_iseq_eval(self); } static VALUE @@ -1066,15 +1089,6 @@ end } } -int -debug_node(NODE *node) -{ - printf("node type: %d\n", nd_type(node)); - printf("node name: %s\n", ruby_node_name(nd_type(node))); - printf("node filename: %s\n", node->nd_file); - return 0; -} - #define DECL_SYMBOL(name) \ static VALUE sym_##name @@ -1121,7 +1135,7 @@ cdhash_each(VALUE key, VALUE value, VALUE ary) VALUE iseq_data_to_ary(rb_iseq_t *iseq) { - int i, pos, line = 0, insn_pos = 0; + int i, pos, line = 0; VALUE *seq; VALUE val = rb_ary_new(); @@ -1133,7 +1147,7 @@ iseq_data_to_ary(rb_iseq_t *iseq) VALUE exception = rb_ary_new(); /* [[....]] */ VALUE misc = rb_hash_new(); - static VALUE insn_syms[YARV_MAX_INSTRUCTION_SIZE]; + static VALUE insn_syms[VM_INSTRUCTION_SIZE]; struct st_table *labels_table = st_init_numtable(); DECL_SYMBOL(top); @@ -1146,7 +1160,7 @@ iseq_data_to_ary(rb_iseq_t *iseq) if (sym_top == 0) { int i; - for (i=0; i #include diff --git a/signal.c b/signal.c index 44c2d2df7d..772e5ec890 100644 --- a/signal.c +++ b/signal.c @@ -15,7 +15,7 @@ #include "ruby/ruby.h" #include "ruby/signal.h" #include "ruby/node.h" -#include "yarvcore.h" +#include "vm_core.h" #include #include diff --git a/template/insns.inc.tmpl b/template/insns.inc.tmpl index 05af3e81f3..770210e752 100644 --- a/template/insns.inc.tmpl +++ b/template/insns.inc.tmpl @@ -17,5 +17,5 @@ enum{ <%= insns %> }; -#define YARV_MAX_INSTRUCTION_SIZE <%= @insns.size %> +#define VM_INSTRUCTION_SIZE <%= @insns.size %> diff --git a/thread.c b/thread.c index bf17dc81dc..c38130ffff 100644 --- a/thread.c +++ b/thread.c @@ -389,7 +389,7 @@ thread_join(rb_thread_t *target_th, double delay) rb_thread_t *th = GET_THREAD(); double now, limit = timeofday() + delay; - thread_debug("thread_join (thid: %p)\n", (void*)target_th->thread_id); + thread_debug("thread_join (thid: %p)\n", (void *)target_th->thread_id); if (target_th->status != THREAD_KILLED) { th->join_list_next = target_th->join_list_head; @@ -404,17 +404,17 @@ thread_join(rb_thread_t *target_th, double delay) now = timeofday(); if (now > limit) { thread_debug("thread_join: timeout (thid: %p)\n", - (void*)target_th->thread_id); + (void *)target_th->thread_id); return Qnil; } sleep_wait_for_interrupt(th, limit - now); } thread_debug("thread_join: interrupted (thid: %p)\n", - (void*)target_th->thread_id); + (void *)target_th->thread_id); } thread_debug("thread_join: success (thid: %p)\n", - (void*)target_th->thread_id); + (void *)target_th->thread_id); if (target_th->errinfo != Qnil) { VALUE err = target_th->errinfo; @@ -2349,7 +2349,7 @@ thlist_signal(rb_thread_list_t **list, unsigned int maxth) int woken = 0; rb_thread_list_t *q; - while ((q = *list) != 0) { + while ((q = *list) != NULL) { rb_thread_t *th = q->th; *list = q->next; @@ -2922,10 +2922,12 @@ Init_Thread(void) rb_define_method(rb_cMutex, "lock", rb_mutex_lock, 0); rb_define_method(rb_cMutex, "unlock", rb_mutex_unlock, 0); rb_define_method(rb_cMutex, "sleep", mutex_sleep, -1); - yarvcore_eval(Qnil, rb_str_new2( - "class Mutex;" - " def synchronize; self.lock; yield; ensure; self.unlock; end;" - "end;"), rb_str_new2(""), INT2FIX(1)); + + rb_iseq_eval(rb_iseq_compile( + rb_str_new2("class Mutex;" + " def synchronize; self.lock; yield; ensure; self.unlock; end;" + "end;"), + rb_str_new2(__FILE__), INT2FIX(__LINE__))); recursive_key = rb_intern("__recursive_key__"); rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError); diff --git a/thread_pthread.ci b/thread_pthread.ci index cd5e05bde1..d624e98487 100644 --- a/thread_pthread.ci +++ b/thread_pthread.ci @@ -301,7 +301,7 @@ ubf_pthread_cond_signal(rb_thread_t *th) static void ubf_select_each(rb_thread_t *th) { - thread_debug("ubf_select_each (%p)\n", (void*)th->thread_id); + thread_debug("ubf_select_each (%p)\n", (void *)th->thread_id); if (th) { pthread_kill(th->thread_id, SIGVTALRM); } diff --git a/vm.c b/vm.c index 0aae865770..80e470f5ad 100644 --- a/vm.c +++ b/vm.c @@ -21,29 +21,26 @@ #define BUFSIZE 0x100 #define PROCDEBUG 0 +VALUE rb_cVM; +VALUE rb_cThread; VALUE rb_cEnv; + VALUE ruby_vm_global_state_version = 1; +rb_thread_t *ruby_current_thread = 0; +rb_vm_t *ruby_current_vm = 0; void vm_analysis_operand(int insn, int n, VALUE op); void vm_analysis_register(int reg, int isset); void vm_analysis_insn(int insn); -VALUE vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, - VALUE self, int argc, VALUE *argv); - -VALUE vm_eval_body(rb_thread_t *th); - -static NODE *lfp_get_special_cref(VALUE *lfp); static NODE *lfp_set_special_cref(VALUE *lfp, NODE * cref); -static inline int block_proc_is_lambda(VALUE procval); - #if OPT_STACK_CACHING -static VALUE yarv_finish_insn_seq[1] = { BIN(finish_SC_ax_ax) }; +static VALUE finish_insn_seq[1] = { BIN(finish_SC_ax_ax) }; #elif OPT_CALL_THREADED_CODE -static VALUE const yarv_finish_insn_seq[1] = { 0 }; +static VALUE const finish_insn_seq[1] = { 0 }; #else -static VALUE yarv_finish_insn_seq[1] = { BIN(finish) }; +static VALUE finish_insn_seq[1] = { BIN(finish) }; #endif void @@ -60,7 +57,7 @@ rb_vm_set_finish_env(rb_thread_t *th) vm_push_frame(th, 0, FRAME_MAGIC_FINISH, Qnil, th->cfp->lfp[0], 0, th->cfp->sp, 0, 1); - th->cfp->pc = (VALUE *)&yarv_finish_insn_seq[0]; + th->cfp->pc = (VALUE *)&finish_insn_seq[0]; return Qtrue; } @@ -379,7 +376,7 @@ vm_make_proc(rb_thread_t *th, if (PROCDEBUG) { check_env_value(envval); } - procval = rb_proc_alloc(); + procval = rb_proc_alloc(rb_cProc); GetProcPtr(procval, proc); proc->blockprocval = blockprocval; proc->block.self = block->self; @@ -1009,8 +1006,8 @@ add_opt_method(VALUE klass, ID mid, VALUE bop) } } -void -yarv_init_redefined_flag(void) +static void +vm_init_redefined_flag(void) { const VALUE register_info[] = { idPLUS, BOP_PLUS, rb_cFixnum, rb_cFloat, rb_cString, rb_cArray, 0, @@ -1202,7 +1199,7 @@ vm_eval_body(rb_thread_t *th) if (cfp->dfp == escape_dfp) { if (state == TAG_RETURN) { - if ((cfp + 1)->pc != &yarv_finish_insn_seq[0]) { + if ((cfp + 1)->pc != &finish_insn_seq[0]) { SET_THROWOBJ_CATCH_POINT(err, (VALUE)(cfp + 1)->dfp); SET_THROWOBJ_STATE(err, state = TAG_BREAK); } @@ -1344,7 +1341,7 @@ vm_eval_body(rb_thread_t *th) } else { th->cfp++; - if (th->cfp->pc != &yarv_finish_insn_seq[0]) { + if (th->cfp->pc != &finish_insn_seq[0]) { goto exception_handler; } else { @@ -1363,8 +1360,9 @@ vm_eval_body(rb_thread_t *th) /* misc */ VALUE -rb_thread_eval(rb_thread_t *th, VALUE iseqval) +rb_iseq_eval(VALUE iseqval) { + rb_thread_t *th = GET_THREAD(); VALUE val; volatile VALUE tmp; @@ -1439,3 +1437,402 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, rb_block_t *blockp vm_pop_frame(th); return val; } + +/* vm */ + +static void +vm_free(void *ptr) +{ + RUBY_FREE_ENTER("vm"); + if (ptr) { + rb_vm_t *vmobj = ptr; + + st_free_table(vmobj->living_threads); + /* TODO: MultiVM Instance */ + /* VM object should not be cleaned by GC */ + /* ruby_xfree(ptr); */ + /* ruby_current_vm = 0; */ + } + RUBY_FREE_LEAVE("vm"); +} + +static int +vm_mark_each_thread_func(st_data_t key, st_data_t value, st_data_t dummy) +{ + VALUE thval = (VALUE)key; + rb_gc_mark(thval); + return ST_CONTINUE; +} + +static void +mark_event_hooks(rb_event_hook_t *hook) +{ + while (hook) { + rb_gc_mark(hook->data); + hook = hook->next; + } +} + +void +rb_vm_mark(void *ptr) +{ + RUBY_MARK_ENTER("vm"); + RUBY_GC_INFO("-------------------------------------------------\n"); + if (ptr) { + rb_vm_t *vm = ptr; + if (vm->living_threads) { + st_foreach(vm->living_threads, vm_mark_each_thread_func, 0); + } + RUBY_MARK_UNLESS_NULL(vm->thgroup_default); + RUBY_MARK_UNLESS_NULL(vm->mark_object_ary); + RUBY_MARK_UNLESS_NULL(vm->last_status); + RUBY_MARK_UNLESS_NULL(vm->loaded_features); + RUBY_MARK_UNLESS_NULL(vm->top_self); + + if (vm->loading_table) { + rb_mark_tbl(vm->loading_table); + } + + mark_event_hooks(vm->event_hooks); + } + + RUBY_MARK_LEAVE("vm"); +} + +static void +vm_init2(rb_vm_t *vm) +{ + MEMZERO(vm, rb_vm_t, 1); +} + +/* Thread */ + +static void +thread_free(void *ptr) +{ + rb_thread_t *th; + RUBY_FREE_ENTER("thread"); + + if (ptr) { + th = ptr; + + if (!th->root_fiber) { + RUBY_FREE_UNLESS_NULL(th->stack); + } + + if (th->local_storage) { + st_free_table(th->local_storage); + } + +#if USE_VALUE_CACHE + { + VALUE *ptr = th->value_cache_ptr; + while (*ptr) { + VALUE v = *ptr; + RBASIC(v)->flags = 0; + RBASIC(v)->klass = 0; + ptr++; + } + } +#endif + + if (th->vm->main_thread == th) { + RUBY_GC_INFO("main thread\n"); + } + else { + ruby_xfree(ptr); + } + } + RUBY_FREE_LEAVE("thread"); +} + +void rb_gc_mark_machine_stack(rb_thread_t *th); + +void +rb_thread_mark(void *ptr) +{ + rb_thread_t *th = NULL; + RUBY_MARK_ENTER("thread"); + if (ptr) { + th = ptr; + if (th->stack) { + VALUE *p = th->stack; + VALUE *sp = th->cfp->sp + th->mark_stack_len; + rb_control_frame_t *cfp = th->cfp; + rb_control_frame_t *limit_cfp = + (void *)(th->stack + th->stack_size); + + while (p < sp) { + rb_gc_mark(*p++); + } + while (cfp != limit_cfp) { + rb_gc_mark(cfp->proc); + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); + } + } + + /* mark ruby objects */ + RUBY_MARK_UNLESS_NULL(th->first_proc); + RUBY_MARK_UNLESS_NULL(th->first_args); + + RUBY_MARK_UNLESS_NULL(th->thgroup); + RUBY_MARK_UNLESS_NULL(th->value); + RUBY_MARK_UNLESS_NULL(th->errinfo); + RUBY_MARK_UNLESS_NULL(th->thrown_errinfo); + RUBY_MARK_UNLESS_NULL(th->local_svar); + RUBY_MARK_UNLESS_NULL(th->top_self); + RUBY_MARK_UNLESS_NULL(th->top_wrapper); + RUBY_MARK_UNLESS_NULL(th->fiber); + RUBY_MARK_UNLESS_NULL(th->root_fiber); + + rb_mark_tbl(th->local_storage); + + if (GET_THREAD() != th && th->machine_stack_start && th->machine_stack_end) { + rb_gc_mark_machine_stack(th); + rb_gc_mark_locations((VALUE *)&th->machine_regs, + (VALUE *)(&th->machine_regs) + + sizeof(th->machine_regs) / sizeof(VALUE)); + } + + mark_event_hooks(th->event_hooks); + } + + RUBY_MARK_UNLESS_NULL(th->stat_insn_usage); + RUBY_MARK_LEAVE("thread"); +} + +static VALUE +thread_alloc(VALUE klass) +{ + VALUE volatile obj; + rb_thread_t *th; + obj = Data_Make_Struct(klass, rb_thread_t, + rb_thread_mark, thread_free, th); + return obj; +} + +static void +th_init2(rb_thread_t *th) +{ + MEMZERO(th, rb_thread_t, 1); + + /* allocate thread stack */ + th->stack_size = RUBY_VM_THREAD_STACK_SIZE; + th->stack = ALLOC_N(VALUE, th->stack_size); + + th->cfp = (void *)(th->stack + th->stack_size); + th->cfp--; + + th->cfp->pc = 0; + th->cfp->sp = th->stack + 1; + th->cfp->bp = 0; + th->cfp->lfp = th->stack; + *th->cfp->lfp = 0; + th->cfp->dfp = th->stack; + th->cfp->self = Qnil; + th->cfp->flag = 0; + th->cfp->iseq = 0; + th->cfp->proc = 0; + th->cfp->block_iseq = 0; + + th->status = THREAD_RUNNABLE; + th->errinfo = Qnil; + +#if USE_VALUE_CACHE + th->value_cache_ptr = &th->value_cache[0]; +#endif +} + +static void +th_init(rb_thread_t *th) +{ + th_init2(th); +} + +static VALUE +ruby_thread_init(VALUE self) +{ + rb_thread_t *th; + rb_vm_t *vm = GET_THREAD()->vm; + GetThreadPtr(self, th); + + th_init(th); + th->self = self; + th->vm = vm; + + th->top_wrapper = 0; + th->top_self = rb_vm_top_self(); + return self; +} + +VALUE +rb_thread_alloc(VALUE klass) +{ + VALUE self = thread_alloc(klass); + ruby_thread_init(self); + return self; +} + +VALUE insns_name_array(void); +extern VALUE *rb_gc_stack_start; +#ifdef __ia64 +extern VALUE *rb_gc_register_stack_start; +#endif + +static VALUE +sdr(void) +{ + rb_vm_bugreport(); + return Qnil; +} + +static VALUE +nsdr(void) +{ + VALUE ary = rb_ary_new(); +#if HAVE_BACKTRACE +#include +#define MAX_NATIVE_TRACE 1024 + static void *trace[MAX_NATIVE_TRACE]; + int n = backtrace(trace, MAX_NATIVE_TRACE); + char **syms = backtrace_symbols(trace, n); + int i; + + if (syms == 0) { + rb_memerror(); + } + + for (i=0; iself = Data_Wrap_Struct(rb_cVM, rb_vm_mark, vm_free, vm); + + /* create main thread */ + th_self = th->self = Data_Wrap_Struct(rb_cThread, rb_thread_mark, + thread_free, th); + + vm->main_thread = th; + vm->running_thread = th; + th->vm = vm; + th->top_wrapper = 0; + th->top_self = rb_vm_top_self(); + rb_thread_set_current(th); + + vm->living_threads = st_init_numtable(); + st_insert(vm->living_threads, th_self, (st_data_t) th->thread_id); + } + vm_init_redefined_flag(); +} + +void +Init_BareVM(void) +{ + /* VM bootstrap: phase 1 */ + rb_vm_t *vm = ALLOC(rb_vm_t); + rb_thread_t *th = ALLOC(rb_thread_t); + + vm_init2(vm); + ruby_current_vm = vm; + + th_init2(th); + th->vm = vm; + th->machine_stack_start = rb_gc_stack_start; +#ifdef __ia64 + th->machine_register_stack_start = rb_gc_register_stack_start; +#endif + rb_thread_set_current_raw(th); +} + +/* top self */ + +static VALUE +main_to_s(VALUE obj) +{ + return rb_str_new2("main"); +} + +VALUE +rb_vm_top_self() +{ + return GET_VM()->top_self; +} + +void +Init_top_self() +{ + rb_vm_t *vm = GET_VM(); + + vm->top_self = rb_obj_alloc(rb_cObject); + rb_define_singleton_method(rb_vm_top_self(), "to_s", main_to_s, 0); +} diff --git a/vm.h b/vm.h index de8365b411..c496e59df3 100644 --- a/vm.h +++ b/vm.h @@ -10,13 +10,8 @@ **********************************************************************/ -#ifndef _VM_H_INCLUDED_ -#define _VM_H_INCLUDED_ - -#if YARVDEBUG > VMDEBUG -#undef VMDEBUG -#define VMDEBUG YARVDEBUG -#endif +#ifndef RUBY_VM_H +#define RUBY_VM_H typedef long OFFSET; typedef unsigned long rb_num_t; @@ -42,6 +37,11 @@ extern VALUE ruby_vm_redefined_flag; * 10: gc check */ + +#ifndef VMDEBUG +#define VMDEBUG 0 +#endif + #if 0 #undef VMDEBUG #define VMDEBUG 3 @@ -52,9 +52,9 @@ extern VALUE ruby_vm_redefined_flag; #define USAGE_ANALYSIS_OPERAND(insn, n, op) vm_analysis_operand(insn, n, (VALUE)op) #define USAGE_ANALYSIS_REGISTER(reg, s) vm_analysis_register(reg, s) #else -#define USAGE_ANALYSIS_INSN(insn) /* none */ +#define USAGE_ANALYSIS_INSN(insn) /* none */ #define USAGE_ANALYSIS_OPERAND(insn, n, op) /* none */ -#define USAGE_ANALYSIS_REGISTER(reg, s) /* none */ +#define USAGE_ANALYSIS_REGISTER(reg, s) /* none */ #endif #ifdef __GCC__ @@ -298,4 +298,4 @@ while (0) #define BOP_GT 0x2000 #define BOP_GE 0x4000 -#endif /* _VM_H_INCLUDED_ */ +#endif /* RUBY_VM_H */ diff --git a/vm_core.h b/vm_core.h new file mode 100644 index 0000000000..568b7b390e --- /dev/null +++ b/vm_core.h @@ -0,0 +1,689 @@ +/********************************************************************** + + vm_core.h - + + $Author$ + $Date$ + created at: 04/01/01 19:41:38 JST + + Copyright (C) 2004-2007 Koichi Sasada + +**********************************************************************/ + +#ifndef RUBY_CORE_H +#define RUBY_CORE_H + +#define RUBY_VM_THREAD_MODEL 2 + +#include + +#include "ruby/ruby.h" +#include "ruby/signal.h" +#include "ruby/st.h" +#include "ruby/node.h" + +#include "debug.h" +#include "vm_opts.h" +#include "id.h" + +#if defined(_WIN32) +#include "thread_win32.h" +#elif defined(HAVE_PTHREAD_H) +#include "thread_pthread.h" +#else +#error "unsupported thread type" +#endif + +#include + +#ifndef NSIG +# ifdef DJGPP +# define NSIG SIGMAX +# else +# define NSIG (_SIGMAX + 1) /* For QNX */ +# endif +#endif + +#define RUBY_NSIG NSIG + +/*****************/ +/* configuration */ +/*****************/ + +/* gcc ver. check */ +#if defined(__GNUC__) && __GNUC__ >= 2 + +#if OPT_TOKEN_THREADED_CODE +#if OPT_DIRECT_THREADED_CODE +#undef OPT_DIRECT_THREADED_CODE +#endif +#endif + +#else /* defined(__GNUC__) && __GNUC__ >= 2 */ + +/* disable threaded code options */ +#if OPT_DIRECT_THREADED_CODE +#undef OPT_DIRECT_THREADED_CODE +#endif +#if OPT_TOKEN_THREADED_CODE +#undef OPT_TOKEN_THREADED_CODE +#endif +#endif + +/* call threaded code */ +#if OPT_CALL_THREADED_CODE +#if OPT_DIRECT_THREADED_CODE +#undef OPT_DIRECT_THREADED_CODE +#endif /* OPT_DIRECT_THREADED_CODE */ +#if OPT_STACK_CACHING +#undef OPT_STACK_CACHING +#endif /* OPT_STACK_CACHING */ +#endif /* OPT_CALL_THREADED_CODE */ + +/* likely */ +#if __GNUC__ >= 3 +#define LIKELY(x) (__builtin_expect((x), 1)) +#define UNLIKELY(x) (__builtin_expect((x), 0)) +#else /* __GNUC__ >= 3 */ +#define LIKELY(x) (x) +#define UNLIKELY(x) (x) +#endif /* __GNUC__ >= 3 */ + +#define ISEQ_TYPE_TOP INT2FIX(1) +#define ISEQ_TYPE_METHOD INT2FIX(2) +#define ISEQ_TYPE_BLOCK INT2FIX(3) +#define ISEQ_TYPE_CLASS INT2FIX(4) +#define ISEQ_TYPE_RESCUE INT2FIX(5) +#define ISEQ_TYPE_ENSURE INT2FIX(6) +#define ISEQ_TYPE_EVAL INT2FIX(7) +#define ISEQ_TYPE_DEFINED_GUARD INT2FIX(8) + +#define CATCH_TYPE_RESCUE INT2FIX(1) +#define CATCH_TYPE_ENSURE INT2FIX(2) +#define CATCH_TYPE_RETRY INT2FIX(3) +#define CATCH_TYPE_BREAK INT2FIX(4) +#define CATCH_TYPE_REDO INT2FIX(5) +#define CATCH_TYPE_NEXT INT2FIX(6) + +struct iseq_insn_info_entry { + unsigned short position; + unsigned short line_no; +}; + +struct iseq_catch_table_entry { + VALUE type; + VALUE iseq; + unsigned long start; + unsigned long end; + unsigned long cont; + unsigned long sp; +}; + +#define INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE (512) + +struct iseq_compile_data_storage { + struct iseq_compile_data_storage *next; + unsigned long pos; + unsigned long size; + char *buff; +}; + +struct iseq_compile_data_ensure_node_stack; + +typedef struct rb_compile_option_struct { + int inline_const_cache; + int peephole_optimization; + int tailcall_optimization; + int specialized_instruction; + int operands_unification; + int instructions_unification; + int stack_caching; + int trace_instruction; +} rb_compile_option_t; + +struct iseq_compile_data { + /* GC is needed */ + VALUE err_info; + VALUE mark_ary; + VALUE catch_table_ary; /* Array */ + + /* GC is not needed */ + struct iseq_label_data *start_label; + struct iseq_label_data *end_label; + struct iseq_label_data *redo_label; + VALUE current_block; + VALUE loopval_popped; /* used by NODE_BREAK */ + VALUE ensure_node; + VALUE for_iseq; + struct iseq_compile_data_ensure_node_stack *ensure_node_stack; + int cached_const; + struct iseq_compile_data_storage *storage_head; + struct iseq_compile_data_storage *storage_current; + int last_line; + int flip_cnt; + const rb_compile_option_t *option; +}; + +#if 1 +#define GetCoreDataFromValue(obj, type, ptr) do { \ + ptr = (type*)DATA_PTR(obj); \ +} while (0) +#else +#define GetCoreDataFromValue(obj, type, ptr) Data_Get_Struct(obj, type, ptr) +#endif + +#define GetISeqPtr(obj, ptr) \ + GetCoreDataFromValue(obj, rb_iseq_t, ptr) + +typedef struct rb_iseq_profile_struct { + VALUE count; + VALUE time_self; + VALUE time_cumu; /* cumulative */ +} rb_iseq_profile_t; + +struct rb_iseq_struct; + +struct rb_iseq_struct { + /***************/ + /* static data */ + /***************/ + + VALUE type; /* instruction sequence type */ + VALUE name; /* String: iseq name */ + VALUE filename; /* file information where this sequence from */ + VALUE *iseq; /* iseq (insn number and openrads) */ + VALUE *iseq_encoded; /* encoded iseq */ + unsigned long iseq_size; + VALUE mark_ary; /* Array: includes operands which should be GC marked */ + + /* insn info, must be freed */ + struct iseq_insn_info_entry *insn_info_table; + unsigned long insn_info_size; + + ID *local_table; /* must free */ + int local_table_size; + + /* method, class frame: sizeof(vars) + 1, block frame: sizeof(vars) */ + int local_size; + + /** + * argument information + * + * def m(a1, a2, ..., aM, # mandatory + * b1=(...), b2=(...), ..., bN=(...), # optinal + * *c, # rest + * d1, d2, ..., dO, # post + * &e) # block + * => + * + * argc = M + * arg_rest = M+N+1 // or -1 if no rest arg + * arg_opts = N + * arg_opts_tbl = [ (N entries) ] + * arg_post_len = O // 0 if no post arguments + * arg_post_start = M+N+2 + * arg_block = M+N + 1 + O + 1 // -1 if no block arg + * arg_simple = 0 if not simple arguments. + * = 1 if no opt, rest, post, block. + * = 2 if ambiguos block parameter ({|a|}). + * arg_size = argument size. + */ + + int argc; + int arg_simple; + int arg_rest; + int arg_block; + int arg_opts; + int arg_post_len; + int arg_post_start; + int arg_size; + VALUE *arg_opt_table; + + int stack_max; /* for stack overflow check */ + + /* catch table */ + struct iseq_catch_table_entry *catch_table; + int catch_table_size; + + /* for child iseq */ + struct rb_iseq_struct *parent_iseq; + struct rb_iseq_struct *local_iseq; + + /****************/ + /* dynamic data */ + /****************/ + + VALUE self; + + /* block inlining */ + NODE *node; + void *special_block_builder; + void *cached_special_block_builder; + VALUE cached_special_block; + + /* klass/module nest information stack (cref) */ + NODE *cref_stack; + VALUE klass; + + /* misc */ + ID defined_method_id; /* for define_method */ + rb_iseq_profile_t profile; + + /* used at compile time */ + struct iseq_compile_data *compile_data; +}; + +typedef struct rb_iseq_struct rb_iseq_t; + +#define RUBY_EVENT_NONE 0x00 +#define RUBY_EVENT_LINE 0x01 +#define RUBY_EVENT_CLASS 0x02 +#define RUBY_EVENT_END 0x04 +#define RUBY_EVENT_CALL 0x08 +#define RUBY_EVENT_RETURN 0x10 +#define RUBY_EVENT_C_CALL 0x20 +#define RUBY_EVENT_C_RETURN 0x40 +#define RUBY_EVENT_RAISE 0x80 +#define RUBY_EVENT_ALL 0xff +#define RUBY_EVENT_VM 0x100 +#define RUBY_EVENT_SWITCH 0x200 + +typedef unsigned int rb_event_flag_t; +typedef void (*rb_event_hook_func_t)(rb_event_flag_t, VALUE data, VALUE, ID, VALUE klass); + +typedef struct rb_event_hook_struct { + rb_event_flag_t flag; + rb_event_hook_func_t func; + VALUE data; + struct rb_event_hook_struct *next; +} rb_event_hook_t; + +#define GetVMPtr(obj, ptr) \ + GetCoreDataFromValue(obj, rb_vm_t, ptr) + +typedef struct rb_vm_struct { + VALUE self; + + rb_thread_lock_t global_interpreter_lock; + + struct rb_thread_struct *main_thread; + struct rb_thread_struct *running_thread; + + st_table *living_threads; + VALUE thgroup_default; + VALUE last_status; /* $? */ + + int thread_abort_on_exception; + unsigned long trace_flag; + + /* object management */ + VALUE mark_object_ary; + + /* load */ + VALUE top_self; + VALUE loaded_features; + struct st_table *loading_table; + + /* signal */ + rb_atomic_t signal_buff[RUBY_NSIG]; + rb_atomic_t bufferd_signal_size; + + /* hook */ + rb_event_hook_t *event_hooks; +} rb_vm_t; + +typedef struct { + VALUE *pc; /* cfp[0] */ + VALUE *sp; /* cfp[1] */ + VALUE *bp; /* cfp[2] */ + rb_iseq_t *iseq; /* cfp[3] */ + VALUE flag; /* cfp[4] */ + VALUE self; /* cfp[5] / block[0] */ + VALUE *lfp; /* cfp[6] / block[1] */ + VALUE *dfp; /* cfp[7] / block[2] */ + rb_iseq_t *block_iseq; /* cfp[8] / block[3] */ + VALUE proc; /* cfp[9] / block[4] */ + ID method_id; /* cfp[10] saved in special case */ + VALUE method_klass; /* cfp[11] saved in special case */ + VALUE prof_time_self; /* cfp[12] */ + VALUE prof_time_chld; /* cfp[13] */ +} rb_control_frame_t; + +typedef struct { + VALUE self; /* share with method frame if it's only block */ + VALUE *lfp; /* share with method frame if it's only block */ + VALUE *dfp; /* share with method frame if it's only block */ + rb_iseq_t *iseq; + VALUE proc; +} rb_block_t; + +#define GetThreadPtr(obj, ptr) \ + GetCoreDataFromValue(obj, rb_thread_t, ptr) + +enum rb_thread_status { + THREAD_TO_KILL, + THREAD_RUNNABLE, + THREAD_STOPPED, + THREAD_KILLED, +}; + +typedef jmp_buf rb_jmpbuf_t; + +struct rb_vm_tag { + rb_jmpbuf_t buf; + VALUE tag; + VALUE retval; + struct rb_vm_tag *prev; +}; + +struct rb_vm_trap_tag { + struct rb_vm_trap_tag *prev; +}; + +#define RUBY_VM_VALUE_CACHE_SIZE 0x1000 +#define USE_VALUE_CACHE 0 + +struct rb_thread_struct +{ + VALUE self; + rb_vm_t *vm; + + /* execution information */ + VALUE *stack; /* must free, must mark */ + unsigned long stack_size; + rb_control_frame_t *cfp; + int safe_level; + int raised_flag; + + /* passing state */ + int state; + + /* for rb_iterate */ + rb_block_t *passed_block; + + /* for load(true) */ + VALUE top_self; + VALUE top_wrapper; + + /* eval env */ + rb_block_t *base_block; + + VALUE *local_lfp; + VALUE local_svar; + + /* thread control */ + rb_thread_id_t thread_id; + enum rb_thread_status status; + int priority; + + native_thread_data_t native_thread_data; + + VALUE thgroup; + VALUE value; + + VALUE errinfo; + VALUE thrown_errinfo; + int exec_signal; + + int interrupt_flag; + rb_unblock_function_t *unblock_function; + rb_thread_lock_t interrupt_lock; + + struct rb_vm_tag *tag; + struct rb_vm_trap_tag *trap_tag; + + int parse_in_eval; + + /* storage */ + st_table *local_storage; +#if USE_VALUE_CACHE + VALUE value_cache[RUBY_VM_VALUE_CACHE_SIZE + 1]; + VALUE *value_cache_ptr; +#endif + + struct rb_thread_struct *join_list_next; + struct rb_thread_struct *join_list_head; + + VALUE first_proc; + VALUE first_args; + VALUE (*first_func)(ANYARGS); + void *first_func_arg; + + /* for GC */ + VALUE *machine_stack_start; + VALUE *machine_stack_end; +#ifdef __ia64 + VALUE *machine_register_stack_start; + VALUE *machine_register_stack_end; +#endif + jmp_buf machine_regs; + int mark_stack_len; + + /* statistics data for profiler */ + VALUE stat_insn_usage; + + /* tracer */ + rb_event_hook_t *event_hooks; + rb_event_flag_t event_flags; + int tracing; + + /* fiber */ + VALUE fiber; + VALUE root_fiber; + rb_jmpbuf_t root_jmpbuf; + + /* misc */ + int method_missing_reason; + int abort_on_exception; +}; + +/* iseq.c */ +VALUE rb_iseq_new(NODE*, VALUE, VALUE, VALUE, VALUE); +VALUE rb_iseq_new_with_bopt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE); +VALUE rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, const rb_compile_option_t*); +VALUE rb_iseq_compile(VALUE src, VALUE file, VALUE line); +VALUE ruby_iseq_disasm(VALUE self); +VALUE ruby_iseq_disasm_insn(VALUE str, VALUE *iseqval, int pos, rb_iseq_t *iseq, VALUE child); +const char *ruby_node_name(int node); + + +/* each thread has this size stack : 128KB */ +#define RUBY_VM_THREAD_STACK_SIZE (128 * 1024) + +struct global_entry { + struct global_variable *var; + ID id; +}; + +#define GetProcPtr(obj, ptr) \ + GetCoreDataFromValue(obj, rb_proc_t, ptr) + +typedef struct { + rb_block_t block; + + VALUE envval; /* for GC mark */ + VALUE blockprocval; + int safe_level; + int is_lambda; + + NODE *special_cref_stack; +} rb_proc_t; + +#define GetEnvPtr(obj, ptr) \ + GetCoreDataFromValue(obj, rb_env_t, ptr) + +typedef struct { + VALUE *env; + int env_size; + int local_size; + VALUE prev_envval; /* for GC mark */ + rb_block_t block; +} rb_env_t; + +#define GetBindingPtr(obj, ptr) \ + GetCoreDataFromValue(obj, rb_binding_t, ptr) + +typedef struct { + VALUE env; + NODE *cref_stack; +} rb_binding_t; + + +/* used by compile time and send insn */ +#define VM_CALL_ARGS_SPLAT_BIT (0x01 << 1) +#define VM_CALL_ARGS_BLOCKARG_BIT (0x01 << 2) +#define VM_CALL_FCALL_BIT (0x01 << 3) +#define VM_CALL_VCALL_BIT (0x01 << 4) +#define VM_CALL_TAILCALL_BIT (0x01 << 5) +#define VM_CALL_TAILRECURSION_BIT (0x01 << 6) +#define VM_CALL_SUPER_BIT (0x01 << 7) +#define VM_CALL_SEND_BIT (0x01 << 8) + +/* inline (method|const) cache */ +#define NEW_INLINE_CACHE_ENTRY() NEW_WHILE(Qundef, 0, 0) +#define ic_klass u1.value +#define ic_method u2.node +#define ic_value u2.value +#define ic_vmstat u3.cnt +typedef NODE *IC; + +void rb_vm_change_state(void); + +typedef VALUE CDHASH; + +#ifndef FUNC_FASTCALL +#define FUNC_FASTCALL(x) x +#endif + +typedef rb_control_frame_t * + (FUNC_FASTCALL(*rb_insn_func_t))(rb_thread_t *, rb_control_frame_t *); + +#define GC_GUARDED_PTR(p) ((VALUE)((VALUE)(p) | 0x01)) +#define GC_GUARDED_PTR_REF(p) ((void *)(((VALUE)p) & ~0x03)) +#define GC_GUARDED_PTR_P(p) (((VALUE)p) & 0x01) + +#define RUBY_VM_METHOD_NODE NODE_METHOD + +#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp) (cfp+1) +#define RUBY_VM_NEXT_CONTROL_FRAME(cfp) (cfp-1) +#define RUBY_VM_END_CONTROL_FRAME(th) \ + ((rb_control_frame_t *)((th)->stack + (th)->stack_size)) +#define RUBY_VM_VALID_CONTROL_FRAME_P(cfp, ecfp) \ + ((void *)(ecfp) > (void *)(cfp)) +#define RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp) \ + (!RUBY_VM_VALID_CONTROL_FRAME_P((cfp), RUBY_VM_END_CONTROL_FRAME(th))) + +#define RUBY_VM_IFUNC_P(ptr) (BUILTIN_TYPE(ptr) == T_NODE) +#define RUBY_VM_NORMAL_ISEQ_P(ptr) \ + (ptr && !RUBY_VM_IFUNC_P(ptr)) + +#define RUBY_VM_CLASS_SPECIAL_P(ptr) (((VALUE)(ptr)) & 0x02) + +#define RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp) ((rb_block_t *)(&(cfp)->self)) +#define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b) \ + ((rb_control_frame_t *)((VALUE *)(b) - 5)) + +/* defined? */ +#define DEFINED_IVAR INT2FIX(1) +#define DEFINED_IVAR2 INT2FIX(2) +#define DEFINED_GVAR INT2FIX(3) +#define DEFINED_CVAR INT2FIX(4) +#define DEFINED_CONST INT2FIX(5) +#define DEFINED_METHOD INT2FIX(6) +#define DEFINED_YIELD INT2FIX(7) +#define DEFINED_REF INT2FIX(8) +#define DEFINED_ZSUPER INT2FIX(9) +#define DEFINED_FUNC INT2FIX(10) + +/* VM related object allocate functions */ +/* TODO: should be static functions */ +VALUE rb_thread_alloc(VALUE klass); +VALUE rb_proc_alloc(VALUE klass); + +/* for debug */ +extern void vm_stack_dump_raw(rb_thread_t *, rb_control_frame_t *); +#define SDR() vm_stack_dump_raw(GET_THREAD(), GET_THREAD()->cfp) +#define SDR2(cfp) vm_stack_dump_raw(GET_THREAD(), (cfp)) +void rb_vm_bugreport(void); + + +/* functions about thread/vm execution */ + +VALUE rb_iseq_eval(VALUE iseqval); +void rb_enable_interrupt(void); +void rb_disable_interrupt(void); +int rb_thread_method_id_and_klass(rb_thread_t *th, ID *idp, VALUE *klassp); + +VALUE vm_eval_body(rb_thread_t *th); +VALUE vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, int argc, VALUE *argv); +VALUE vm_make_proc(rb_thread_t *th, rb_control_frame_t *cfp, rb_block_t *block); +VALUE vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp); +VALUE vm_backtrace(rb_thread_t *, int); + +VALUE vm_yield(rb_thread_t *th, int argc, VALUE *argv); +VALUE vm_call0(rb_thread_t *th, VALUE klass, VALUE recv, VALUE id, ID oid, + int argc, const VALUE *argv, NODE *body, int nosuper); + +int vm_get_sourceline(rb_control_frame_t *); + +RUBY_EXTERN VALUE sysstack_error; + +/* for thread */ + +#if RUBY_VM_THREAD_MODEL == 2 +extern rb_thread_t *ruby_current_thread; +extern rb_vm_t *ruby_current_vm; + +#define GET_VM() ruby_current_vm +#define GET_THREAD() ruby_current_thread +#define rb_thread_set_current_raw(th) (ruby_current_thread = th) +#define rb_thread_set_current(th) do { \ + rb_thread_set_current_raw(th); \ + th->vm->running_thread = th; \ +} while (0) + +#else +#error "unsupported thread model" +#endif + +void rb_thread_execute_interrupts(rb_thread_t *); + +#define RUBY_VM_CHECK_INTS_TH(th) do { \ + if(th->interrupt_flag){ \ + /* TODO: trap something event */ \ + rb_thread_execute_interrupts(th); \ + } \ +} while (0) + +#define RUBY_VM_CHECK_INTS() \ + RUBY_VM_CHECK_INTS_TH(GET_THREAD()) + +/* tracer */ +static void inline +exec_event_hooks(rb_event_hook_t *hook, rb_event_flag_t flag, VALUE self, ID id, VALUE klass) +{ + while (hook) { + if (flag & hook->flag) { + (*hook->func)(flag, hook->data, self, id, klass); + } + hook = hook->next; + } +} + +#define EXEC_EVENT_HOOK(th, flag, self, id, klass) do { \ + rb_event_flag_t wait_event__ = th->event_flags; \ + if (UNLIKELY(wait_event__)) { \ + if (wait_event__ & (flag | RUBY_EVENT_VM)) { \ + VALUE self__ = (self), klass__ = (klass); \ + ID id__ = (id); \ + if (wait_event__ & flag) { \ + exec_event_hooks(th->event_hooks, flag, self__, id__, klass__); \ + } \ + if (wait_event__ & RUBY_EVENT_VM) { \ + exec_event_hooks(th->vm->event_hooks, flag, self__, id__, klass__); \ + } \ + } \ + } \ +} while (0) + +#endif /* RUBY_CORE_H */ diff --git a/vm_dump.c b/vm_dump.c index c72b4e1e7e..0f782e68c1 100644 --- a/vm_dump.c +++ b/vm_dump.c @@ -13,7 +13,7 @@ #include "ruby/ruby.h" #include "ruby/node.h" -#include "yarvcore.h" +#include "vm_core.h" #include "vm.h" #define MAX_POSBUF 128 @@ -114,7 +114,7 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp) line = -1; } - fprintf(stderr, "c:%04ld ", + fprintf(stderr, "c:%04d ", (rb_control_frame_t *)(th->stack + th->stack_size) - cfp); if (pc == -1) { fprintf(stderr, "p:---- "); @@ -123,8 +123,8 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp) fprintf(stderr, "p:%04d ", pc); } fprintf(stderr, "s:%04d b:%04d ", cfp->sp - th->stack, bp); - fprintf(stderr, lfp_in_heap == ' ' ? "l:%06d " : "l:%06p ", lfp % 10000); - fprintf(stderr, dfp_in_heap == ' ' ? "d:%06d " : "d:%06p ", dfp % 10000); + fprintf(stderr, lfp_in_heap == ' ' ? "l:%06d " : "l:%06x ", lfp % 10000); + fprintf(stderr, dfp_in_heap == ' ' ? "d:%06d " : "d:%06x ", dfp % 10000); fprintf(stderr, "%-6s ", magic); if (line) { fprintf(stderr, "%s", posbuf); @@ -235,7 +235,7 @@ stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp) VALUE *lfp = cfp->lfp; VALUE *dfp = cfp->dfp; - int argc, local_size; + int argc = 0, local_size; const char *name; rb_iseq_t *iseq = cfp->iseq; @@ -300,7 +300,7 @@ stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp) else { rstr = rb_inspect(*ptr); } - fprintf(stderr, " stack %2d: %8s (%ld)\n", i, StringValueCStr(rstr), + fprintf(stderr, " stack %2d: %8s (%d)\n", i, StringValueCStr(rstr), ptr - th->stack); } } @@ -337,7 +337,7 @@ debug_print_register(rb_thread_t *th) dfp = -1; cfpi = ((rb_control_frame_t *)(th->stack + th->stack_size)) - cfp; - fprintf(stderr, " [PC] %04d, [SP] %04ld, [LFP] %04d, [DFP] %04d, [CFP] %04d\n", + fprintf(stderr, " [PC] %04d, [SP] %04d, [LFP] %04d, [DFP] %04d, [CFP] %04d\n", pc, cfp->sp - th->stack, lfp, dfp, cfpi); } @@ -424,13 +424,11 @@ vm_analysis_insn(int insn) VALUE ihash; VALUE cv; - SET_YARV_STOP(); - if (usage_hash == 0) { usage_hash = rb_intern("USAGE_ANALISYS_INSN"); bigram_hash = rb_intern("USAGE_ANALISYS_INSN_BIGRAM"); } - uh = rb_const_get(mYarvCore, usage_hash); + uh = rb_const_get(rb_cVM, usage_hash); if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) { ihash = rb_hash_new(); rb_hash_aset(uh, INT2FIX(insn), ihash); @@ -450,15 +448,13 @@ vm_analysis_insn(int insn) ary[1] = INT2FIX(insn); bi = rb_ary_new4(2, &ary[0]); - uh = rb_const_get(mYarvCore, bigram_hash); + uh = rb_const_get(rb_cVM, bigram_hash); if ((cv = rb_hash_aref(uh, bi)) == Qnil) { cv = INT2FIX(0); } rb_hash_aset(uh, bi, INT2FIX(FIX2INT(cv) + 1)); } prev_insn = insn; - - SET_YARV_START(); } /* from disasm.c */ @@ -476,13 +472,11 @@ vm_analysis_operand(int insn, int n, VALUE op) VALUE valstr; VALUE cv; - SET_YARV_STOP(); - if (usage_hash == 0) { usage_hash = rb_intern("USAGE_ANALISYS_INSN"); } - uh = rb_const_get(mYarvCore, usage_hash); + uh = rb_const_get(rb_cVM, usage_hash); if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) { ihash = rb_hash_new(); rb_hash_aset(uh, INT2FIX(insn), ihash); @@ -499,8 +493,6 @@ vm_analysis_operand(int insn, int n, VALUE op) cv = INT2FIX(0); } rb_hash_aset(ophash, valstr, INT2FIX(FIX2INT(cv) + 1)); - - SET_YARV_START(); } void @@ -527,8 +519,6 @@ vm_analysis_register(int reg, int isset) VALUE cv; - SET_YARV_STOP(); - if (usage_hash == 0) { char buff[0x10]; int i; @@ -546,13 +536,11 @@ vm_analysis_register(int reg, int isset) } valstr = syms[reg][isset]; - uh = rb_const_get(mYarvCore, usage_hash); + uh = rb_const_get(rb_cVM, usage_hash); if ((cv = rb_hash_aref(uh, valstr)) == Qnil) { cv = INT2FIX(0); } rb_hash_aset(uh, valstr, INT2FIX(FIX2INT(cv) + 1)); - - SET_YARV_START(); } @@ -575,7 +563,7 @@ thread_dump_state(VALUE self) } void -yarv_bug(void) +rb_vm_bugreport(void) { rb_thread_t *th = GET_THREAD(); VALUE bt; diff --git a/vm_evalbody.ci b/vm_evalbody.ci index f9dd39f5a3..3ac3fa5192 100644 --- a/vm_evalbody.ci +++ b/vm_evalbody.ci @@ -80,9 +80,9 @@ vm_eval(rb_thread_t *th, VALUE initial) #include "vmtc.inc" if (th == 0) { #if OPT_STACK_CACHING - yarv_finish_insn_seq[0] = (VALUE)&&LABEL (finish_SC_ax_ax); + finish_insn_seq[0] = (VALUE)&&LABEL (finish_SC_ax_ax); #else - yarv_finish_insn_seq[0] = (VALUE)&&LABEL (finish); + finish_insn_seq[0] = (VALUE)&&LABEL (finish); #endif return (VALUE)insns_address_table; } diff --git a/yarvcore.c b/yarvcore.c deleted file mode 100644 index 194ca1a586..0000000000 --- a/yarvcore.c +++ /dev/null @@ -1,582 +0,0 @@ -/********************************************************************** - - yarvcore.h - - - $Author$ - $Date$ - created at: 04/01/01 01:17:22 JST - - Copyright (C) 2004-2006 Koichi Sasada - -**********************************************************************/ - -#include "ruby/ruby.h" -#include "ruby/node.h" -#include "yarvcore.h" -#include "gc.h" - - -VALUE rb_cVM; -VALUE rb_cThread; - -VALUE symIFUNC; -VALUE symCFUNC; - -ID idPLUS; -ID idMINUS; -ID idMULT; -ID idDIV; -ID idMOD; -ID idLT; -ID idLTLT; -ID idLE; -ID idGT; -ID idGE; -ID idEq; -ID idEqq; -ID idBackquote; -ID idEqTilde; -ID idThrowState; -ID idAREF; -ID idASET; -ID idIntern; -ID idMethodMissing; -ID idLength; -ID idLambda; -ID idGets; -ID idSucc; -ID idEach; -ID idRangeEachLT; -ID idRangeEachLE; -ID idArrayEach; -ID idTimes; -ID idEnd; -ID idBitblt; -ID idAnswer; -ID idSvarPlaceholder; -ID idSend; -ID id__send__; -ID id__send; -ID idFuncall; -ID id__send_bang; - -/* from Ruby 1.9 eval.c */ -#ifdef HAVE_STDARG_PROTOTYPES -#include -#define va_init_list(a,b) va_start(a,b) -#else -#include -#define va_init_list(a,b) va_start(a) -#endif - -/************/ -/* YARVCore */ -/************/ - -rb_thread_t *ruby_current_thread = 0; -rb_vm_t *ruby_current_vm = 0; - -static NODE * -compile_string(VALUE str, VALUE file, VALUE line) -{ - VALUE parser = rb_parser_new(); - NODE *node; - - node = rb_parser_compile_string(parser, StringValueCStr(file), - str, NUM2INT(line)); - - if (!node) { - rb_exc_raise(GET_THREAD()->errinfo); /* TODO: check err */ - } - return node; -} - -static VALUE -yarvcore_eval_iseq(VALUE iseq) -{ - return rb_thread_eval(GET_THREAD(), iseq); -} - -static VALUE -vm_compile_from_node(rb_thread_t *th, NODE * node, VALUE file) -{ - VALUE iseq; - if (th->base_block) { - iseq = rb_iseq_new(node, - th->base_block->iseq->name, - file, - th->base_block->iseq->self, - ISEQ_TYPE_EVAL); - } - else { - iseq = rb_iseq_new(node, rb_str_new2("
"), file, - Qfalse, ISEQ_TYPE_TOP); - } - return iseq; -} - -VALUE -vm_compile(rb_thread_t *th, VALUE str, VALUE file, VALUE line) -{ - NODE *node = (NODE *) compile_string(str, file, line); - return vm_compile_from_node(th, (NODE *) node, file); -} - -VALUE -yarvcore_eval_parsed(NODE *node, VALUE file) -{ - VALUE iseq = vm_compile_from_node(GET_THREAD(), node, file); - return yarvcore_eval_iseq(iseq); -} - -VALUE -yarvcore_eval(VALUE self, VALUE str, VALUE file, VALUE line) -{ - NODE *node; - node = compile_string(str, file, line); - return yarvcore_eval_parsed(node, file); -} - -/******/ -/* VM */ -/******/ - -void native_thread_cleanup(void *); - -static void -vm_free(void *ptr) -{ - RUBY_FREE_ENTER("vm"); - if (ptr) { - rb_vm_t *vmobj = ptr; - - st_free_table(vmobj->living_threads); - /* TODO: MultiVM Instance */ - /* VM object should not be cleaned by GC */ - /* ruby_xfree(ptr); */ - /* ruby_current_vm = 0; */ - } - RUBY_FREE_LEAVE("vm"); -} - -static int -vm_mark_each_thread_func(st_data_t key, st_data_t value, st_data_t dummy) -{ - VALUE thval = (VALUE)key; - rb_gc_mark(thval); - return ST_CONTINUE; -} - -static void -mark_event_hooks(rb_event_hook_t *hook) -{ - while (hook) { - rb_gc_mark(hook->data); - hook = hook->next; - } -} - -static void -vm_mark(void *ptr) -{ - RUBY_MARK_ENTER("vm"); - RUBY_GC_INFO("-------------------------------------------------\n"); - if (ptr) { - rb_vm_t *vm = ptr; - if (vm->living_threads) { - st_foreach(vm->living_threads, vm_mark_each_thread_func, 0); - } - RUBY_MARK_UNLESS_NULL(vm->thgroup_default); - RUBY_MARK_UNLESS_NULL(vm->mark_object_ary); - RUBY_MARK_UNLESS_NULL(vm->last_status); - RUBY_MARK_UNLESS_NULL(vm->loaded_features); - - if (vm->loading_table) { - rb_mark_tbl(vm->loading_table); - } - - mark_event_hooks(vm->event_hooks); - } - - RUBY_MARK_LEAVE("vm"); -} - -void -rb_vm_mark(void *ptr) -{ - vm_mark(ptr); -} - -static void -vm_init2(rb_vm_t *vm) -{ - MEMZERO(vm, rb_vm_t, 1); -} - -/**********/ -/* Thread */ -/**********/ - -static void -thread_free(void *ptr) -{ - rb_thread_t *th; - RUBY_FREE_ENTER("thread"); - - if (ptr) { - th = ptr; - - if (!th->root_fiber) { - RUBY_FREE_UNLESS_NULL(th->stack); - } - - if (th->local_storage) { - st_free_table(th->local_storage); - } - -#if USE_VALUE_CACHE - { - VALUE *ptr = th->value_cache_ptr; - while (*ptr) { - VALUE v = *ptr; - RBASIC(v)->flags = 0; - RBASIC(v)->klass = 0; - ptr++; - } - } -#endif - - if (th->vm->main_thread == th) { - RUBY_GC_INFO("main thread\n"); - } - else { - ruby_xfree(ptr); - } - } - RUBY_FREE_LEAVE("thread"); -} - -void yarv_machine_stack_mark(rb_thread_t *th); - -void -rb_thread_mark(void *ptr) -{ - rb_thread_t *th = NULL; - RUBY_MARK_ENTER("thread"); - if (ptr) { - th = ptr; - if (th->stack) { - VALUE *p = th->stack; - VALUE *sp = th->cfp->sp + th->mark_stack_len; - rb_control_frame_t *cfp = th->cfp; - rb_control_frame_t *limit_cfp = - (void *)(th->stack + th->stack_size); - - while (p < sp) { - rb_gc_mark(*p++); - } - while (cfp != limit_cfp) { - rb_gc_mark(cfp->proc); - cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); - } - } - - /* mark ruby objects */ - RUBY_MARK_UNLESS_NULL(th->first_proc); - RUBY_MARK_UNLESS_NULL(th->first_args); - - RUBY_MARK_UNLESS_NULL(th->thgroup); - RUBY_MARK_UNLESS_NULL(th->value); - RUBY_MARK_UNLESS_NULL(th->errinfo); - RUBY_MARK_UNLESS_NULL(th->thrown_errinfo); - RUBY_MARK_UNLESS_NULL(th->local_svar); - RUBY_MARK_UNLESS_NULL(th->top_self); - RUBY_MARK_UNLESS_NULL(th->top_wrapper); - RUBY_MARK_UNLESS_NULL(th->fiber); - RUBY_MARK_UNLESS_NULL(th->root_fiber); - - rb_mark_tbl(th->local_storage); - - if (GET_THREAD() != th && th->machine_stack_start && th->machine_stack_end) { - yarv_machine_stack_mark(th); - rb_gc_mark_locations((VALUE *)&th->machine_regs, - (VALUE *)(&th->machine_regs) + - sizeof(th->machine_regs) / sizeof(VALUE)); - } - - mark_event_hooks(th->event_hooks); - } - - RUBY_MARK_UNLESS_NULL(th->stat_insn_usage); - RUBY_MARK_LEAVE("thread"); -} - -static VALUE -thread_alloc(VALUE klass) -{ - VALUE volatile obj; - rb_thread_t *th; - obj = Data_Make_Struct(klass, rb_thread_t, - rb_thread_mark, thread_free, th); - return obj; -} - -static void -th_init2(rb_thread_t *th) -{ - MEMZERO(th, rb_thread_t, 1); - - /* allocate thread stack */ - th->stack_size = RUBY_VM_THREAD_STACK_SIZE; - th->stack = ALLOC_N(VALUE, th->stack_size); - - th->cfp = (void *)(th->stack + th->stack_size); - th->cfp--; - - th->cfp->pc = 0; - th->cfp->sp = th->stack + 1; - th->cfp->bp = 0; - th->cfp->lfp = th->stack; - *th->cfp->lfp = 0; - th->cfp->dfp = th->stack; - th->cfp->self = Qnil; - th->cfp->flag = 0; - th->cfp->iseq = 0; - th->cfp->proc = 0; - th->cfp->block_iseq = 0; - - th->status = THREAD_RUNNABLE; - th->errinfo = Qnil; - -#if USE_VALUE_CACHE - th->value_cache_ptr = &th->value_cache[0]; -#endif -} - -static void -th_init(rb_thread_t *th) -{ - th_init2(th); -} - -extern VALUE ruby_top_self; - -static VALUE -ruby_thread_init(VALUE self) -{ - rb_thread_t *th; - rb_vm_t *vm = GET_THREAD()->vm; - GetThreadPtr(self, th); - - th_init(th); - th->self = self; - th->vm = vm; - - th->top_wrapper = 0; - th->top_self = ruby_top_self; - return self; -} - -VALUE -rb_thread_alloc(VALUE klass) -{ - VALUE self = thread_alloc(klass); - ruby_thread_init(self); - return self; -} - -/********************************************************************/ - -VALUE insns_name_array(void); -extern VALUE *rb_gc_stack_start; -#ifdef __ia64 -extern VALUE *rb_gc_register_stack_start; -#endif - -static VALUE -sdr(void) -{ - yarv_bug(); - return Qnil; -} - -static VALUE -nsdr(void) -{ - VALUE ary = rb_ary_new(); -#if HAVE_BACKTRACE -#include -#define MAX_NATIVE_TRACE 1024 - static void *trace[MAX_NATIVE_TRACE]; - int n = backtrace(trace, MAX_NATIVE_TRACE); - char **syms = backtrace_symbols(trace, n); - int i; - - if (syms == 0) { - rb_memerror(); - } - - for (i=0; i")); - symCFUNC = ID2SYM(rb_intern("")); - - /* IDs */ - idPLUS = rb_intern("+"); - idMINUS = rb_intern("-"); - idMULT = rb_intern("*"); - idDIV = rb_intern("/"); - idMOD = rb_intern("%"); - idLT = rb_intern("<"); - idLTLT = rb_intern("<<"); - idLE = rb_intern("<="); - idGT = rb_intern(">"); - idGE = rb_intern(">="); - idEq = rb_intern("=="); - idEqq = rb_intern("==="); - idBackquote = rb_intern("`"); - idEqTilde = rb_intern("=~"); - - idAREF = rb_intern("[]"); - idASET = rb_intern("[]="); - - idEach = rb_intern("each"); - idTimes = rb_intern("times"); - idLength = rb_intern("length"); - idLambda = rb_intern("lambda"); - idIntern = rb_intern("intern"); - idGets = rb_intern("gets"); - idSucc = rb_intern("succ"); - idEnd = rb_intern("end"); - idRangeEachLT = rb_intern("Range#each#LT"); - idRangeEachLE = rb_intern("Range#each#LE"); - idArrayEach = rb_intern("Array#each"); - idMethodMissing = rb_intern("method_missing"); - - idThrowState = rb_intern("#__ThrowState__"); - - idBitblt = rb_intern("bitblt"); - idAnswer = rb_intern("the_answer_to_life_the_universe_and_everything"); - idSvarPlaceholder = rb_intern("#svar"); - - idSend = rb_intern("send"); - id__send__ = rb_intern("__send__"); - id__send = rb_intern("__send"); - idFuncall = rb_intern("funcall"); - id__send_bang = rb_intern("__send!"); - - /* VM bootstrap: phase 2 */ - { - rb_vm_t *vm = ruby_current_vm; - rb_thread_t *th = GET_THREAD(); - volatile VALUE th_self; - - /* create vm object */ - vm->self = Data_Wrap_Struct(rb_cVM, vm_mark, vm_free, vm); - - /* create main thread */ - th_self = th->self = Data_Wrap_Struct(rb_cThread, rb_thread_mark, - thread_free, th); - - vm->main_thread = th; - vm->running_thread = th; - th->vm = vm; - th->top_wrapper = 0; - th->top_self = ruby_top_self; - rb_thread_set_current(th); - - vm->living_threads = st_init_numtable(); - st_insert(vm->living_threads, th_self, (st_data_t) th->thread_id); - } - yarv_init_redefined_flag(); -} - -void -Init_yarv(void) -{ - /* VM bootstrap: phase 1 */ - rb_vm_t *vm = ALLOC(rb_vm_t); - rb_thread_t *th = ALLOC(rb_thread_t); - - vm_init2(vm); - ruby_current_vm = vm; - - th_init2(th); - th->vm = vm; - th->machine_stack_start = rb_gc_stack_start; -#ifdef __ia64 - th->machine_register_stack_start = rb_gc_register_stack_start; -#endif - rb_thread_set_current_raw(th); -} - diff --git a/yarvcore.h b/yarvcore.h deleted file mode 100644 index d0ce781dd8..0000000000 --- a/yarvcore.h +++ /dev/null @@ -1,751 +0,0 @@ -/********************************************************************** - - yarvcore.h - - - $Author$ - $Date$ - created at: 04/01/01 19:41:38 JST - - Copyright (C) 2004-2006 Koichi Sasada - -**********************************************************************/ - -#ifndef _YARVCORE_H_INCLUDED_ -#define _YARVCORE_H_INCLUDED_ - -#define RUBY_VM_THREAD_MODEL 2 - -#include - -#include "ruby/ruby.h" -#include "ruby/signal.h" -#include "ruby/st.h" -#include "ruby/node.h" - -#include "debug.h" -#include "vm_opts.h" - -#if defined(_WIN32) -#include "thread_win32.h" -#elif defined(HAVE_PTHREAD_H) -#include "thread_pthread.h" -#else -#error "unsupported thread type" -#endif - -#include - -#ifndef NSIG -# ifdef DJGPP -# define NSIG SIGMAX -# else -# define NSIG (_SIGMAX + 1) /* For QNX */ -# endif -#endif - -#define RUBY_NSIG NSIG - -/*****************/ -/* configuration */ -/*****************/ - -/* gcc ver. check */ -#if defined(__GNUC__) && __GNUC__ >= 2 - -#if OPT_TOKEN_THREADED_CODE -#if OPT_DIRECT_THREADED_CODE -#undef OPT_DIRECT_THREADED_CODE -#endif -#endif - -#else /* defined(__GNUC__) && __GNUC__ >= 2 */ - -/* disable threaded code options */ -#if OPT_DIRECT_THREADED_CODE -#undef OPT_DIRECT_THREADED_CODE -#endif -#if OPT_TOKEN_THREADED_CODE -#undef OPT_TOKEN_THREADED_CODE -#endif -#endif - -/* call threaded code */ -#if OPT_CALL_THREADED_CODE -#if OPT_DIRECT_THREADED_CODE -#undef OPT_DIRECT_THREADED_CODE -#endif /* OPT_DIRECT_THREADED_CODE */ -#if OPT_STACK_CACHING -#undef OPT_STACK_CACHING -#endif /* OPT_STACK_CACHING */ -#define YARV_AOT_COMPILED 1 -#endif /* OPT_CALL_THREADED_CODE */ - -/* likely */ -#if __GNUC__ >= 3 -#define LIKELY(x) (__builtin_expect((x), 1)) -#define UNLIKELY(x) (__builtin_expect((x), 0)) -#else /* __GNUC__ >= 3 */ -#define LIKELY(x) (x) -#define UNLIKELY(x) (x) -#endif /* __GNUC__ >= 3 */ - -#define YARVDEBUG 0 -#define CPDEBUG 0 -#define VMDEBUG 0 -#define GCDEBUG 0 - - -/* classes and modules */ - -extern VALUE symIFUNC; -extern VALUE symCFUNC; - -/* special id */ -extern ID idPLUS; -extern ID idMINUS; -extern ID idMULT; -extern ID idDIV; -extern ID idMOD; -extern ID idLT; -extern ID idLTLT; -extern ID idLE; -extern ID idGT; -extern ID idGE; -extern ID idEq; -extern ID idEqq; -extern ID idBackquote; -extern ID idEqTilde; -extern ID idThrowState; -extern ID idAREF; -extern ID idASET; -extern ID idIntern; -extern ID idMethodMissing; -extern ID idLength; -extern ID idGets; -extern ID idSucc; -extern ID idEach; -extern ID idLambda; -extern ID idRangeEachLT; -extern ID idRangeEachLE; -extern ID idArrayEach; -extern ID idTimes; -extern ID idEnd; -extern ID idBitblt; -extern ID idAnswer; -extern ID idSvarPlaceholder; -extern ID idSend; -extern ID id__send__; -extern ID id__send; -extern ID idFuncall; -extern ID id__send_bang; - - -struct iseq_insn_info_entry { - unsigned short position; - unsigned short line_no; -}; - -#define ISEQ_TYPE_TOP INT2FIX(1) -#define ISEQ_TYPE_METHOD INT2FIX(2) -#define ISEQ_TYPE_BLOCK INT2FIX(3) -#define ISEQ_TYPE_CLASS INT2FIX(4) -#define ISEQ_TYPE_RESCUE INT2FIX(5) -#define ISEQ_TYPE_ENSURE INT2FIX(6) -#define ISEQ_TYPE_EVAL INT2FIX(7) -#define ISEQ_TYPE_DEFINED_GUARD INT2FIX(8) - -#define CATCH_TYPE_RESCUE INT2FIX(1) -#define CATCH_TYPE_ENSURE INT2FIX(2) -#define CATCH_TYPE_RETRY INT2FIX(3) -#define CATCH_TYPE_BREAK INT2FIX(4) -#define CATCH_TYPE_REDO INT2FIX(5) -#define CATCH_TYPE_NEXT INT2FIX(6) - -struct iseq_catch_table_entry { - VALUE type; - VALUE iseq; - unsigned long start; - unsigned long end; - unsigned long cont; - unsigned long sp; -}; - -#define INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE (512) - -struct iseq_compile_data_storage { - struct iseq_compile_data_storage *next; - unsigned long pos; - unsigned long size; - char *buff; -}; - -struct iseq_compile_data_ensure_node_stack; - -typedef struct rb_compile_option_struct { - int inline_const_cache; - int peephole_optimization; - int tailcall_optimization; - int specialized_instruction; - int operands_unification; - int instructions_unification; - int stack_caching; - int trace_instruction; -} rb_compile_option_t; - -struct iseq_compile_data { - /* GC is needed */ - VALUE err_info; - VALUE mark_ary; - VALUE catch_table_ary; /* Array */ - - /* GC is not needed */ - struct iseq_label_data *start_label; - struct iseq_label_data *end_label; - struct iseq_label_data *redo_label; - VALUE current_block; - VALUE loopval_popped; /* used by NODE_BREAK */ - VALUE ensure_node; - VALUE for_iseq; - struct iseq_compile_data_ensure_node_stack *ensure_node_stack; - int cached_const; - struct iseq_compile_data_storage *storage_head; - struct iseq_compile_data_storage *storage_current; - int last_line; - int flip_cnt; - const rb_compile_option_t *option; -}; - -#if 1 -#define GetCoreDataFromValue(obj, type, ptr) do { \ - ptr = (type*)DATA_PTR(obj); \ -} while (0) -#else -#define GetCoreDataFromValue(obj, type, ptr) Data_Get_Struct(obj, type, ptr) -#endif - -#define GetISeqPtr(obj, ptr) \ - GetCoreDataFromValue(obj, rb_iseq_t, ptr) - -typedef struct rb_iseq_profile_struct { - VALUE count; - VALUE time_self; - VALUE time_cumu; /* cumulative */ -} rb_iseq_profile_t; - -struct rb_iseq_struct; - -struct rb_iseq_struct { - /***************/ - /* static data */ - /***************/ - - VALUE type; /* instruction sequence type */ - VALUE name; /* String: iseq name */ - VALUE filename; /* file information where this sequence from */ - VALUE *iseq; /* iseq (insn number and openrads) */ - VALUE *iseq_encoded; /* encoded iseq */ - unsigned long iseq_size; - VALUE mark_ary; /* Array: includes operands which should be GC marked */ - - /* insn info, must be freed */ - struct iseq_insn_info_entry *insn_info_table; - unsigned long insn_info_size; - - ID *local_table; /* must free */ - int local_table_size; - - /* method, class frame: sizeof(vars) + 1, block frame: sizeof(vars) */ - int local_size; - - /** - * argument information - * - * def m(a1, a2, ..., aM, # mandatory - * b1=(...), b2=(...), ..., bN=(...), # optinal - * *c, # rest - * d1, d2, ..., dO, # post - * &e) # block - * => - * - * argc = M - * arg_rest = M+N+1 // or -1 if no rest arg - * arg_opts = N - * arg_opts_tbl = [ (N entries) ] - * arg_post_len = O // 0 if no post arguments - * arg_post_start = M+N+2 - * arg_block = M+N + 1 + O + 1 // -1 if no block arg - * arg_simple = 0 if not simple arguments. - * = 1 if no opt, rest, post, block. - * = 2 if ambiguos block parameter ({|a|}). - * arg_size = argument size. - */ - - int argc; - int arg_simple; - int arg_rest; - int arg_block; - int arg_opts; - int arg_post_len; - int arg_post_start; - int arg_size; - VALUE *arg_opt_table; - - int stack_max; /* for stack overflow check */ - - /* catch table */ - struct iseq_catch_table_entry *catch_table; - int catch_table_size; - - /* for child iseq */ - struct rb_iseq_struct *parent_iseq; - struct rb_iseq_struct *local_iseq; - - /****************/ - /* dynamic data */ - /****************/ - - VALUE self; - - /* block inlining */ - NODE *node; - void *special_block_builder; - void *cached_special_block_builder; - VALUE cached_special_block; - - /* klass/module nest information stack (cref) */ - NODE *cref_stack; - VALUE klass; - - /* misc */ - ID defined_method_id; /* for define_method */ - rb_iseq_profile_t profile; - - /* used at compile time */ - struct iseq_compile_data *compile_data; -}; - -typedef struct rb_iseq_struct rb_iseq_t; - -#define RUBY_EVENT_NONE 0x00 -#define RUBY_EVENT_LINE 0x01 -#define RUBY_EVENT_CLASS 0x02 -#define RUBY_EVENT_END 0x04 -#define RUBY_EVENT_CALL 0x08 -#define RUBY_EVENT_RETURN 0x10 -#define RUBY_EVENT_C_CALL 0x20 -#define RUBY_EVENT_C_RETURN 0x40 -#define RUBY_EVENT_RAISE 0x80 -#define RUBY_EVENT_ALL 0xff -#define RUBY_EVENT_VM 0x100 -#define RUBY_EVENT_SWITCH 0x200 - -typedef unsigned int rb_event_flag_t; -typedef void (*rb_event_hook_func_t)(rb_event_flag_t, VALUE data, VALUE, ID, VALUE klass); - -typedef struct rb_event_hook_struct { - rb_event_flag_t flag; - rb_event_hook_func_t func; - VALUE data; - struct rb_event_hook_struct *next; -} rb_event_hook_t; - - -#define GetVMPtr(obj, ptr) \ - GetCoreDataFromValue(obj, rb_vm_t, ptr) - -typedef struct rb_vm_struct { - VALUE self; - - rb_thread_lock_t global_interpreter_lock; - - struct rb_thread_struct *main_thread; - struct rb_thread_struct *running_thread; - - st_table *living_threads; - VALUE thgroup_default; - VALUE last_status; /* $? */ - - int thread_abort_on_exception; - unsigned long trace_flag; - - /* object management */ - VALUE mark_object_ary; - - /* load */ - VALUE loaded_features; - struct st_table *loading_table; - - /* signal */ - rb_atomic_t signal_buff[RUBY_NSIG]; - rb_atomic_t bufferd_signal_size; - - /* hook */ - rb_event_hook_t *event_hooks; -} rb_vm_t; - -typedef struct { - VALUE *pc; /* cfp[0] */ - VALUE *sp; /* cfp[1] */ - VALUE *bp; /* cfp[2] */ - rb_iseq_t *iseq; /* cfp[3] */ - VALUE flag; /* cfp[4] */ - VALUE self; /* cfp[5] / block[0] */ - VALUE *lfp; /* cfp[6] / block[1] */ - VALUE *dfp; /* cfp[7] / block[2] */ - rb_iseq_t *block_iseq; /* cfp[8] / block[3] */ - VALUE proc; /* cfp[9] / block[4] */ - ID method_id; /* cfp[10] saved in special case */ - VALUE method_klass; /* cfp[11] saved in special case */ - VALUE prof_time_self; /* cfp[12] */ - VALUE prof_time_chld; /* cfp[13] */ -} rb_control_frame_t; - -typedef struct { - VALUE self; /* share with method frame if it's only block */ - VALUE *lfp; /* share with method frame if it's only block */ - VALUE *dfp; /* share with method frame if it's only block */ - rb_iseq_t *iseq; - VALUE proc; -} rb_block_t; - -#define GetThreadPtr(obj, ptr) \ - GetCoreDataFromValue(obj, rb_thread_t, ptr) - -enum rb_thread_status { - THREAD_TO_KILL, - THREAD_RUNNABLE, - THREAD_STOPPED, - THREAD_KILLED, -}; - -typedef jmp_buf rb_jmpbuf_t; - -struct rb_vm_tag { - rb_jmpbuf_t buf; - VALUE tag; - VALUE retval; - struct rb_vm_tag *prev; -}; - -struct rb_vm_trap_tag { - struct rb_vm_trap_tag *prev; -}; - -#define RUBY_VM_VALUE_CACHE_SIZE 0x1000 -#define USE_VALUE_CACHE 0 - -struct rb_thread_struct -{ - VALUE self; - rb_vm_t *vm; - - /* execution information */ - VALUE *stack; /* must free, must mark */ - unsigned long stack_size; - rb_control_frame_t *cfp; - int safe_level; - int raised_flag; - - /* passing state */ - int state; - - /* for rb_iterate */ - rb_block_t *passed_block; - - /* for load(true) */ - VALUE top_self; - VALUE top_wrapper; - - /* eval env */ - rb_block_t *base_block; - - VALUE *local_lfp; - VALUE local_svar; - - /* thread control */ - rb_thread_id_t thread_id; - enum rb_thread_status status; - int priority; - - native_thread_data_t native_thread_data; - - VALUE thgroup; - VALUE value; - - VALUE errinfo; - VALUE thrown_errinfo; - int exec_signal; - - int interrupt_flag; - rb_unblock_function_t *unblock_function; - rb_thread_lock_t interrupt_lock; - - struct rb_vm_tag *tag; - struct rb_vm_trap_tag *trap_tag; - - int parse_in_eval; - - /* storage */ - st_table *local_storage; -#if USE_VALUE_CACHE - VALUE value_cache[RUBY_VM_VALUE_CACHE_SIZE + 1]; - VALUE *value_cache_ptr; -#endif - - struct rb_thread_struct *join_list_next; - struct rb_thread_struct *join_list_head; - - VALUE first_proc; - VALUE first_args; - VALUE (*first_func)(ANYARGS); - void *first_func_arg; - - /* for GC */ - VALUE *machine_stack_start; - VALUE *machine_stack_end; -#ifdef __ia64 - VALUE *machine_register_stack_start; - VALUE *machine_register_stack_end; -#endif - jmp_buf machine_regs; - int mark_stack_len; - - /* statistics data for profiler */ - VALUE stat_insn_usage; - - /* tracer */ - rb_event_hook_t *event_hooks; - rb_event_flag_t event_flags; - int tracing; - - /* fiber */ - VALUE fiber; - VALUE root_fiber; - rb_jmpbuf_t root_jmpbuf; - - /* misc */ - int method_missing_reason; - int abort_on_exception; -}; - -/** node -> yarv instruction sequence object */ -VALUE rb_iseq_compile(VALUE self, NODE *node); -VALUE rb_iseq_new(NODE*, VALUE, VALUE, VALUE, VALUE); -VALUE rb_iseq_new_with_bopt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE); -VALUE rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, const rb_compile_option_t*); - -/** disassemble instruction sequence */ -VALUE ruby_iseq_disasm(VALUE self); -VALUE ruby_iseq_disasm_insn(VALUE str, VALUE *iseqval, int pos, - rb_iseq_t *iseq, VALUE child); -const char *ruby_node_name(int node); - - -/* each thread has this size stack : 2MB */ -#define RUBY_VM_THREAD_STACK_SIZE (128 * 1024) - - -/* from ruby 1.9 variable.c */ -struct global_entry { - struct global_variable *var; - ID id; -}; - -#define GetProcPtr(obj, ptr) \ - GetCoreDataFromValue(obj, rb_proc_t, ptr) - -typedef struct { - rb_block_t block; - - VALUE envval; /* for GC mark */ - VALUE blockprocval; - int safe_level; - int is_lambda; - - NODE *special_cref_stack; -} rb_proc_t; - -#define GetEnvPtr(obj, ptr) \ - GetCoreDataFromValue(obj, rb_env_t, ptr) - -typedef struct { - VALUE *env; - int env_size; - int local_size; - VALUE prev_envval; /* for GC mark */ - rb_block_t block; -} rb_env_t; - -#define GetBindingPtr(obj, ptr) \ - GetCoreDataFromValue(obj, rb_binding_t, ptr) - -typedef struct { - VALUE env; - NODE *cref_stack; -} rb_binding_t; - - -/* used by compile time and send insn */ -#define VM_CALL_ARGS_SPLAT_BIT (0x01 << 1) -#define VM_CALL_ARGS_BLOCKARG_BIT (0x01 << 2) -#define VM_CALL_FCALL_BIT (0x01 << 3) -#define VM_CALL_VCALL_BIT (0x01 << 4) -#define VM_CALL_TAILCALL_BIT (0x01 << 5) -#define VM_CALL_TAILRECURSION_BIT (0x01 << 6) -#define VM_CALL_SUPER_BIT (0x01 << 7) -#define VM_CALL_SEND_BIT (0x01 << 8) - -/* inline (method|const) cache */ -#define NEW_INLINE_CACHE_ENTRY() NEW_WHILE(Qundef, 0, 0) -#define ic_klass u1.value -#define ic_method u2.node -#define ic_value u2.value -#define ic_vmstat u3.cnt -typedef NODE *IC; - -void rb_vm_change_state(void); - -typedef VALUE CDHASH; - -#ifndef FUNC_FASTCALL -#define FUNC_FASTCALL(x) x -#endif - -typedef rb_control_frame_t * - (FUNC_FASTCALL(*rb_insn_func_t))(rb_thread_t *, rb_control_frame_t *); - -#define GC_GUARDED_PTR(p) ((VALUE)((VALUE)(p) | 0x01)) -#define GC_GUARDED_PTR_REF(p) ((void *)(((VALUE)p) & ~0x03)) -#define GC_GUARDED_PTR_P(p) (((VALUE)p) & 0x01) - -#define RUBY_VM_METHOD_NODE NODE_METHOD - -#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp) (cfp+1) -#define RUBY_VM_NEXT_CONTROL_FRAME(cfp) (cfp-1) -#define RUBY_VM_END_CONTROL_FRAME(th) \ - ((rb_control_frame_t *)((th)->stack + (th)->stack_size)) -#define RUBY_VM_VALID_CONTROL_FRAME_P(cfp, ecfp) \ - ((void *)(ecfp) > (void *)(cfp)) -#define RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp) \ - (!RUBY_VM_VALID_CONTROL_FRAME_P((cfp), RUBY_VM_END_CONTROL_FRAME(th))) - -#define RUBY_VM_IFUNC_P(ptr) (BUILTIN_TYPE(ptr) == T_NODE) -#define RUBY_VM_NORMAL_ISEQ_P(ptr) \ - (ptr && !RUBY_VM_IFUNC_P(ptr)) - -#define RUBY_VM_CLASS_SPECIAL_P(ptr) (((VALUE)(ptr)) & 0x02) - -#define RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp) ((rb_block_t *)(&(cfp)->self)) -#define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b) \ - ((rb_control_frame_t *)((VALUE *)(b) - 5)) - - -/* defined? */ -#define DEFINED_IVAR INT2FIX(1) -#define DEFINED_IVAR2 INT2FIX(2) -#define DEFINED_GVAR INT2FIX(3) -#define DEFINED_CVAR INT2FIX(4) -#define DEFINED_CONST INT2FIX(5) -#define DEFINED_METHOD INT2FIX(6) -#define DEFINED_YIELD INT2FIX(7) -#define DEFINED_REF INT2FIX(8) -#define DEFINED_ZSUPER INT2FIX(9) -#define DEFINED_FUNC INT2FIX(10) - - -/* VM related object allocate functions */ -/* TODO: should be static functions */ -VALUE rb_thread_alloc(VALUE klass); -VALUE rb_proc_alloc(void); - -/* for debug */ -extern void vm_stack_dump_raw(rb_thread_t *, rb_control_frame_t *); -#define SDR() vm_stack_dump_raw(GET_THREAD(), GET_THREAD()->cfp) -#define SDR2(cfp) vm_stack_dump_raw(GET_THREAD(), (cfp)) -void yarv_bug(void); - - -/* functions about thread/vm execution */ - -VALUE rb_thread_eval(rb_thread_t *th, VALUE iseqval); -void rb_enable_interrupt(void); -void rb_disable_interrupt(void); -int rb_thread_method_id_and_klass(rb_thread_t *th, ID *idp, VALUE *klassp); - -VALUE vm_eval_body(rb_thread_t *th); -VALUE vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, int argc, VALUE *argv); -VALUE vm_make_proc(rb_thread_t *th, rb_control_frame_t *cfp, rb_block_t *block); -VALUE vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp); -VALUE vm_backtrace(rb_thread_t *, int); - -VALUE vm_yield(rb_thread_t *th, int argc, VALUE *argv); -VALUE vm_call0(rb_thread_t *th, VALUE klass, VALUE recv, - VALUE id, ID oid, int argc, const VALUE *argv, - NODE * body, int nosuper); - -int vm_get_sourceline(rb_control_frame_t *); - -VALUE yarvcore_eval_parsed(NODE *node, VALUE file); -VALUE yarvcore_eval(VALUE self, VALUE str, VALUE file, VALUE line); - -RUBY_EXTERN VALUE sysstack_error; - -/* for thread */ - -#if RUBY_VM_THREAD_MODEL == 2 -extern rb_thread_t *ruby_current_thread; -extern rb_vm_t *ruby_current_vm; - -#define GET_VM() ruby_current_vm -#define GET_THREAD() ruby_current_thread -#define rb_thread_set_current_raw(th) (ruby_current_thread = th) -#define rb_thread_set_current(th) do { \ - rb_thread_set_current_raw(th); \ - th->vm->running_thread = th; \ -} while (0) - -#else -#error "unsupported thread model" -#endif - -void rb_thread_execute_interrupts(rb_thread_t *); - -#define RUBY_VM_CHECK_INTS_TH(th) do { \ - if(th->interrupt_flag){ \ - /* TODO: trap something event */ \ - rb_thread_execute_interrupts(th); \ - } \ -} while (0) - -#define RUBY_VM_CHECK_INTS() \ - RUBY_VM_CHECK_INTS_TH(GET_THREAD()) - -/* tracer */ -static void inline -exec_event_hooks(rb_event_hook_t *hook, rb_event_flag_t flag, VALUE self, ID id, VALUE klass) -{ - while (hook) { - if (flag & hook->flag) { - (*hook->func)(flag, hook->data, self, id, klass); - } - hook = hook->next; - } -} - -#define EXEC_EVENT_HOOK(th, flag, self, id, klass) do { \ - rb_event_flag_t wait_event__ = th->event_flags; \ - if (UNLIKELY(wait_event__)) { \ - if (wait_event__ & (flag | RUBY_EVENT_VM)) { \ - VALUE self__ = (self), klass__ = (klass); \ - ID id__ = (id); \ - if (wait_event__ & flag) { \ - exec_event_hooks(th->event_hooks, flag, self__, id__, klass__); \ - } \ - if (wait_event__ & RUBY_EVENT_VM) { \ - exec_event_hooks(th->vm->event_hooks, flag, self__, id__, klass__); \ - } \ - } \ - } \ -} while (0) - -#endif /* _YARVCORE_H_INCLUDED_ */ -- cgit v1.2.3