Created
December 27, 2009 04:48
-
-
Save methodmissing/264160 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/configure.in b/configure.in | |
| index ac63760..0211b14 100644 | |
| --- a/configure.in | |
| +++ b/configure.in | |
| @@ -669,6 +669,24 @@ if test "$use_setreuid" = yes; then | |
| AC_DEFINE(USE_SETREUID) | |
| AC_DEFINE(USE_SETREGID) | |
| fi | |
| + | |
| +AC_ARG_ENABLE(threaded-dispatch, | |
| + [ --enable-threaded-dispatch use threaded dispatch for rb_eval], | |
| + [use_threaded_dispatch=$enableval]) | |
| +if test "$use_threaded_dispatch" = yes; then | |
| + AC_DEFINE(USE_THREADED_DISPATCH) | |
| + XCFLAGS="$XCFLAGS -03 -fno-strict-aliasing -fwrapv -fno-reorder-blocks -fomit-frame-pointer" | |
| +fi | |
| + | |
| +AC_ARG_ENABLE(repl-switch-dispatch, | |
| + [ --enable-repl-switch-dispatch use repl switch dispatch for rb_eval], | |
| + [use_repl_switch_dispatch=$enableval]) | |
| +if test "$use_repl_switch_dispatch" = yes; then | |
| + AC_DEFINE(USE_THREADED_DISPATCH) | |
| + AC_DEFINE(USE_REPL_SWITCH_DISPATCH) | |
| + XCFLAGS="$XCFLAGS -03 -fno-strict-aliasing -fwrapv -fno-reorder-blocks -fomit-frame-pointer" | |
| +fi | |
| + | |
| AC_STRUCT_TIMEZONE | |
| AC_CACHE_CHECK(for struct tm.tm_gmtoff, rb_cv_member_struct_tm_tm_gmtoff, | |
| [AC_TRY_COMPILE([#include <time.h>], | |
| diff --git a/eval.c b/eval.c | |
| index 6c6b4c1..b1ed630 100644 | |
| --- a/eval.c | |
| +++ b/eval.c | |
| @@ -3838,6 +3838,256 @@ eval_cdecl(self, node, result) | |
| rb_const_set(ruby_cbase, node->nd_vid, result); | |
| } | |
| +#if (defined(__GNUC__) || defined (__SUNPRO_C)) && defined(USE_THREADED_DISPATCH) | |
| +#define THREADED_DISPATCH | |
| +#endif | |
| + | |
| +#ifdef THREADED_DISPATCH | |
| +#ifdef USE_REPL_SWITCH_DISPATCH | |
| +#define DISPATCH_TABLE {{ | |
| +#define NEXT_NODE do { \ | |
| + CHECK_INTS; \ | |
| + result = Qnil; \ | |
| + if (!node) return result; \ | |
| + ruby_current_node = node; \ | |
| + switch(nd_type(node)) { \ | |
| + case NODE_SCOPE: goto TARGET_NODE_SCOPE; \ | |
| + case NODE_BLOCK: goto TARGET_NODE_BLOCK; \ | |
| + case NODE_IF: goto TARGET_NODE_IF; \ | |
| + case NODE_CASE: goto TARGET_NODE_CASE; \ | |
| + case NODE_WHEN: goto TARGET_NODE_WHEN; \ | |
| + case NODE_OPT_N: goto TARGET_NODE_OPT_N; \ | |
| + case NODE_WHILE: goto TARGET_NODE_WHILE; \ | |
| + case NODE_UNTIL: goto TARGET_NODE_UNTIL; \ | |
| + case NODE_ITER: goto TARGET_NODE_ITER; \ | |
| + case NODE_FOR: goto TARGET_NODE_ITER; \ | |
| + case NODE_BREAK: goto TARGET_NODE_BREAK; \ | |
| + case NODE_NEXT: goto TARGET_NODE_NEXT; \ | |
| + case NODE_REDO: goto TARGET_NODE_REDO; \ | |
| + case NODE_RETRY: goto TARGET_NODE_RETRY; \ | |
| + case NODE_RESCUE: goto TARGET_NODE_RESCUE; \ | |
| + case NODE_ENSURE: goto TARGET_NODE_ENSURE; \ | |
| + case NODE_AND: goto TARGET_NODE_AND; \ | |
| + case NODE_OR: goto TARGET_NODE_OR; \ | |
| + case NODE_NOT: goto TARGET_NODE_NOT; \ | |
| + case NODE_MASGN: goto TARGET_NODE_MASGN; \ | |
| + case NODE_LASGN: goto TARGET_NODE_LASGN; \ | |
| + case NODE_DASGN: goto TARGET_NODE_DASGN; \ | |
| + case NODE_DASGN_CURR: goto TARGET_NODE_DASGN_CURR; \ | |
| + case NODE_GASGN: goto TARGET_NODE_GASGN; \ | |
| + case NODE_IASGN: goto TARGET_NODE_IASGN; \ | |
| + case NODE_CDECL: goto TARGET_NODE_CDECL; \ | |
| + case NODE_CVASGN: goto TARGET_NODE_CVASGN; \ | |
| + case NODE_CVDECL: goto TARGET_NODE_CVDECL; \ | |
| + case NODE_OP_ASGN1: goto TARGET_NODE_OP_ASGN1; \ | |
| + case NODE_OP_ASGN2: goto TARGET_NODE_OP_ASGN2; \ | |
| + case NODE_OP_ASGN_AND: goto TARGET_NODE_OP_ASGN_AND; \ | |
| + case NODE_OP_ASGN_OR: goto TARGET_NODE_OP_ASGN_OR; \ | |
| + case NODE_CALL: goto TARGET_NODE_CALL; \ | |
| + case NODE_FCALL: goto TARGET_NODE_FCALL; \ | |
| + case NODE_VCALL: goto TARGET_NODE_VCALL; \ | |
| + case NODE_SUPER: goto TARGET_NODE_SUPER; \ | |
| + case NODE_ZSUPER: goto TARGET_NODE_SUPER; \ | |
| + case NODE_ARRAY: goto TARGET_NODE_ARRAY; \ | |
| + case NODE_ZARRAY: goto TARGET_NODE_ZARRAY; \ | |
| + case NODE_HASH: goto TARGET_NODE_HASH; \ | |
| + case NODE_RETURN: goto TARGET_NODE_RETURN; \ | |
| + case NODE_YIELD: goto TARGET_NODE_YIELD; \ | |
| + case NODE_LVAR: goto TARGET_NODE_LVAR; \ | |
| + case NODE_DVAR: goto TARGET_NODE_DVAR; \ | |
| + case NODE_GVAR: goto TARGET_NODE_GVAR; \ | |
| + case NODE_IVAR: goto TARGET_NODE_IVAR; \ | |
| + case NODE_CONST: goto TARGET_NODE_CONST; \ | |
| + case NODE_CVAR: goto TARGET_NODE_CVAR; \ | |
| + case NODE_NTH_REF: goto TARGET_NODE_NTH_REF; \ | |
| + case NODE_BACK_REF: goto TARGET_NODE_BACK_REF; \ | |
| + case NODE_MATCH: goto TARGET_NODE_MATCH; \ | |
| + case NODE_MATCH2: goto TARGET_NODE_MATCH2; \ | |
| + case NODE_MATCH3: goto TARGET_NODE_MATCH3; \ | |
| + case NODE_LIT: goto TARGET_NODE_LIT; \ | |
| + case NODE_STR: goto TARGET_NODE_STR; \ | |
| + case NODE_DSTR: goto TARGET_NODE_DSTR; \ | |
| + case NODE_XSTR: goto TARGET_NODE_XSTR; \ | |
| + case NODE_DXSTR: goto TARGET_NODE_DSTR; \ | |
| + case NODE_EVSTR: goto TARGET_NODE_EVSTR; \ | |
| + case NODE_DREGX: goto TARGET_NODE_DSTR; \ | |
| + case NODE_DREGX_ONCE: goto TARGET_NODE_DSTR; \ | |
| + case NODE_ARGSCAT: goto TARGET_NODE_ARGSCAT; \ | |
| + case NODE_ARGSPUSH: goto TARGET_NODE_ARGSPUSH; \ | |
| + case NODE_SPLAT: goto TARGET_NODE_SPLAT; \ | |
| + case NODE_TO_ARY: goto TARGET_NODE_TO_ARY; \ | |
| + case NODE_SVALUE: goto TARGET_NODE_SVALUE; \ | |
| + case NODE_BLOCK_ARG: goto TARGET_NODE_BLOCK_ARG; \ | |
| + case NODE_BLOCK_PASS: goto TARGET_NODE_BLOCK_PASS; \ | |
| + case NODE_DEFN: goto TARGET_NODE_DEFN; \ | |
| + case NODE_DEFS: goto TARGET_NODE_DEFS; \ | |
| + case NODE_ALIAS: goto TARGET_NODE_ALIAS; \ | |
| + case NODE_VALIAS: goto TARGET_NODE_VALIAS; \ | |
| + case NODE_UNDEF: goto TARGET_NODE_UNDEF; \ | |
| + case NODE_CLASS: goto TARGET_NODE_CLASS; \ | |
| + case NODE_MODULE: goto TARGET_NODE_MODULE; \ | |
| + case NODE_SCLASS: goto TARGET_NODE_SCLASS; \ | |
| + case NODE_COLON2: goto TARGET_NODE_COLON2; \ | |
| + case NODE_COLON3: goto TARGET_NODE_COLON3; \ | |
| + case NODE_DOT2: goto TARGET_NODE_DOT2; \ | |
| + case NODE_DOT3: goto TARGET_NODE_DOT2; \ | |
| + case NODE_FLIP2: goto TARGET_NODE_FLIP2; \ | |
| + case NODE_FLIP3: goto TARGET_NODE_FLIP3; \ | |
| + case NODE_SELF: goto TARGET_NODE_SELF; \ | |
| + case NODE_NIL: goto TARGET_NODE_NIL; \ | |
| + case NODE_TRUE: goto TARGET_NODE_TRUE; \ | |
| + case NODE_FALSE: goto TARGET_NODE_FALSE; \ | |
| + case NODE_DEFINED: goto TARGET_NODE_DEFINED; \ | |
| + case NODE_NEWLINE: goto TARGET_NODE_NEWLINE; \ | |
| + case NODE_POSTEXE: goto TARGET_NODE_POSTEXE; \ | |
| + case NODE_DSYM: goto TARGET_NODE_DSTR; \ | |
| + case NODE_ATTRASGN: goto TARGET_NODE_ATTRASGN; \ | |
| + default: unknown_node(node); \ | |
| + } \ | |
| +} while(0) | |
| +#else | |
| +#define DISPATCH_TABLE \ | |
| +static const void *dispatch_table[104] = { \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_NODE_SCOPE, \ | |
| + &&TARGET_NODE_BLOCK, \ | |
| + &&TARGET_NODE_IF, \ | |
| + &&TARGET_NODE_CASE, \ | |
| + &&TARGET_NODE_WHEN, \ | |
| + &&TARGET_NODE_OPT_N, \ | |
| + &&TARGET_NODE_WHILE, \ | |
| + &&TARGET_NODE_UNTIL, \ | |
| + &&TARGET_NODE_ITER, \ | |
| + &&TARGET_NODE_ITER, \ | |
| + &&TARGET_NODE_BREAK, \ | |
| + &&TARGET_NODE_NEXT, \ | |
| + &&TARGET_NODE_REDO, \ | |
| + &&TARGET_NODE_RETRY, \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_NODE_RESCUE, \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_NODE_ENSURE, \ | |
| + &&TARGET_NODE_AND, \ | |
| + &&TARGET_NODE_OR, \ | |
| + &&TARGET_NODE_NOT, \ | |
| + &&TARGET_NODE_MASGN, \ | |
| + &&TARGET_NODE_LASGN, \ | |
| + &&TARGET_NODE_DASGN, \ | |
| + &&TARGET_NODE_DASGN_CURR, \ | |
| + &&TARGET_NODE_GASGN, \ | |
| + &&TARGET_NODE_IASGN, \ | |
| + &&TARGET_NODE_CDECL, \ | |
| + &&TARGET_NODE_CVASGN, \ | |
| + &&TARGET_NODE_CVDECL, \ | |
| + &&TARGET_NODE_OP_ASGN1, \ | |
| + &&TARGET_NODE_OP_ASGN2, \ | |
| + &&TARGET_NODE_OP_ASGN_AND, \ | |
| + &&TARGET_NODE_OP_ASGN_OR, \ | |
| + &&TARGET_NODE_CALL, \ | |
| + &&TARGET_NODE_FCALL, \ | |
| + &&TARGET_NODE_VCALL, \ | |
| + &&TARGET_NODE_SUPER, \ | |
| + &&TARGET_NODE_SUPER, \ | |
| + &&TARGET_NODE_ARRAY, \ | |
| + &&TARGET_NODE_ZARRAY, \ | |
| + &&TARGET_NODE_HASH, \ | |
| + &&TARGET_NODE_RETURN, \ | |
| + &&TARGET_NODE_YIELD, \ | |
| + &&TARGET_NODE_LVAR, \ | |
| + &&TARGET_NODE_DVAR, \ | |
| + &&TARGET_NODE_GVAR, \ | |
| + &&TARGET_NODE_IVAR, \ | |
| + &&TARGET_NODE_CONST, \ | |
| + &&TARGET_NODE_CVAR, \ | |
| + &&TARGET_NODE_NTH_REF, \ | |
| + &&TARGET_NODE_BACK_REF, \ | |
| + &&TARGET_NODE_MATCH, \ | |
| + &&TARGET_NODE_MATCH2, \ | |
| + &&TARGET_NODE_MATCH3, \ | |
| + &&TARGET_NODE_LIT, \ | |
| + &&TARGET_NODE_STR, \ | |
| + &&TARGET_NODE_DSTR, \ | |
| + &&TARGET_NODE_XSTR, \ | |
| + &&TARGET_NODE_DSTR, \ | |
| + &&TARGET_NODE_EVSTR, \ | |
| + &&TARGET_NODE_DSTR, \ | |
| + &&TARGET_NODE_DSTR, \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_NODE_ARGSCAT, \ | |
| + &&TARGET_NODE_ARGSPUSH, \ | |
| + &&TARGET_NODE_SPLAT, \ | |
| + &&TARGET_NODE_TO_ARY, \ | |
| + &&TARGET_NODE_SVALUE, \ | |
| + &&TARGET_NODE_BLOCK_ARG, \ | |
| + &&TARGET_NODE_BLOCK_PASS, \ | |
| + &&TARGET_NODE_DEFN, \ | |
| + &&TARGET_NODE_DEFS, \ | |
| + &&TARGET_NODE_ALIAS, \ | |
| + &&TARGET_NODE_VALIAS, \ | |
| + &&TARGET_NODE_UNDEF, \ | |
| + &&TARGET_NODE_CLASS, \ | |
| + &&TARGET_NODE_MODULE, \ | |
| + &&TARGET_NODE_SCLASS, \ | |
| + &&TARGET_NODE_COLON2, \ | |
| + &&TARGET_NODE_COLON3, \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_NODE_DOT2, \ | |
| + &&TARGET_NODE_DOT2, \ | |
| + &&TARGET_NODE_FLIP2, \ | |
| + &&TARGET_NODE_FLIP3, \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_NODE_SELF, \ | |
| + &&TARGET_NODE_NIL, \ | |
| + &&TARGET_NODE_TRUE, \ | |
| + &&TARGET_NODE_FALSE, \ | |
| + &&TARGET_NODE_DEFINED, \ | |
| + &&TARGET_NODE_NEWLINE, \ | |
| + &&TARGET_NODE_POSTEXE, \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_UNDEF, \ | |
| + &&TARGET_NODE_DSTR, \ | |
| + &&TARGET_NODE_ATTRASGN \ | |
| +}; \ | |
| +{{ | |
| +#define NEXT_NODE do { \ | |
| + CHECK_INTS; \ | |
| + result = Qnil; \ | |
| + if (!node) return result; \ | |
| + ruby_current_node = node; \ | |
| + goto *dispatch_table[nd_type(node)]; \ | |
| +} while (0) | |
| +#endif | |
| +#define DISPATCH_BEGIN NEXT_NODE; | |
| +#define TARGET(node) TARGET_##node: \ | |
| + asm("#" #node); | |
| +#define TARGET_ALIAS(node) | |
| +#define BREAK return result; | |
| +#define DEFAULT_NODE TARGET_UNDEF: \ | |
| + unknown_node(node); | |
| +#define DISPATCH_END }} | |
| +#else | |
| +#define DISPATCH_TABLE | |
| +#define DISPATCH_BEGIN \ | |
| + again: \ | |
| + CHECK_INTS; \ | |
| + result = Qnil; \ | |
| + if (node) { \ | |
| + ruby_current_node = node; \ | |
| + switch (nd_type(node)) { | |
| +#define NEXT_NODE goto again; | |
| +#define TARGET(node) case (node): | |
| +#define TARGET_ALIAS(node) case (node): | |
| +#define BREAK return result; | |
| +#define DEFAULT_NODE \ | |
| + default: \ | |
| + unknown_node(node); | |
| +#define DISPATCH_END }} | |
| +#endif | |
| static VALUE | |
| rb_eval(self, node) | |
| @@ -3845,67 +4095,63 @@ rb_eval(self, node) | |
| NODE * node; | |
| { | |
| VALUE result; | |
| - | |
| -again: | |
| - CHECK_INTS; | |
| - result = Qnil; | |
| - if (node) { | |
| - ruby_current_node = node; | |
| - switch (nd_type(node)) { | |
| - case NODE_BLOCK: | |
| + DISPATCH_TABLE; | |
| + DISPATCH_BEGIN; | |
| + | |
| + TARGET(NODE_BLOCK); | |
| while (node->nd_next) { | |
| rb_eval(self, node->nd_head); | |
| node = node->nd_next; | |
| } | |
| node = node->nd_head; | |
| - goto again; | |
| + NEXT_NODE; | |
| - case NODE_POSTEXE: | |
| + TARGET(NODE_POSTEXE); | |
| rb_f_END(); | |
| nd_set_type(node, NODE_NIL); /* exec just once */ | |
| - break; | |
| + BREAK; | |
| /* begin .. end without clauses */ | |
| - case NODE_BEGIN: | |
| + TARGET(NODE_BEGIN); | |
| node = node->nd_body; | |
| - goto again; | |
| + NEXT_NODE; | |
| /* nodes for speed-up(default match) */ | |
| - case NODE_MATCH: | |
| + TARGET(NODE_MATCH); | |
| result = rb_reg_match2(node->nd_lit); | |
| - break; | |
| + BREAK; | |
| /* nodes for speed-up(literal match) */ | |
| - case NODE_MATCH2: | |
| + TARGET(NODE_MATCH2); | |
| result = eval_match2(self, node); | |
| - break; | |
| + BREAK; | |
| /* nodes for speed-up(literal match) */ | |
| - case NODE_MATCH3: | |
| + TARGET(NODE_MATCH3); | |
| result = eval_match3(self,node); | |
| - break; | |
| + BREAK; | |
| /* node for speed-up(top-level loop for -n/-p) */ | |
| - case NODE_OPT_N: | |
| + TARGET(NODE_OPT_N); | |
| eval_opt_n(self, node); | |
| - break; | |
| + BREAK; | |
| - case NODE_SELF: | |
| + TARGET(NODE_SELF); | |
| result = self; | |
| - break; | |
| + BREAK; | |
| - case NODE_NIL: | |
| - break; | |
| + TARGET(NODE_NIL); | |
| + BREAK; | |
| - case NODE_TRUE: | |
| + TARGET(NODE_TRUE); | |
| result = Qtrue; | |
| - break; | |
| + BREAK; | |
| - case NODE_FALSE: | |
| + TARGET(NODE_FALSE); | |
| result = Qfalse; | |
| - break; | |
| + BREAK; | |
| - case NODE_IF: | |
| + TARGET(NODE_IF); | |
| if (RTEST(rb_eval(self, node->nd_cond))) { | |
| EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self, | |
| ruby_frame->last_func, | |
| @@ -3918,63 +4164,63 @@ again: | |
| ruby_frame->last_class); | |
| node = node->nd_else; | |
| } | |
| - goto again; | |
| + NEXT_NODE; | |
| - case NODE_WHEN: | |
| - if (node = eval_when(self, node)) goto again; | |
| - break; | |
| + TARGET(NODE_WHEN); | |
| + if (node = eval_when(self, node)) NEXT_NODE; | |
| + BREAK; | |
| - case NODE_CASE: | |
| - if (node = eval_case(self, node)) goto again; | |
| - break; | |
| + TARGET(NODE_CASE); | |
| + if (node = eval_case(self, node)) NEXT_NODE; | |
| + BREAK; | |
| - case NODE_WHILE: | |
| + TARGET(NODE_WHILE); | |
| result = eval_while(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_UNTIL: | |
| + TARGET(NODE_UNTIL); | |
| result = eval_until(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_BLOCK_PASS: | |
| + TARGET(NODE_BLOCK_PASS); | |
| result = block_pass(self, node); | |
| - break; | |
| + BREAK; | |
| - case NODE_ITER: | |
| - case NODE_FOR: | |
| + TARGET_ALIAS(NODE_FOR); | |
| + TARGET(NODE_ITER); | |
| result = eval_iter(self, node); | |
| - break; | |
| + BREAK; | |
| - case NODE_BREAK: | |
| + TARGET(NODE_BREAK); | |
| break_jump(rb_eval(self, node->nd_stts)); | |
| - break; | |
| + BREAK; | |
| - case NODE_NEXT: | |
| + TARGET(NODE_NEXT); | |
| next_jump(rb_eval(self, node->nd_stts)); | |
| - break; | |
| + BREAK; | |
| - case NODE_REDO: | |
| + TARGET(NODE_REDO); | |
| JUMP_TAG(TAG_REDO); | |
| - break; | |
| + BREAK; | |
| - case NODE_RETRY: | |
| + TARGET(NODE_RETRY); | |
| JUMP_TAG(TAG_RETRY); | |
| - break; | |
| + BREAK; | |
| - case NODE_SPLAT: | |
| + TARGET(NODE_SPLAT); | |
| result = splat_value(rb_eval(self, node->nd_head)); | |
| - break; | |
| + BREAK; | |
| - case NODE_TO_ARY: | |
| + TARGET(NODE_TO_ARY); | |
| result = rb_ary_to_ary(rb_eval(self, node->nd_head)); | |
| - break; | |
| + BREAK; | |
| - case NODE_SVALUE: | |
| + TARGET(NODE_SVALUE); | |
| result = avalue_splat(rb_eval(self, node->nd_head)); | |
| if (result == Qundef) result = Qnil; | |
| - break; | |
| + BREAK; | |
| - case NODE_YIELD: | |
| + TARGET(NODE_YIELD); | |
| if (node->nd_head) { | |
| result = rb_eval(self, node->nd_head); | |
| ruby_current_node = node; | |
| @@ -3984,188 +4230,188 @@ again: | |
| } | |
| SET_CURRENT_SOURCE(); | |
| result = rb_yield_0(result, 0, 0, 0, node->nd_state); | |
| - break; | |
| + BREAK; | |
| - case NODE_RESCUE: | |
| + TARGET(NODE_RESCUE); | |
| result = eval_rescue(self,node); | |
| if (result == Qundef) { /* handle else clause w/o recursion */ | |
| node = node->nd_else; | |
| - goto again; | |
| + NEXT_NODE; | |
| } | |
| - break; | |
| + BREAK; | |
| - case NODE_ENSURE: | |
| + TARGET(NODE_ENSURE); | |
| result = eval_ensure(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_AND: | |
| + TARGET(NODE_AND); | |
| result = rb_eval(self, node->nd_1st); | |
| - if (!RTEST(result)) break; | |
| + if (!RTEST(result)) BREAK; | |
| node = node->nd_2nd; | |
| - goto again; | |
| + NEXT_NODE; | |
| - case NODE_OR: | |
| + TARGET(NODE_OR); | |
| result = rb_eval(self, node->nd_1st); | |
| - if (RTEST(result)) break; | |
| + if (RTEST(result)) BREAK; | |
| node = node->nd_2nd; | |
| - goto again; | |
| + NEXT_NODE; | |
| - case NODE_NOT: | |
| + TARGET(NODE_NOT) | |
| result = RTEST(rb_eval(self, node->nd_body)) ? Qfalse : Qtrue; | |
| - break; | |
| + BREAK; | |
| - case NODE_DOT2: | |
| - case NODE_DOT3: | |
| + TARGET_ALIAS(NODE_DOT3); | |
| + TARGET(NODE_DOT2); | |
| result = eval_dot(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_FLIP2: /* like AWK */ | |
| + TARGET(NODE_FLIP2); /* like AWK */ | |
| result = eval_flip2(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_FLIP3: /* like SED */ | |
| + TARGET(NODE_FLIP3); /* like SED */ | |
| result = eval_flip3(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_RETURN: | |
| + TARGET(NODE_RETURN); | |
| return_jump(rb_eval(self, node->nd_stts)); | |
| - break; | |
| + BREAK; | |
| - case NODE_ARGSCAT: | |
| + TARGET(NODE_ARGSCAT); | |
| result = rb_eval(self, node->nd_head); | |
| result = rb_ary_concat(result, splat_value(rb_eval(self, node->nd_body))); | |
| - break; | |
| + BREAK; | |
| - case NODE_ARGSPUSH: | |
| + TARGET(NODE_ARGSPUSH); | |
| result = rb_ary_dup(rb_eval(self, node->nd_head)); | |
| result = rb_ary_push(result, rb_eval(self, node->nd_body)); | |
| - break; | |
| + BREAK; | |
| - case NODE_ATTRASGN: | |
| + TARGET(NODE_ATTRASGN); | |
| result = eval_attrasgn(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_CALL: | |
| + TARGET(NODE_CALL); | |
| result = eval_call(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_FCALL: | |
| + TARGET(NODE_FCALL); | |
| result = eval_fcall(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_VCALL: | |
| + TARGET(NODE_VCALL); | |
| SET_CURRENT_SOURCE(); | |
| result = rb_call(CLASS_OF(self),self,node->nd_mid,0,0,2,self); | |
| - break; | |
| + BREAK; | |
| - case NODE_SUPER: | |
| - case NODE_ZSUPER: | |
| + TARGET_ALIAS(NODE_ZSUPER); | |
| + TARGET(NODE_SUPER); | |
| result = eval_super(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_SCOPE: | |
| + TARGET(NODE_SCOPE); | |
| result = eval_scope(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_OP_ASGN1: | |
| + TARGET(NODE_OP_ASGN1); | |
| result = eval_op_asgn1(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_OP_ASGN2: | |
| + TARGET(NODE_OP_ASGN2); | |
| result = eval_op_asgn2(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_OP_ASGN_AND: | |
| + TARGET(NODE_OP_ASGN_AND); | |
| result = rb_eval(self, node->nd_head); | |
| - if (!RTEST(result)) break; | |
| + if (!RTEST(result)) BREAK; | |
| node = node->nd_value; | |
| - goto again; | |
| + NEXT_NODE; | |
| - case NODE_OP_ASGN_OR: | |
| + TARGET(NODE_OP_ASGN_OR); | |
| if ((node->nd_aid && !is_defined(self, node->nd_head, 0)) || | |
| !RTEST(result = rb_eval(self, node->nd_head))) { | |
| node = node->nd_value; | |
| - goto again; | |
| + NEXT_NODE; | |
| } | |
| - break; | |
| + BREAK; | |
| - case NODE_MASGN: | |
| + TARGET(NODE_MASGN); | |
| result = massign(self, node, rb_eval(self, node->nd_value), 0); | |
| - break; | |
| + BREAK; | |
| - case NODE_LASGN: | |
| + TARGET(NODE_LASGN); | |
| if (ruby_scope->local_vars == 0) | |
| rb_bug("unexpected local variable assignment"); | |
| result = rb_eval(self, node->nd_value); | |
| ruby_scope->local_vars[node->nd_cnt] = result; | |
| - break; | |
| + BREAK; | |
| - case NODE_DASGN: | |
| + TARGET(NODE_DASGN); | |
| result = rb_eval(self, node->nd_value); | |
| dvar_asgn(node->nd_vid, result); | |
| - break; | |
| + BREAK; | |
| - case NODE_DASGN_CURR: | |
| + TARGET(NODE_DASGN_CURR); | |
| result = rb_eval(self, node->nd_value); | |
| dvar_asgn_curr(node->nd_vid, result); | |
| - break; | |
| + BREAK; | |
| - case NODE_GASGN: | |
| + TARGET(NODE_GASGN); | |
| result = rb_eval(self, node->nd_value); | |
| rb_gvar_set(node->nd_entry, result); | |
| - break; | |
| + BREAK; | |
| - case NODE_IASGN: | |
| + TARGET(NODE_IASGN); | |
| result = rb_eval(self, node->nd_value); | |
| rb_ivar_set(self, node->nd_vid, result); | |
| - break; | |
| + BREAK; | |
| - case NODE_CDECL: | |
| + TARGET(NODE_CDECL); | |
| result = rb_eval(self, node->nd_value); | |
| eval_cdecl(self, node, result); | |
| - break; | |
| + BREAK; | |
| - case NODE_CVDECL: | |
| + TARGET(NODE_CVDECL); | |
| if (NIL_P(ruby_cbase)) { | |
| rb_raise(rb_eTypeError, "no class/module to define class variable"); | |
| } | |
| result = rb_eval(self, node->nd_value); | |
| eval_cvar_set(node, result, Qtrue); | |
| - break; | |
| + BREAK; | |
| - case NODE_CVASGN: | |
| + TARGET(NODE_CVASGN); | |
| result = rb_eval(self, node->nd_value); | |
| eval_cvar_set(node, result, Qfalse); | |
| - break; | |
| + BREAK; | |
| - case NODE_LVAR: | |
| + TARGET(NODE_LVAR); | |
| if (ruby_scope->local_vars == 0) { | |
| rb_bug("unexpected local variable"); | |
| } | |
| result = ruby_scope->local_vars[node->nd_cnt]; | |
| - break; | |
| + BREAK; | |
| - case NODE_DVAR: | |
| + TARGET(NODE_DVAR); | |
| result = rb_dvar_ref(node->nd_vid); | |
| - break; | |
| + BREAK; | |
| - case NODE_GVAR: | |
| + TARGET(NODE_GVAR); | |
| result = rb_gvar_get(node->nd_entry); | |
| - break; | |
| + BREAK; | |
| - case NODE_IVAR: | |
| + TARGET(NODE_IVAR); | |
| result = rb_ivar_get(self, node->nd_vid); | |
| - break; | |
| + BREAK; | |
| - case NODE_CONST: | |
| + TARGET(NODE_CONST); | |
| result = ev_const_get(ruby_cref, node->nd_vid, self); | |
| - break; | |
| + BREAK; | |
| - case NODE_CVAR: | |
| + TARGET(NODE_CVAR); | |
| result = rb_cvar_get(cvar_cbase(), node->nd_vid); | |
| - break; | |
| + BREAK; | |
| - case NODE_BLOCK_ARG: | |
| + TARGET(NODE_BLOCK_ARG); | |
| if (ruby_scope->local_vars == 0) | |
| rb_bug("unexpected block argument"); | |
| if (rb_block_given_p()) { | |
| @@ -4175,9 +4421,9 @@ again: | |
| else { | |
| result = Qnil; | |
| } | |
| - break; | |
| + BREAK; | |
| - case NODE_COLON2: | |
| + TARGET(NODE_COLON2); | |
| result = rb_eval(self, node->nd_head); | |
| if (rb_is_const_id(node->nd_mid)) { | |
| switch (TYPE(result)) { | |
| @@ -4193,17 +4439,17 @@ again: | |
| } | |
| else | |
| result = rb_funcall(result, node->nd_mid, 0, 0); | |
| - break; | |
| + BREAK; | |
| - case NODE_COLON3: | |
| + TARGET(NODE_COLON3); | |
| result = rb_const_get_from(rb_cObject, node->nd_mid); | |
| - break; | |
| + BREAK; | |
| - case NODE_NTH_REF: | |
| + TARGET(NODE_NTH_REF); | |
| result = rb_reg_nth_match(node->nd_nth, MATCH_DATA); | |
| - break; | |
| + BREAK; | |
| - case NODE_BACK_REF: | |
| + TARGET(NODE_BACK_REF); | |
| switch (node->nd_nth) { | |
| case '&': | |
| result = rb_reg_last_match(MATCH_DATA); | |
| @@ -4220,101 +4466,99 @@ again: | |
| default: | |
| rb_bug("unexpected back-ref"); | |
| } | |
| - break; | |
| + BREAK; | |
| - case NODE_HASH: | |
| + TARGET(NODE_HASH); | |
| result = eval_hash(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_ZARRAY: /* zero length list */ | |
| + TARGET(NODE_ZARRAY); /* zero length list */ | |
| result = rb_ary_new(); | |
| - break; | |
| + BREAK; | |
| - case NODE_ARRAY: | |
| + TARGET(NODE_ARRAY); | |
| result = eval_array(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_STR: | |
| + TARGET(NODE_STR); | |
| result = rb_str_new3(node->nd_lit); | |
| - break; | |
| + BREAK; | |
| - case NODE_EVSTR: | |
| + TARGET(NODE_EVSTR); | |
| result = rb_obj_as_string(rb_eval(self, node->nd_body)); | |
| - break; | |
| + BREAK; | |
| - case NODE_DSTR: | |
| - case NODE_DXSTR: | |
| - case NODE_DREGX: | |
| - case NODE_DREGX_ONCE: | |
| - case NODE_DSYM: | |
| + TARGET_ALIAS(NODE_DXSTR); | |
| + TARGET_ALIAS(NODE_DREGX); | |
| + TARGET_ALIAS(NODE_DREGX_ONCE); | |
| + TARGET_ALIAS(NODE_DSYM); | |
| + TARGET(NODE_DSTR); | |
| result = eval_slit(self, node); | |
| - if (result == Qundef) goto again; | |
| - break; | |
| + if (result == Qundef) NEXT_NODE; | |
| + BREAK; | |
| - case NODE_XSTR: | |
| + TARGET(NODE_XSTR); | |
| result = rb_funcall(self, '`', 1, rb_str_new3(node->nd_lit)); | |
| - break; | |
| + BREAK; | |
| - case NODE_LIT: | |
| + TARGET(NODE_LIT); | |
| result = node->nd_lit; | |
| - break; | |
| + BREAK; | |
| - case NODE_DEFN: | |
| + TARGET(NODE_DEFN); | |
| if (node->nd_defn) | |
| eval_defn(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_DEFS: | |
| + TARGET(NODE_DEFS); | |
| if (node->nd_defn) | |
| eval_defs(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_UNDEF: | |
| + TARGET(NODE_UNDEF); | |
| if (NIL_P(ruby_class)) { | |
| rb_raise(rb_eTypeError, "no class to undef method"); | |
| } | |
| rb_undef(ruby_class, rb_to_id(rb_eval(self, node->u2.node))); | |
| - break; | |
| + BREAK; | |
| - case NODE_ALIAS: | |
| + TARGET(NODE_ALIAS); | |
| if (NIL_P(ruby_class)) { | |
| rb_raise(rb_eTypeError, "no class to make alias"); | |
| } | |
| rb_alias(ruby_class, rb_to_id(rb_eval(self, node->u1.node)), | |
| rb_to_id(rb_eval(self, node->u2.node))); | |
| - break; | |
| + BREAK; | |
| - case NODE_VALIAS: | |
| + TARGET(NODE_VALIAS); | |
| rb_alias_variable(node->u1.id, node->u2.id); | |
| - break; | |
| + BREAK; | |
| - case NODE_CLASS: | |
| + TARGET(NODE_CLASS); | |
| result = eval_class(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_MODULE: | |
| + TARGET(NODE_MODULE); | |
| result = eval_module(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_SCLASS: | |
| + TARGET(NODE_SCLASS); | |
| result = eval_sclass(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_DEFINED: | |
| + TARGET(NODE_DEFINED); | |
| result = eval_defined(self,node); | |
| - break; | |
| + BREAK; | |
| - case NODE_NEWLINE: | |
| + TARGET(NODE_NEWLINE); | |
| EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self, | |
| ruby_frame->last_func, | |
| ruby_frame->last_class); | |
| node = node->nd_next; | |
| - goto again; | |
| + NEXT_NODE; | |
| - default: | |
| - unknown_node(node); | |
| - } | |
| - } | |
| + DEFAULT_NODE; | |
| + DISPATCH_END; | |
| return result; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment