mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers vm.c Source File

vm.c

00001 /*
00002 ** vm.c - virtual machine for mruby
00003 **
00004 ** See Copyright Notice in mruby.h
00005 */
00006 
00007 #include <stddef.h>
00008 #include <stdarg.h>
00009 #include <math.h>
00010 #include "mruby.h"
00011 #include "mruby/array.h"
00012 #include "mruby/class.h"
00013 #include "mruby/hash.h"
00014 #include "mruby/irep.h"
00015 #include "mruby/numeric.h"
00016 #include "mruby/proc.h"
00017 #include "mruby/range.h"
00018 #include "mruby/string.h"
00019 #include "mruby/variable.h"
00020 #include "mruby/error.h"
00021 #include "mruby/opcode.h"
00022 #include "value_array.h"
00023 #include "mrb_throw.h"
00024 
00025 #ifndef ENABLE_STDIO
00026 #if defined(__cplusplus)
00027 extern "C" {
00028 #endif
00029 void abort(void);
00030 #if defined(__cplusplus)
00031 }  /* extern "C" { */
00032 #endif
00033 #endif
00034 
00035 #define STACK_INIT_SIZE 128
00036 #define CALLINFO_INIT_SIZE 32
00037 
00038 /* Define amount of linear stack growth. */
00039 #ifndef MRB_STACK_GROWTH
00040 #define MRB_STACK_GROWTH 128
00041 #endif
00042 
00043 /* Maximum stack depth. Should be set lower on memory constrained systems.
00044 The value below allows about 60000 recursive calls in the simplest case. */
00045 #ifndef MRB_STACK_MAX
00046 #define MRB_STACK_MAX (0x40000 - MRB_STACK_GROWTH)
00047 #endif
00048 
00049 #ifdef VM_DEBUG
00050 # define DEBUG(x) (x)
00051 #else
00052 # define DEBUG(x)
00053 #endif
00054 
00055 #define ARENA_RESTORE(mrb,ai) (mrb)->arena_idx = (ai)
00056 
00057 static inline void
00058 stack_clear(mrb_value *from, size_t count)
00059 {
00060 #ifndef MRB_NAN_BOXING
00061   const mrb_value mrb_value_zero = { { 0 } };
00062 
00063   while (count-- > 0) {
00064     *from++ = mrb_value_zero;
00065   }
00066 #else
00067   while (count-- > 0) {
00068     SET_NIL_VALUE(*from);
00069     from++;
00070   }
00071 #endif
00072 }
00073 
00074 static inline void
00075 stack_copy(mrb_value *dst, const mrb_value *src, size_t size)
00076 {
00077   while (size-- > 0) {
00078     *dst++ = *src++;
00079   }
00080 }
00081 
00082 static void
00083 stack_init(mrb_state *mrb)
00084 {
00085   struct mrb_context *c = mrb->c;
00086 
00087   /* mrb_assert(mrb->stack == NULL); */
00088   c->stbase = (mrb_value *)mrb_calloc(mrb, STACK_INIT_SIZE, sizeof(mrb_value));
00089   c->stend = c->stbase + STACK_INIT_SIZE;
00090   c->stack = c->stbase;
00091 
00092   /* mrb_assert(ci == NULL); */
00093   c->cibase = (mrb_callinfo *)mrb_calloc(mrb, CALLINFO_INIT_SIZE, sizeof(mrb_callinfo));
00094   c->ciend = c->cibase + CALLINFO_INIT_SIZE;
00095   c->ci = c->cibase;
00096   c->ci->target_class = mrb->object_class;
00097   c->ci->stackent = c->stack;
00098 }
00099 
00100 static inline void
00101 envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
00102 {
00103   mrb_callinfo *ci = mrb->c->cibase;
00104 
00105   if (newbase == oldbase) return;
00106   while (ci <= mrb->c->ci) {
00107     struct REnv *e = ci->env;
00108     if (e && MRB_ENV_STACK_SHARED_P(e)) {
00109       ptrdiff_t off = e->stack - oldbase;
00110 
00111       e->stack = newbase + off;
00112     }
00113     ci->stackent = newbase + (ci->stackent - oldbase);
00114     ci++;
00115   }
00116 }
00117 
00118 static inline void
00119 init_new_stack_space(mrb_state *mrb, int room, int keep)
00120 {
00121   if (room > keep) {
00122     /* do not leave uninitialized malloc region */
00123     stack_clear(&(mrb->c->stack[keep]), room - keep);
00124   }
00125 }
00126 
00127 /** def rec ; $deep =+ 1 ; if $deep > 1000 ; return 0 ; end ; rec ; end  */
00128 
00129 static void
00130 stack_extend_alloc(mrb_state *mrb, int room, int keep)
00131 {
00132   mrb_value *oldbase = mrb->c->stbase;
00133   int size = mrb->c->stend - mrb->c->stbase;
00134   int off = mrb->c->stack - mrb->c->stbase;
00135 
00136 #ifdef MRB_STACK_EXTEND_DOUBLING
00137   if (room <= size)
00138     size *= 2;
00139   else
00140     size += room;
00141 #else
00142   /* Use linear stack growth.
00143      It is slightly slower than doubling the stack space,
00144      but it saves memory on small devices. */
00145   if (room <= MRB_STACK_GROWTH)
00146     size += MRB_STACK_GROWTH;
00147   else
00148     size += room;
00149 #endif
00150 
00151   mrb->c->stbase = (mrb_value *)mrb_realloc(mrb, mrb->c->stbase, sizeof(mrb_value) * size);
00152   mrb->c->stack = mrb->c->stbase + off;
00153   mrb->c->stend = mrb->c->stbase + size;
00154   envadjust(mrb, oldbase, mrb->c->stbase);
00155 
00156   /* Raise an exception if the new stack size will be too large,
00157      to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */
00158   if (size > MRB_STACK_MAX) {
00159     init_new_stack_space(mrb, room, keep);
00160     mrb_raise(mrb, E_SYSSTACK_ERROR, "stack level too deep. (limit=" MRB_STRINGIZE(MRB_STACK_MAX) ")");
00161   }
00162 }
00163 
00164 static inline void
00165 stack_extend(mrb_state *mrb, int room, int keep)
00166 {
00167   if (mrb->c->stack + room >= mrb->c->stend) {
00168     stack_extend_alloc(mrb, room, keep);
00169   }
00170   init_new_stack_space(mrb, room, keep);
00171 }
00172 
00173 static inline struct REnv*
00174 uvenv(mrb_state *mrb, int up)
00175 {
00176   struct REnv *e = mrb->c->ci->proc->env;
00177 
00178   while (up--) {
00179     if (!e) return NULL;
00180     e = (struct REnv*)e->c;
00181   }
00182   return e;
00183 }
00184 
00185 static inline mrb_bool
00186 is_strict(mrb_state *mrb, struct REnv *e)
00187 {
00188   int cioff = e->cioff;
00189 
00190   if (MRB_ENV_STACK_SHARED_P(e) && mrb->c->cibase[cioff].proc &&
00191       MRB_PROC_STRICT_P(mrb->c->cibase[cioff].proc)) {
00192     return TRUE;
00193   }
00194   return FALSE;
00195 }
00196 
00197 static inline struct REnv*
00198 top_env(mrb_state *mrb, struct RProc *proc)
00199 {
00200   struct REnv *e = proc->env;
00201 
00202   if (is_strict(mrb, e)) return e;
00203   while (e->c) {
00204     e = (struct REnv*)e->c;
00205     if (is_strict(mrb, e)) return e;
00206   }
00207   return e;
00208 }
00209 
00210 #define CI_ACC_SKIP    -1
00211 #define CI_ACC_DIRECT  -2
00212 
00213 static mrb_callinfo*
00214 cipush(mrb_state *mrb)
00215 {
00216   struct mrb_context *c = mrb->c;
00217   mrb_callinfo *ci = c->ci;
00218 
00219   int eidx = ci->eidx;
00220   int ridx = ci->ridx;
00221 
00222   if (ci + 1 == c->ciend) {
00223     size_t size = ci - c->cibase;
00224 
00225     c->cibase = (mrb_callinfo *)mrb_realloc(mrb, c->cibase, sizeof(mrb_callinfo)*size*2);
00226     c->ci = c->cibase + size;
00227     c->ciend = c->cibase + size * 2;
00228   }
00229   ci = ++c->ci;
00230   ci->eidx = eidx;
00231   ci->ridx = ridx;
00232   ci->env = 0;
00233   ci->pc = 0;
00234   ci->err = 0;
00235   ci->proc = 0;
00236 
00237   return ci;
00238 }
00239 
00240 static void
00241 cipop(mrb_state *mrb)
00242 {
00243   struct mrb_context *c = mrb->c;
00244 
00245   if (c->ci->env) {
00246     struct REnv *e = c->ci->env;
00247     size_t len = (size_t)MRB_ENV_STACK_LEN(e);
00248     mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
00249 
00250     MRB_ENV_UNSHARE_STACK(e);
00251     if (len > 0) {
00252       stack_copy(p, e->stack, len);
00253     }
00254     e->stack = p;
00255     mrb_write_barrier(mrb, (struct RBasic *)e);
00256   }
00257 
00258   c->ci--;
00259 }
00260 
00261 static void
00262 ecall(mrb_state *mrb, int i)
00263 {
00264   struct RProc *p;
00265   mrb_callinfo *ci;
00266   mrb_value *self = mrb->c->stack;
00267   struct RObject *exc;
00268 
00269   p = mrb->c->ensure[i];
00270   if (!p) return;
00271   if (mrb->c->ci->eidx > i)
00272     mrb->c->ci->eidx = i;
00273   ci = cipush(mrb);
00274   ci->stackent = mrb->c->stack;
00275   ci->mid = ci[-1].mid;
00276   ci->acc = CI_ACC_SKIP;
00277   ci->argc = 0;
00278   ci->proc = p;
00279   ci->nregs = p->body.irep->nregs;
00280   ci->target_class = p->target_class;
00281   mrb->c->stack = mrb->c->stack + ci[-1].nregs;
00282   exc = mrb->exc; mrb->exc = 0;
00283   mrb_run(mrb, p, *self);
00284   mrb->c->ensure[i] = NULL;
00285   if (!mrb->exc) mrb->exc = exc;
00286 }
00287 
00288 #ifndef MRB_FUNCALL_ARGC_MAX
00289 #define MRB_FUNCALL_ARGC_MAX 16
00290 #endif
00291 
00292 MRB_API mrb_value
00293 mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, mrb_int argc, ...)
00294 {
00295   mrb_value argv[MRB_FUNCALL_ARGC_MAX];
00296   va_list ap;
00297   mrb_int i;
00298   mrb_sym mid = mrb_intern_cstr(mrb, name);
00299 
00300   if (argc > MRB_FUNCALL_ARGC_MAX) {
00301     mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" MRB_STRINGIZE(MRB_FUNCALL_ARGC_MAX) ")");
00302   }
00303 
00304   va_start(ap, argc);
00305   for (i = 0; i < argc; i++) {
00306     argv[i] = va_arg(ap, mrb_value);
00307   }
00308   va_end(ap);
00309   return mrb_funcall_argv(mrb, self, mid, argc, argv);
00310 }
00311 
00312 MRB_API mrb_value
00313 mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk)
00314 {
00315   mrb_value val;
00316 
00317   if (!mrb->jmp) {
00318     struct mrb_jmpbuf c_jmp;
00319     mrb_callinfo *old_ci = mrb->c->ci;
00320 
00321     MRB_TRY(&c_jmp) {
00322       mrb->jmp = &c_jmp;
00323       /* recursive call */
00324       val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk);
00325       mrb->jmp = 0;
00326     }
00327     MRB_CATCH(&c_jmp) { /* error */
00328       while (old_ci != mrb->c->ci) {
00329         mrb->c->stack = mrb->c->ci->stackent;
00330         cipop(mrb);
00331       }
00332       mrb->jmp = 0;
00333       val = mrb_obj_value(mrb->exc);
00334     }
00335     MRB_END_EXC(&c_jmp);
00336   }
00337   else {
00338     struct RProc *p;
00339     struct RClass *c;
00340     mrb_sym undef = 0;
00341     mrb_callinfo *ci;
00342     int n;
00343 
00344     if (!mrb->c->stack) {
00345       stack_init(mrb);
00346     }
00347     n = mrb->c->ci->nregs;
00348     if (argc < 0) {
00349       mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%S)", mrb_fixnum_value(argc));
00350     }
00351     c = mrb_class(mrb, self);
00352     p = mrb_method_search_vm(mrb, &c, mid);
00353     if (!p) {
00354       undef = mid;
00355       mid = mrb_intern_lit(mrb, "method_missing");
00356       p = mrb_method_search_vm(mrb, &c, mid);
00357       n++; argc++;
00358     }
00359     ci = cipush(mrb);
00360     ci->mid = mid;
00361     ci->proc = p;
00362     ci->stackent = mrb->c->stack;
00363     ci->argc = argc;
00364     ci->target_class = c;
00365     mrb->c->stack = mrb->c->stack + n;
00366     if (MRB_PROC_CFUNC_P(p)) {
00367       ci->nregs = argc + 2;
00368       stack_extend(mrb, ci->nregs, 0);
00369     }
00370     else {
00371       ci->nregs = p->body.irep->nregs + n;
00372       stack_extend(mrb, ci->nregs, argc+2);
00373     }
00374     mrb->c->stack[0] = self;
00375     if (undef) {
00376       mrb->c->stack[1] = mrb_symbol_value(undef);
00377       if (argc > 1) {
00378         stack_copy(mrb->c->stack+2, argv, argc-1);
00379       }
00380     }
00381     else if (argc > 0) {
00382       stack_copy(mrb->c->stack+1, argv, argc);
00383     }
00384     mrb->c->stack[argc+1] = blk;
00385 
00386     if (MRB_PROC_CFUNC_P(p)) {
00387       int ai = mrb_gc_arena_save(mrb);
00388 
00389       ci->acc = CI_ACC_DIRECT;
00390       val = p->body.func(mrb, self);
00391       mrb->c->stack = mrb->c->ci->stackent;
00392       cipop(mrb);
00393       mrb_gc_arena_restore(mrb, ai);
00394     }
00395     else {
00396       ci->acc = CI_ACC_SKIP;
00397       val = mrb_run(mrb, p, self);
00398     }
00399   }
00400   mrb_gc_protect(mrb, val);
00401   return val;
00402 }
00403 
00404 MRB_API mrb_value
00405 mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv)
00406 {
00407   return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value());
00408 }
00409 
00410 /* 15.3.1.3.4  */
00411 /* 15.3.1.3.44 */
00412 /*
00413  *  call-seq:
00414  *     obj.send(symbol [, args...])        -> obj
00415  *     obj.__send__(symbol [, args...])      -> obj
00416  *
00417  *  Invokes the method identified by _symbol_, passing it any
00418  *  arguments specified. You can use <code>__send__</code> if the name
00419  *  +send+ clashes with an existing method in _obj_.
00420  *
00421  *     class Klass
00422  *       def hello(*args)
00423  *         "Hello " + args.join(' ')
00424  *       end
00425  *     end
00426  *     k = Klass.new
00427  *     k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"
00428  */
00429 MRB_API mrb_value
00430 mrb_f_send(mrb_state *mrb, mrb_value self)
00431 {
00432   mrb_sym name;
00433   mrb_value block, *argv, *regs;
00434   mrb_int argc, i, len;
00435   struct RProc *p;
00436   struct RClass *c;
00437   mrb_callinfo *ci;
00438 
00439   mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block);
00440 
00441   c = mrb_class(mrb, self);
00442   p = mrb_method_search_vm(mrb, &c, name);
00443 
00444   if (!p) {                     /* call method_mising */
00445     return mrb_funcall_with_block(mrb, self, name, argc, argv, block);
00446   }
00447 
00448   ci = mrb->c->ci;
00449   ci->mid = name;
00450   ci->target_class = c;
00451   ci->proc = p;
00452   regs = mrb->c->stack+1;
00453   /* remove first symbol from arguments */
00454   if (ci->argc >= 0) {
00455     for (i=0,len=ci->argc; i<len; i++) {
00456       regs[i] = regs[i+1];
00457     }
00458     ci->argc--;
00459   }
00460   else {                     /* variable length arguments */
00461     mrb_ary_shift(mrb, regs[0]);
00462   }
00463 
00464   if (MRB_PROC_CFUNC_P(p)) {
00465     return p->body.func(mrb, self);
00466   }
00467 
00468   ci->nregs = p->body.irep->nregs;
00469   ci = cipush(mrb);
00470   ci->nregs = 0;
00471   ci->target_class = 0;
00472   ci->pc = p->body.irep->iseq;
00473   ci->stackent = mrb->c->stack;
00474   ci->acc = 0;
00475 
00476   return self;
00477 }
00478 
00479 static mrb_value
00480 eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
00481 {
00482   struct RProc *p;
00483   mrb_callinfo *ci;
00484 
00485   if (mrb_nil_p(blk)) {
00486     mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
00487   }
00488   ci = mrb->c->ci;
00489   if (ci->acc == CI_ACC_DIRECT) {
00490     return mrb_yield_with_class(mrb, blk, 0, 0, self, c);
00491   }
00492   ci->target_class = c;
00493   p = mrb_proc_ptr(blk);
00494   ci->proc = p;
00495   if (MRB_PROC_CFUNC_P(p)) {
00496     return p->body.func(mrb, self);
00497   }
00498   ci->nregs = p->body.irep->nregs;
00499   ci = cipush(mrb);
00500   ci->nregs = 0;
00501   ci->target_class = 0;
00502   ci->pc = p->body.irep->iseq;
00503   ci->stackent = mrb->c->stack;
00504   ci->acc = 0;
00505 
00506   return self;
00507 }
00508 
00509 /* 15.2.2.4.35 */
00510 /*
00511  *  call-seq:
00512  *     mod.class_eval {| | block }  -> obj
00513  *     mod.module_eval {| | block } -> obj
00514  *
00515  *  Evaluates block in the context of _mod_. This can
00516  *  be used to add methods to a class. <code>module_eval</code> returns
00517  *  the result of evaluating its argument.
00518  */
00519 mrb_value
00520 mrb_mod_module_eval(mrb_state *mrb, mrb_value mod)
00521 {
00522   mrb_value a, b;
00523 
00524   if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
00525     mrb_raise(mrb, E_NOTIMP_ERROR, "module_eval/class_eval with string not implemented");
00526   }
00527   return eval_under(mrb, mod, b, mrb_class_ptr(mod));
00528 }
00529 
00530 /* 15.3.1.3.18 */
00531 /*
00532  *  call-seq:
00533  *     obj.instance_eval {| | block }                       -> obj
00534  *
00535  *  Evaluates the given block,within  the context of the receiver (_obj_).
00536  *  In order to set the context, the variable +self+ is set to _obj_ while
00537  *  the code is executing, giving the code access to _obj_'s
00538  *  instance variables. In the version of <code>instance_eval</code>
00539  *  that takes a +String+, the optional second and third
00540  *  parameters supply a filename and starting line number that are used
00541  *  when reporting compilation errors.
00542  *
00543  *     class KlassWithSecret
00544  *       def initialize
00545  *         @secret = 99
00546  *       end
00547  *     end
00548  *     k = KlassWithSecret.new
00549  *     k.instance_eval { @secret }   #=> 99
00550  */
00551 mrb_value
00552 mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
00553 {
00554   mrb_value a, b;
00555   mrb_value cv;
00556   struct RClass *c;
00557 
00558   if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
00559     mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented");
00560   }
00561   switch (mrb_type(self)) {
00562   case MRB_TT_SYMBOL:
00563   case MRB_TT_FIXNUM:
00564   case MRB_TT_FLOAT:
00565     c = 0;
00566     break;
00567   default:
00568     cv = mrb_singleton_class(mrb, self);
00569     c = mrb_class_ptr(cv);
00570     break;
00571   }
00572   return eval_under(mrb, self, b, c);
00573 }
00574 
00575 MRB_API mrb_value
00576 mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c)
00577 {
00578   struct RProc *p;
00579   mrb_sym mid = mrb->c->ci->mid;
00580   mrb_callinfo *ci;
00581   int n = mrb->c->ci->nregs;
00582   mrb_value val;
00583 
00584   if (mrb_nil_p(b)) {
00585     mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
00586   }
00587   p = mrb_proc_ptr(b);
00588   ci = cipush(mrb);
00589   ci->mid = mid;
00590   ci->proc = p;
00591   ci->stackent = mrb->c->stack;
00592   ci->argc = argc;
00593   ci->target_class = c;
00594   ci->acc = CI_ACC_SKIP;
00595   mrb->c->stack = mrb->c->stack + n;
00596   if (MRB_PROC_CFUNC_P(p)) {
00597     ci->nregs = argc + 2;
00598     stack_extend(mrb, ci->nregs, 0);
00599   }
00600   else {
00601     ci->nregs = p->body.irep->nregs;
00602     stack_extend(mrb, ci->nregs, argc+2);
00603   }
00604 
00605   mrb->c->stack[0] = self;
00606   if (argc > 0) {
00607     stack_copy(mrb->c->stack+1, argv, argc);
00608   }
00609   mrb->c->stack[argc+1] = mrb_nil_value();
00610 
00611   if (MRB_PROC_CFUNC_P(p)) {
00612     val = p->body.func(mrb, self);
00613     mrb->c->stack = mrb->c->ci->stackent;
00614     cipop(mrb);
00615   }
00616   else {
00617     val = mrb_run(mrb, p, self);
00618   }
00619   return val;
00620 }
00621 
00622 MRB_API mrb_value
00623 mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv)
00624 {
00625   struct RProc *p = mrb_proc_ptr(b);
00626 
00627   return mrb_yield_with_class(mrb, b, argc, argv, p->env->stack[0], p->target_class);
00628 }
00629 
00630 MRB_API mrb_value
00631 mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg)
00632 {
00633   struct RProc *p = mrb_proc_ptr(b);
00634 
00635   return mrb_yield_with_class(mrb, b, 1, &arg, p->env->stack[0], p->target_class);
00636 }
00637 
00638 typedef enum {
00639   LOCALJUMP_ERROR_RETURN = 0,
00640   LOCALJUMP_ERROR_BREAK = 1,
00641   LOCALJUMP_ERROR_YIELD = 2
00642 } localjump_error_kind;
00643 
00644 static void
00645 localjump_error(mrb_state *mrb, localjump_error_kind kind)
00646 {
00647   char kind_str[3][7] = { "return", "break", "yield" };
00648   char kind_str_len[] = { 6, 5, 5 };
00649   static const char lead[] = "unexpected ";
00650   mrb_value msg;
00651   mrb_value exc;
00652 
00653   msg = mrb_str_buf_new(mrb, sizeof(lead) + 7);
00654   mrb_str_cat(mrb, msg, lead, sizeof(lead) - 1);
00655   mrb_str_cat(mrb, msg, kind_str[kind], kind_str_len[kind]);
00656   exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg);
00657   mrb->exc = mrb_obj_ptr(exc);
00658 }
00659 
00660 static void
00661 argnum_error(mrb_state *mrb, mrb_int num)
00662 {
00663   mrb_value exc;
00664   mrb_value str;
00665 
00666   if (mrb->c->ci->mid) {
00667     str = mrb_format(mrb, "'%S': wrong number of arguments (%S for %S)",
00668                   mrb_sym2str(mrb, mrb->c->ci->mid),
00669                   mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num));
00670   }
00671   else {
00672     str = mrb_format(mrb, "wrong number of arguments (%S for %S)",
00673                   mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num));
00674   }
00675   exc = mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str);
00676   mrb->exc = mrb_obj_ptr(exc);
00677 }
00678 
00679 #define ERR_PC_SET(mrb, pc) mrb->c->ci->err = pc;
00680 #define ERR_PC_CLR(mrb)     mrb->c->ci->err = 0;
00681 #ifdef ENABLE_DEBUG
00682 #define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs));
00683 #else
00684 #define CODE_FETCH_HOOK(mrb, irep, pc, regs)
00685 #endif
00686 
00687 #if defined __GNUC__ || defined __clang__ || defined __INTEL_COMPILER
00688 #define DIRECT_THREADED
00689 #endif
00690 
00691 #ifndef DIRECT_THREADED
00692 
00693 #define INIT_DISPATCH for (;;) { i = *pc; CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (GET_OPCODE(i)) {
00694 #define CASE(op) case op:
00695 #define NEXT pc++; break
00696 #define JUMP break
00697 #define END_DISPATCH }}
00698 
00699 #else
00700 
00701 #define INIT_DISPATCH JUMP; return mrb_nil_value();
00702 #define CASE(op) L_ ## op:
00703 #define NEXT i=*++pc; CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)]
00704 #define JUMP i=*pc; CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)]
00705 
00706 #define END_DISPATCH
00707 
00708 #endif
00709 
00710 mrb_value mrb_gv_val_get(mrb_state *mrb, mrb_sym sym);
00711 void mrb_gv_val_set(mrb_state *mrb, mrb_sym sym, mrb_value val);
00712 
00713 #define CALL_MAXARGS 127
00714 
00715 MRB_API mrb_value
00716 mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep)
00717 {
00718   /* mrb_assert(mrb_proc_cfunc_p(proc)) */
00719   mrb_irep *irep = proc->body.irep;
00720   mrb_code *pc = irep->iseq;
00721   mrb_value *pool = irep->pool;
00722   mrb_sym *syms = irep->syms;
00723   mrb_value *regs = NULL;
00724   mrb_code i;
00725   int ai = mrb_gc_arena_save(mrb);
00726   struct mrb_jmpbuf *prev_jmp = mrb->jmp;
00727   struct mrb_jmpbuf c_jmp;
00728 
00729 #ifdef DIRECT_THREADED
00730   static void *optable[] = {
00731     &&L_OP_NOP, &&L_OP_MOVE,
00732     &&L_OP_LOADL, &&L_OP_LOADI, &&L_OP_LOADSYM, &&L_OP_LOADNIL,
00733     &&L_OP_LOADSELF, &&L_OP_LOADT, &&L_OP_LOADF,
00734     &&L_OP_GETGLOBAL, &&L_OP_SETGLOBAL, &&L_OP_GETSPECIAL, &&L_OP_SETSPECIAL,
00735     &&L_OP_GETIV, &&L_OP_SETIV, &&L_OP_GETCV, &&L_OP_SETCV,
00736     &&L_OP_GETCONST, &&L_OP_SETCONST, &&L_OP_GETMCNST, &&L_OP_SETMCNST,
00737     &&L_OP_GETUPVAR, &&L_OP_SETUPVAR,
00738     &&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_JMPNOT,
00739     &&L_OP_ONERR, &&L_OP_RESCUE, &&L_OP_POPERR, &&L_OP_RAISE, &&L_OP_EPUSH, &&L_OP_EPOP,
00740     &&L_OP_SEND, &&L_OP_SENDB, &&L_OP_FSEND,
00741     &&L_OP_CALL, &&L_OP_SUPER, &&L_OP_ARGARY, &&L_OP_ENTER,
00742     &&L_OP_KARG, &&L_OP_KDICT, &&L_OP_RETURN, &&L_OP_TAILCALL, &&L_OP_BLKPUSH,
00743     &&L_OP_ADD, &&L_OP_ADDI, &&L_OP_SUB, &&L_OP_SUBI, &&L_OP_MUL, &&L_OP_DIV,
00744     &&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_GT, &&L_OP_GE,
00745     &&L_OP_ARRAY, &&L_OP_ARYCAT, &&L_OP_ARYPUSH, &&L_OP_AREF, &&L_OP_ASET, &&L_OP_APOST,
00746     &&L_OP_STRING, &&L_OP_STRCAT, &&L_OP_HASH,
00747     &&L_OP_LAMBDA, &&L_OP_RANGE, &&L_OP_OCLASS,
00748     &&L_OP_CLASS, &&L_OP_MODULE, &&L_OP_EXEC,
00749     &&L_OP_METHOD, &&L_OP_SCLASS, &&L_OP_TCLASS,
00750     &&L_OP_DEBUG, &&L_OP_STOP, &&L_OP_ERR,
00751   };
00752 #endif
00753 
00754   mrb_bool exc_catched = FALSE;
00755 RETRY_TRY_BLOCK:
00756 
00757   MRB_TRY(&c_jmp) {
00758 
00759   if (exc_catched) {
00760     exc_catched = FALSE;
00761     goto L_RAISE;
00762   }
00763   mrb->jmp = &c_jmp;
00764   if (!mrb->c->stack) {
00765     stack_init(mrb);
00766   }
00767   stack_extend(mrb, irep->nregs, stack_keep);
00768   mrb->c->ci->proc = proc;
00769   mrb->c->ci->nregs = irep->nregs;
00770   regs = mrb->c->stack;
00771   regs[0] = self;
00772 
00773   INIT_DISPATCH {
00774     CASE(OP_NOP) {
00775       /* do nothing */
00776       NEXT;
00777     }
00778 
00779     CASE(OP_MOVE) {
00780       /* A B    R(A) := R(B) */
00781       regs[GETARG_A(i)] = regs[GETARG_B(i)];
00782       NEXT;
00783     }
00784 
00785     CASE(OP_LOADL) {
00786       /* A Bx   R(A) := Pool(Bx) */
00787       regs[GETARG_A(i)] = pool[GETARG_Bx(i)];
00788       NEXT;
00789     }
00790 
00791     CASE(OP_LOADI) {
00792       /* A sBx  R(A) := sBx */
00793       SET_INT_VALUE(regs[GETARG_A(i)], GETARG_sBx(i));
00794       NEXT;
00795     }
00796 
00797     CASE(OP_LOADSYM) {
00798       /* A Bx   R(A) := Syms(Bx) */
00799       SET_SYM_VALUE(regs[GETARG_A(i)], syms[GETARG_Bx(i)]);
00800       NEXT;
00801     }
00802 
00803     CASE(OP_LOADSELF) {
00804       /* A      R(A) := self */
00805       regs[GETARG_A(i)] = regs[0];
00806       NEXT;
00807     }
00808 
00809     CASE(OP_LOADT) {
00810       /* A      R(A) := true */
00811       SET_TRUE_VALUE(regs[GETARG_A(i)]);
00812       NEXT;
00813     }
00814 
00815     CASE(OP_LOADF) {
00816       /* A      R(A) := false */
00817       SET_FALSE_VALUE(regs[GETARG_A(i)]);
00818       NEXT;
00819     }
00820 
00821     CASE(OP_GETGLOBAL) {
00822       /* A Bx   R(A) := getglobal(Syms(Bx)) */
00823       regs[GETARG_A(i)] = mrb_gv_get(mrb, syms[GETARG_Bx(i)]);
00824       NEXT;
00825     }
00826 
00827     CASE(OP_SETGLOBAL) {
00828       /* setglobal(Syms(Bx), R(A)) */
00829       mrb_gv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]);
00830       NEXT;
00831     }
00832 
00833     CASE(OP_GETSPECIAL) {
00834       /* A Bx   R(A) := Special[Bx] */
00835       regs[GETARG_A(i)] = mrb_vm_special_get(mrb, GETARG_Bx(i));
00836       NEXT;
00837     }
00838 
00839     CASE(OP_SETSPECIAL) {
00840       /* A Bx   Special[Bx] := R(A) */
00841       mrb_vm_special_set(mrb, GETARG_Bx(i), regs[GETARG_A(i)]);
00842       NEXT;
00843     }
00844 
00845     CASE(OP_GETIV) {
00846       /* A Bx   R(A) := ivget(Bx) */
00847       regs[GETARG_A(i)] = mrb_vm_iv_get(mrb, syms[GETARG_Bx(i)]);
00848       NEXT;
00849     }
00850 
00851     CASE(OP_SETIV) {
00852       /* ivset(Syms(Bx),R(A)) */
00853       mrb_vm_iv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]);
00854       NEXT;
00855     }
00856 
00857     CASE(OP_GETCV) {
00858       /* A Bx   R(A) := cvget(Syms(Bx)) */
00859       ERR_PC_SET(mrb, pc);
00860       regs[GETARG_A(i)] = mrb_vm_cv_get(mrb, syms[GETARG_Bx(i)]);
00861       ERR_PC_CLR(mrb);
00862       NEXT;
00863     }
00864 
00865     CASE(OP_SETCV) {
00866       /* cvset(Syms(Bx),R(A)) */
00867       mrb_vm_cv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]);
00868       NEXT;
00869     }
00870 
00871     CASE(OP_GETCONST) {
00872       /* A Bx    R(A) := constget(Syms(Bx)) */
00873       mrb_value val;
00874 
00875       ERR_PC_SET(mrb, pc);
00876       val = mrb_vm_const_get(mrb, syms[GETARG_Bx(i)]);
00877       ERR_PC_CLR(mrb);
00878       regs = mrb->c->stack;
00879       regs[GETARG_A(i)] = val;
00880       NEXT;
00881     }
00882 
00883     CASE(OP_SETCONST) {
00884       /* A Bx   constset(Syms(Bx),R(A)) */
00885       mrb_vm_const_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]);
00886       NEXT;
00887     }
00888 
00889     CASE(OP_GETMCNST) {
00890       /* A Bx   R(A) := R(A)::Syms(Bx) */
00891       mrb_value val;
00892       int a = GETARG_A(i);
00893 
00894       ERR_PC_SET(mrb, pc);
00895       val = mrb_const_get(mrb, regs[a], syms[GETARG_Bx(i)]);
00896       ERR_PC_CLR(mrb);
00897       regs = mrb->c->stack;
00898       regs[a] = val;
00899       NEXT;
00900     }
00901 
00902     CASE(OP_SETMCNST) {
00903       /* A Bx    R(A+1)::Syms(Bx) := R(A) */
00904       int a = GETARG_A(i);
00905 
00906       mrb_const_set(mrb, regs[a+1], syms[GETARG_Bx(i)], regs[a]);
00907       NEXT;
00908     }
00909 
00910     CASE(OP_GETUPVAR) {
00911       /* A B C  R(A) := uvget(B,C) */
00912       mrb_value *regs_a = regs + GETARG_A(i);
00913       int up = GETARG_C(i);
00914 
00915       struct REnv *e = uvenv(mrb, up);
00916 
00917       if (!e) {
00918         *regs_a = mrb_nil_value();
00919       }
00920       else {
00921         int idx = GETARG_B(i);
00922         *regs_a = e->stack[idx];
00923       }
00924       NEXT;
00925     }
00926 
00927     CASE(OP_SETUPVAR) {
00928       /* A B C  uvset(B,C,R(A)) */
00929       int up = GETARG_C(i);
00930 
00931       struct REnv *e = uvenv(mrb, up);
00932 
00933       if (e) {
00934         mrb_value *regs_a = regs + GETARG_A(i);
00935         int idx = GETARG_B(i);
00936         e->stack[idx] = *regs_a;
00937         mrb_write_barrier(mrb, (struct RBasic*)e);
00938       }
00939       NEXT;
00940     }
00941 
00942     CASE(OP_JMP) {
00943       /* sBx    pc+=sBx */
00944       pc += GETARG_sBx(i);
00945       JUMP;
00946     }
00947 
00948     CASE(OP_JMPIF) {
00949       /* A sBx  if R(A) pc+=sBx */
00950       if (mrb_test(regs[GETARG_A(i)])) {
00951         pc += GETARG_sBx(i);
00952         JUMP;
00953       }
00954       NEXT;
00955     }
00956 
00957     CASE(OP_JMPNOT) {
00958       /* A sBx  if !R(A) pc+=sBx */
00959       if (!mrb_test(regs[GETARG_A(i)])) {
00960         pc += GETARG_sBx(i);
00961         JUMP;
00962       }
00963       NEXT;
00964     }
00965 
00966     CASE(OP_ONERR) {
00967       /* sBx    pc+=sBx on exception */
00968       if (mrb->c->rsize <= mrb->c->ci->ridx) {
00969         if (mrb->c->rsize == 0) mrb->c->rsize = 16;
00970         else mrb->c->rsize *= 2;
00971         mrb->c->rescue = (mrb_code **)mrb_realloc(mrb, mrb->c->rescue, sizeof(mrb_code*) * mrb->c->rsize);
00972       }
00973       mrb->c->rescue[mrb->c->ci->ridx++] = pc + GETARG_sBx(i);
00974       NEXT;
00975     }
00976 
00977     CASE(OP_RESCUE) {
00978       /* A      R(A) := exc; clear(exc) */
00979       SET_OBJ_VALUE(regs[GETARG_A(i)], mrb->exc);
00980       mrb->exc = 0;
00981       NEXT;
00982     }
00983 
00984     CASE(OP_POPERR) {
00985       /* A      A.times{rescue_pop()} */
00986       int a = GETARG_A(i);
00987 
00988       while (a--) {
00989         mrb->c->ci->ridx--;
00990       }
00991       NEXT;
00992     }
00993 
00994     CASE(OP_RAISE) {
00995       /* A      raise(R(A)) */
00996       mrb->exc = mrb_obj_ptr(regs[GETARG_A(i)]);
00997       goto L_RAISE;
00998     }
00999 
01000     CASE(OP_EPUSH) {
01001       /* Bx     ensure_push(SEQ[Bx]) */
01002       struct RProc *p;
01003 
01004       p = mrb_closure_new(mrb, irep->reps[GETARG_Bx(i)]);
01005       /* push ensure_stack */
01006       if (mrb->c->esize <= mrb->c->ci->eidx) {
01007         if (mrb->c->esize == 0) mrb->c->esize = 16;
01008         else mrb->c->esize *= 2;
01009         mrb->c->ensure = (struct RProc **)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*) * mrb->c->esize);
01010       }
01011       mrb->c->ensure[mrb->c->ci->eidx++] = p;
01012       ARENA_RESTORE(mrb, ai);
01013       NEXT;
01014     }
01015 
01016     CASE(OP_EPOP) {
01017       /* A      A.times{ensure_pop().call} */
01018       int a = GETARG_A(i);
01019       mrb_callinfo *ci = mrb->c->ci;
01020       int n, eidx = ci->eidx;
01021 
01022       for (n=0; n<a && eidx > ci[-1].eidx; n++) {
01023         ecall(mrb, --eidx);
01024         ARENA_RESTORE(mrb, ai);
01025       }
01026       NEXT;
01027     }
01028 
01029     CASE(OP_LOADNIL) {
01030       /* A     R(A) := nil */
01031       int a = GETARG_A(i);
01032 
01033       SET_NIL_VALUE(regs[a]);
01034       NEXT;
01035     }
01036 
01037     CASE(OP_SENDB) {
01038       /* A B C  R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/
01039       /* fall through */
01040     };
01041 
01042   L_SEND:
01043     CASE(OP_SEND) {
01044       /* A B C  R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */
01045       int a = GETARG_A(i);
01046       int n = GETARG_C(i);
01047       struct RProc *m;
01048       struct RClass *c;
01049       mrb_callinfo *ci;
01050       mrb_value recv, result;
01051       mrb_sym mid = syms[GETARG_B(i)];
01052 
01053       recv = regs[a];
01054       if (GET_OPCODE(i) != OP_SENDB) {
01055         if (n == CALL_MAXARGS) {
01056           SET_NIL_VALUE(regs[a+2]);
01057         }
01058         else {
01059           SET_NIL_VALUE(regs[a+n+1]);
01060         }
01061       }
01062       c = mrb_class(mrb, recv);
01063       m = mrb_method_search_vm(mrb, &c, mid);
01064       if (!m) {
01065         mrb_value sym = mrb_symbol_value(mid);
01066 
01067         mid = mrb_intern_lit(mrb, "method_missing");
01068         m = mrb_method_search_vm(mrb, &c, mid);
01069         if (n == CALL_MAXARGS) {
01070           mrb_ary_unshift(mrb, regs[a+1], sym);
01071         }
01072         else {
01073           value_move(regs+a+2, regs+a+1, ++n);
01074           regs[a+1] = sym;
01075         }
01076       }
01077 
01078       /* push callinfo */
01079       ci = cipush(mrb);
01080       ci->mid = mid;
01081       ci->proc = m;
01082       ci->stackent = mrb->c->stack;
01083       if (c->tt == MRB_TT_ICLASS) {
01084         ci->target_class = c->c;
01085       }
01086       else {
01087         ci->target_class = c;
01088       }
01089 
01090       ci->pc = pc + 1;
01091       ci->acc = a;
01092 
01093       /* prepare stack */
01094       mrb->c->stack += a;
01095 
01096       if (MRB_PROC_CFUNC_P(m)) {
01097         if (n == CALL_MAXARGS) {
01098           ci->argc = -1;
01099           ci->nregs = 3;
01100         }
01101         else {
01102           ci->argc = n;
01103           ci->nregs = n + 2;
01104         }
01105         result = m->body.func(mrb, recv);
01106         mrb->c->stack[0] = result;
01107         mrb_gc_arena_restore(mrb, ai);
01108         if (mrb->exc) goto L_RAISE;
01109         /* pop stackpos */
01110         ci = mrb->c->ci;
01111         if (!ci->target_class) { /* return from context modifying method (resume/yield) */
01112           if (!MRB_PROC_CFUNC_P(ci[-1].proc)) {
01113             proc = ci[-1].proc;
01114             irep = proc->body.irep;
01115             pool = irep->pool;
01116             syms = irep->syms;
01117           }
01118         }
01119         regs = mrb->c->stack = ci->stackent;
01120         pc = ci->pc;
01121         cipop(mrb);
01122         JUMP;
01123       }
01124       else {
01125         /* setup environment for calling method */
01126         proc = mrb->c->ci->proc = m;
01127         irep = m->body.irep;
01128         pool = irep->pool;
01129         syms = irep->syms;
01130         ci->nregs = irep->nregs;
01131         if (n == CALL_MAXARGS) {
01132           ci->argc = -1;
01133           stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
01134         }
01135         else {
01136           ci->argc = n;
01137           stack_extend(mrb, irep->nregs,  n+2);
01138         }
01139         regs = mrb->c->stack;
01140         pc = irep->iseq;
01141         JUMP;
01142       }
01143     }
01144 
01145     CASE(OP_FSEND) {
01146       /* A B C  R(A) := fcall(R(A),Syms(B),R(A+1),... ,R(A+C-1)) */
01147       NEXT;
01148     }
01149 
01150     CASE(OP_CALL) {
01151       /* A      R(A) := self.call(frame.argc, frame.argv) */
01152       mrb_callinfo *ci;
01153       mrb_value recv = mrb->c->stack[0];
01154       struct RProc *m = mrb_proc_ptr(recv);
01155 
01156       /* replace callinfo */
01157       ci = mrb->c->ci;
01158       ci->target_class = m->target_class;
01159       ci->proc = m;
01160       if (m->env) {
01161         if (m->env->mid) {
01162           ci->mid = m->env->mid;
01163         }
01164         if (!m->env->stack) {
01165           m->env->stack = mrb->c->stack;
01166         }
01167       }
01168 
01169       /* prepare stack */
01170       if (MRB_PROC_CFUNC_P(m)) {
01171         recv = m->body.func(mrb, recv);
01172         mrb_gc_arena_restore(mrb, ai);
01173         if (mrb->exc) goto L_RAISE;
01174         /* pop stackpos */
01175         ci = mrb->c->ci;
01176         regs = mrb->c->stack = ci->stackent;
01177         regs[ci->acc] = recv;
01178         pc = ci->pc;
01179         cipop(mrb);
01180         irep = mrb->c->ci->proc->body.irep;
01181         pool = irep->pool;
01182         syms = irep->syms;
01183         JUMP;
01184       }
01185       else {
01186         /* setup environment for calling method */
01187         proc = m;
01188         irep = m->body.irep;
01189         if (!irep) {
01190           mrb->c->stack[0] = mrb_nil_value();
01191           goto L_RETURN;
01192         }
01193         pool = irep->pool;
01194         syms = irep->syms;
01195         ci->nregs = irep->nregs;
01196         if (ci->argc < 0) {
01197           stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
01198         }
01199         else {
01200           stack_extend(mrb, irep->nregs, ci->argc+2);
01201         }
01202         regs = mrb->c->stack;
01203         regs[0] = m->env->stack[0];
01204         pc = irep->iseq;
01205         JUMP;
01206       }
01207     }
01208 
01209     CASE(OP_SUPER) {
01210       /* A C  R(A) := super(R(A+1),... ,R(A+C+1)) */
01211       mrb_value recv;
01212       mrb_callinfo *ci = mrb->c->ci;
01213       struct RProc *m;
01214       struct RClass *c;
01215       mrb_sym mid = ci->mid;
01216       int a = GETARG_A(i);
01217       int n = GETARG_C(i);
01218 
01219       recv = regs[0];
01220       c = mrb->c->ci->target_class->super;
01221       m = mrb_method_search_vm(mrb, &c, mid);
01222       if (!m) {
01223         mid = mrb_intern_lit(mrb, "method_missing");
01224         m = mrb_method_search_vm(mrb, &c, mid);
01225         if (n == CALL_MAXARGS) {
01226           mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid));
01227         }
01228         else {
01229           value_move(regs+a+2, regs+a+1, ++n);
01230           SET_SYM_VALUE(regs[a+1], ci->mid);
01231         }
01232       }
01233 
01234       /* push callinfo */
01235       ci = cipush(mrb);
01236       ci->mid = mid;
01237       ci->proc = m;
01238       ci->stackent = mrb->c->stack;
01239       if (n == CALL_MAXARGS) {
01240         ci->argc = -1;
01241       }
01242       else {
01243         ci->argc = n;
01244       }
01245       ci->target_class = c;
01246       ci->pc = pc + 1;
01247 
01248       /* prepare stack */
01249       mrb->c->stack += a;
01250       mrb->c->stack[0] = recv;
01251 
01252       if (MRB_PROC_CFUNC_P(m)) {
01253         ci->nregs = 0;
01254         mrb->c->stack[0] = m->body.func(mrb, recv);
01255         mrb_gc_arena_restore(mrb, ai);
01256         if (mrb->exc) goto L_RAISE;
01257         /* pop stackpos */
01258         regs = mrb->c->stack = mrb->c->ci->stackent;
01259         cipop(mrb);
01260         NEXT;
01261       }
01262       else {
01263         /* fill callinfo */
01264         ci->acc = a;
01265 
01266         /* setup environment for calling method */
01267         ci->proc = m;
01268         irep = m->body.irep;
01269         pool = irep->pool;
01270         syms = irep->syms;
01271         ci->nregs = irep->nregs;
01272         if (n == CALL_MAXARGS) {
01273           stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
01274         }
01275         else {
01276           stack_extend(mrb, irep->nregs, ci->argc+2);
01277         }
01278         regs = mrb->c->stack;
01279         pc = irep->iseq;
01280         JUMP;
01281       }
01282     }
01283 
01284     CASE(OP_ARGARY) {
01285       /* A Bx   R(A) := argument array (16=6:1:5:4) */
01286       int a = GETARG_A(i);
01287       int bx = GETARG_Bx(i);
01288       int m1 = (bx>>10)&0x3f;
01289       int r  = (bx>>9)&0x1;
01290       int m2 = (bx>>4)&0x1f;
01291       int lv = (bx>>0)&0xf;
01292       mrb_value *stack;
01293 
01294       if (lv == 0) stack = regs + 1;
01295       else {
01296         struct REnv *e = uvenv(mrb, lv-1);
01297         if (!e) {
01298           mrb_value exc;
01299           exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method");
01300           mrb->exc = mrb_obj_ptr(exc);
01301           goto L_RAISE;
01302         }
01303         stack = e->stack + 1;
01304       }
01305       if (r == 0) {
01306         regs[a] = mrb_ary_new_from_values(mrb, m1+m2, stack);
01307       }
01308       else {
01309         mrb_value *pp = NULL;
01310         struct RArray *rest;
01311         int len = 0;
01312 
01313         if (mrb_array_p(stack[m1])) {
01314           struct RArray *ary = mrb_ary_ptr(stack[m1]);
01315 
01316           pp = ary->ptr;
01317           len = ary->len;
01318         }
01319         regs[a] = mrb_ary_new_capa(mrb, m1+len+m2);
01320         rest = mrb_ary_ptr(regs[a]);
01321         if (m1 > 0) {
01322           stack_copy(rest->ptr, stack, m1);
01323         }
01324         if (len > 0) {
01325           stack_copy(rest->ptr+m1, pp, len);
01326         }
01327         if (m2 > 0) {
01328           stack_copy(rest->ptr+m1+len, stack+m1+1, m2);
01329         }
01330         rest->len = m1+len+m2;
01331       }
01332       regs[a+1] = stack[m1+r+m2];
01333       ARENA_RESTORE(mrb, ai);
01334       NEXT;
01335     }
01336 
01337     CASE(OP_ENTER) {
01338       /* Ax             arg setup according to flags (23=5:5:1:5:5:1:1) */
01339       /* number of optional arguments times OP_JMP should follow */
01340       mrb_aspec ax = GETARG_Ax(i);
01341       int m1 = MRB_ASPEC_REQ(ax);
01342       int o  = MRB_ASPEC_OPT(ax);
01343       int r  = MRB_ASPEC_REST(ax);
01344       int m2 = MRB_ASPEC_POST(ax);
01345       /* unused
01346       int k  = MRB_ASPEC_KEY(ax);
01347       int kd = MRB_ASPEC_KDICT(ax);
01348       int b  = MRB_ASPEC_BLOCK(ax);
01349       */
01350       int argc = mrb->c->ci->argc;
01351       mrb_value *argv = regs+1;
01352       mrb_value *argv0 = argv;
01353       int len = m1 + o + r + m2;
01354       mrb_value *blk = &argv[argc < 0 ? 1 : argc];
01355 
01356       if (!mrb_nil_p(*blk) && mrb_type(*blk) != MRB_TT_PROC) {
01357         *blk = mrb_convert_type(mrb, *blk, MRB_TT_PROC, "Proc", "to_proc");
01358       }
01359       if (argc < 0) {
01360         struct RArray *ary = mrb_ary_ptr(regs[1]);
01361         argv = ary->ptr;
01362         argc = ary->len;
01363         mrb_gc_protect(mrb, regs[1]);
01364       }
01365       if (mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc)) {
01366         if (argc >= 0) {
01367           if (argc < m1 + m2 || (r == 0 && argc > len)) {
01368             argnum_error(mrb, m1+m2);
01369             goto L_RAISE;
01370           }
01371         }
01372       }
01373       else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) {
01374         mrb_gc_protect(mrb, argv[0]);
01375         argc = mrb_ary_ptr(argv[0])->len;
01376         argv = mrb_ary_ptr(argv[0])->ptr;
01377       }
01378       mrb->c->ci->argc = len;
01379       if (argc < len) {
01380         int mlen = m2;
01381         if (argc < m1+m2) {
01382           if (m1 < argc)
01383             mlen = argc - m1;
01384           else
01385             mlen = 0;
01386         }
01387         regs[len+1] = *blk; /* move block */
01388         SET_NIL_VALUE(regs[argc+1]);
01389         if (argv0 != argv) {
01390           value_move(&regs[1], argv, argc-mlen); /* m1 + o */
01391         }
01392         if (mlen) {
01393           value_move(&regs[len-m2+1], &argv[argc-mlen], mlen);
01394         }
01395         if (r) {
01396           regs[m1+o+1] = mrb_ary_new_capa(mrb, 0);
01397         }
01398         if (o == 0 || argc < m1+m2) pc++;
01399         else
01400           pc += argc - m1 - m2 + 1;
01401       }
01402       else {
01403         int rnum = 0;
01404         if (argv0 != argv) {
01405           regs[len+1] = *blk; /* move block */
01406           value_move(&regs[1], argv, m1+o);
01407         }
01408         if (r) {
01409           rnum = argc-m1-o-m2;
01410           regs[m1+o+1] = mrb_ary_new_from_values(mrb, rnum, argv+m1+o);
01411         }
01412         if (m2) {
01413           if (argc-m2 > m1) {
01414             value_move(&regs[m1+o+r+1], &argv[m1+o+rnum], m2);
01415           }
01416         }
01417         if (argv0 == argv) {
01418           regs[len+1] = *blk; /* move block */
01419         }
01420         pc += o + 1;
01421       }
01422       JUMP;
01423     }
01424 
01425     CASE(OP_KARG) {
01426       /* A B C          R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */
01427       /* if C == 2; raise unless kdict.empty? */
01428       /* OP_JMP should follow to skip init code */
01429       NEXT;
01430     }
01431 
01432     CASE(OP_KDICT) {
01433       /* A C            R(A) := kdict */
01434       NEXT;
01435     }
01436 
01437     L_RETURN:
01438       i = MKOP_AB(OP_RETURN, GETARG_A(i), OP_R_NORMAL);
01439       /* fall through */
01440     CASE(OP_RETURN) {
01441       /* A B     return R(A) (B=normal,in-block return/break) */
01442       if (mrb->exc) {
01443         mrb_callinfo *ci;
01444         int eidx;
01445 
01446       L_RAISE:
01447         ci = mrb->c->ci;
01448         mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern_lit(mrb, "lastpc"), mrb_cptr_value(mrb, pc));
01449         mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern_lit(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->c->cibase));
01450         eidx = ci->eidx;
01451         if (ci == mrb->c->cibase) {
01452           if (ci->ridx == 0) goto L_STOP;
01453           goto L_RESCUE;
01454         }
01455         while (eidx > ci[-1].eidx) {
01456           ecall(mrb, --eidx);
01457         }
01458         while (ci[0].ridx == ci[-1].ridx) {
01459           cipop(mrb);
01460           ci = mrb->c->ci;
01461           mrb->c->stack = ci[1].stackent;
01462           if (ci[1].acc == CI_ACC_SKIP && prev_jmp) {
01463             mrb->jmp = prev_jmp;
01464             MRB_THROW(prev_jmp);
01465           }
01466           if (ci > mrb->c->cibase) {
01467             while (eidx > ci[-1].eidx) {
01468               ecall(mrb, --eidx);
01469             }
01470           }
01471           else if (ci == mrb->c->cibase) {
01472             if (ci->ridx == 0) {
01473               if (mrb->c == mrb->root_c) {
01474                 regs = mrb->c->stack = mrb->c->stbase;
01475                 goto L_STOP;
01476               }
01477               else {
01478                 struct mrb_context *c = mrb->c;
01479 
01480                 mrb->c = c->prev;
01481                 c->prev = NULL;
01482                 goto L_RAISE;
01483               }
01484             }
01485             break;
01486           }
01487         }
01488       L_RESCUE:
01489         if (ci->ridx == 0) goto L_STOP;
01490         proc = ci->proc;
01491         irep = proc->body.irep;
01492         pool = irep->pool;
01493         syms = irep->syms;
01494         regs = mrb->c->stack = ci[1].stackent;
01495         pc = mrb->c->rescue[--ci->ridx];
01496       }
01497       else {
01498         mrb_callinfo *ci = mrb->c->ci;
01499         int acc, eidx = mrb->c->ci->eidx;
01500         mrb_value v = regs[GETARG_A(i)];
01501 
01502         switch (GETARG_B(i)) {
01503         case OP_R_RETURN:
01504           /* Fall through to OP_R_NORMAL otherwise */
01505           if (proc->env && !MRB_PROC_STRICT_P(proc)) {
01506             struct REnv *e = top_env(mrb, proc);
01507 
01508             if (!MRB_ENV_STACK_SHARED_P(e)) {
01509               localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
01510               goto L_RAISE;
01511             }
01512             ci = mrb->c->cibase + e->cioff;
01513             if (ci == mrb->c->cibase) {
01514               localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
01515               goto L_RAISE;
01516             }
01517             mrb->c->ci = ci;
01518             break;
01519           }
01520         case OP_R_NORMAL:
01521           if (ci == mrb->c->cibase) {
01522             if (!mrb->c->prev) { /* toplevel return */
01523               localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
01524               goto L_RAISE;
01525             }
01526             if (mrb->c->prev->ci == mrb->c->prev->cibase) {
01527               mrb_value exc = mrb_exc_new_str_lit(mrb, E_FIBER_ERROR, "double resume");
01528               mrb->exc = mrb_obj_ptr(exc);
01529               goto L_RAISE;
01530             }
01531             /* automatic yield at the end */
01532             mrb->c->status = MRB_FIBER_TERMINATED;
01533             mrb->c = mrb->c->prev;
01534             mrb->c->status = MRB_FIBER_RUNNING;
01535           }
01536           ci = mrb->c->ci;
01537           break;
01538         case OP_R_BREAK:
01539           if (!proc->env || !MRB_ENV_STACK_SHARED_P(proc->env)) {
01540             localjump_error(mrb, LOCALJUMP_ERROR_BREAK);
01541             goto L_RAISE;
01542           }
01543           /* break from fiber block */
01544           if (mrb->c->ci == mrb->c->cibase && mrb->c->ci->pc) {
01545             struct mrb_context *c = mrb->c;
01546 
01547             mrb->c = c->prev;
01548             c->prev = NULL;
01549           }
01550           ci = mrb->c->ci;
01551           mrb->c->ci = mrb->c->cibase + proc->env->cioff + 1;
01552           while (ci > mrb->c->ci) {
01553             if (ci[-1].acc == CI_ACC_SKIP) {
01554               mrb->c->ci = ci;
01555               break;
01556             }
01557             ci--;
01558           }
01559           break;
01560         default:
01561           /* cannot happen */
01562           break;
01563         }
01564         while (eidx > mrb->c->ci[-1].eidx) {
01565           ecall(mrb, --eidx);
01566         }
01567         cipop(mrb);
01568         acc = ci->acc;
01569         pc = ci->pc;
01570         regs = mrb->c->stack = ci->stackent;
01571         if (acc == CI_ACC_SKIP) {
01572           mrb->jmp = prev_jmp;
01573           return v;
01574         }
01575         DEBUG(printf("from :%s\n", mrb_sym2name(mrb, ci->mid)));
01576         proc = mrb->c->ci->proc;
01577         irep = proc->body.irep;
01578         pool = irep->pool;
01579         syms = irep->syms;
01580 
01581         regs[acc] = v;
01582       }
01583       JUMP;
01584     }
01585 
01586     CASE(OP_TAILCALL) {
01587       /* A B C  return call(R(A),Syms(B),R(A+1),... ,R(A+C+1)) */
01588       int a = GETARG_A(i);
01589       int n = GETARG_C(i);
01590       struct RProc *m;
01591       struct RClass *c;
01592       mrb_callinfo *ci;
01593       mrb_value recv;
01594       mrb_sym mid = syms[GETARG_B(i)];
01595 
01596       recv = regs[a];
01597       c = mrb_class(mrb, recv);
01598       m = mrb_method_search_vm(mrb, &c, mid);
01599       if (!m) {
01600         mrb_value sym = mrb_symbol_value(mid);
01601 
01602         mid = mrb_intern_lit(mrb, "method_missing");
01603         m = mrb_method_search_vm(mrb, &c, mid);
01604         if (n == CALL_MAXARGS) {
01605           mrb_ary_unshift(mrb, regs[a+1], sym);
01606         }
01607         else {
01608           value_move(regs+a+2, regs+a+1, ++n);
01609           regs[a+1] = sym;
01610         }
01611       }
01612 
01613       /* replace callinfo */
01614       ci = mrb->c->ci;
01615       ci->mid = mid;
01616       ci->target_class = c;
01617       if (n == CALL_MAXARGS) {
01618         ci->argc = -1;
01619       }
01620       else {
01621         ci->argc = n;
01622       }
01623 
01624       /* move stack */
01625       value_move(mrb->c->stack, &regs[a], ci->argc+1);
01626 
01627       if (MRB_PROC_CFUNC_P(m)) {
01628         mrb->c->stack[0] = m->body.func(mrb, recv);
01629         mrb_gc_arena_restore(mrb, ai);
01630         goto L_RETURN;
01631       }
01632       else {
01633         /* setup environment for calling method */
01634         irep = m->body.irep;
01635         pool = irep->pool;
01636         syms = irep->syms;
01637         if (ci->argc < 0) {
01638           stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
01639         }
01640         else {
01641           stack_extend(mrb, irep->nregs, ci->argc+2);
01642         }
01643         regs = mrb->c->stack;
01644         pc = irep->iseq;
01645       }
01646       JUMP;
01647     }
01648 
01649     CASE(OP_BLKPUSH) {
01650       /* A Bx   R(A) := block (16=6:1:5:4) */
01651       int a = GETARG_A(i);
01652       int bx = GETARG_Bx(i);
01653       int m1 = (bx>>10)&0x3f;
01654       int r  = (bx>>9)&0x1;
01655       int m2 = (bx>>4)&0x1f;
01656       int lv = (bx>>0)&0xf;
01657       mrb_value *stack;
01658 
01659       if (lv == 0) stack = regs + 1;
01660       else {
01661         struct REnv *e = uvenv(mrb, lv-1);
01662         if (!e) {
01663           localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
01664           goto L_RAISE;
01665         }
01666         stack = e->stack + 1;
01667       }
01668       regs[a] = stack[m1+r+m2];
01669       NEXT;
01670     }
01671 
01672 #define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff))
01673 #define OP_MATH_BODY(op,v1,v2) do {\
01674   v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\
01675 } while(0)
01676 
01677     CASE(OP_ADD) {
01678       /* A B C  R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)*/
01679       int a = GETARG_A(i);
01680 
01681       /* need to check if op is overridden */
01682       switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
01683       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
01684         {
01685           mrb_int x, y, z;
01686           mrb_value *regs_a = regs + a;
01687 
01688           x = mrb_fixnum(regs_a[0]);
01689           y = mrb_fixnum(regs_a[1]);
01690           if (mrb_int_add_overflow(x, y, &z)) {
01691             SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y);
01692             break;
01693           }
01694           SET_INT_VALUE(regs[a], z);
01695         }
01696         break;
01697       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
01698         {
01699           mrb_int x = mrb_fixnum(regs[a]);
01700           mrb_float y = mrb_float(regs[a+1]);
01701           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + y);
01702         }
01703         break;
01704       case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
01705 #ifdef MRB_WORD_BOXING
01706         {
01707           mrb_float x = mrb_float(regs[a]);
01708           mrb_int y = mrb_fixnum(regs[a+1]);
01709           SET_FLOAT_VALUE(mrb, regs[a], x + y);
01710         }
01711 #else
01712         OP_MATH_BODY(+,mrb_float,mrb_fixnum);
01713 #endif
01714         break;
01715       case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
01716 #ifdef MRB_WORD_BOXING
01717         {
01718           mrb_float x = mrb_float(regs[a]);
01719           mrb_float y = mrb_float(regs[a+1]);
01720           SET_FLOAT_VALUE(mrb, regs[a], x + y);
01721         }
01722 #else
01723         OP_MATH_BODY(+,mrb_float,mrb_float);
01724 #endif
01725         break;
01726       case TYPES2(MRB_TT_STRING,MRB_TT_STRING):
01727         regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]);
01728         break;
01729       default:
01730         goto L_SEND;
01731       }
01732       ARENA_RESTORE(mrb, ai);
01733       NEXT;
01734     }
01735 
01736     CASE(OP_SUB) {
01737       /* A B C  R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)*/
01738       int a = GETARG_A(i);
01739 
01740       /* need to check if op is overridden */
01741       switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
01742       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
01743         {
01744           mrb_int x, y, z;
01745 
01746           x = mrb_fixnum(regs[a]);
01747           y = mrb_fixnum(regs[a+1]);
01748           if (mrb_int_sub_overflow(x, y, &z)) {
01749             SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y);
01750             break;
01751           }
01752           SET_INT_VALUE(regs[a], z);
01753         }
01754         break;
01755       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
01756         {
01757           mrb_int x = mrb_fixnum(regs[a]);
01758           mrb_float y = mrb_float(regs[a+1]);
01759           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - y);
01760         }
01761         break;
01762       case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
01763 #ifdef MRB_WORD_BOXING
01764         {
01765           mrb_float x = mrb_float(regs[a]);
01766           mrb_int y = mrb_fixnum(regs[a+1]);
01767           SET_FLOAT_VALUE(mrb, regs[a], x - y);
01768         }
01769 #else
01770         OP_MATH_BODY(-,mrb_float,mrb_fixnum);
01771 #endif
01772         break;
01773       case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
01774 #ifdef MRB_WORD_BOXING
01775         {
01776           mrb_float x = mrb_float(regs[a]);
01777           mrb_float y = mrb_float(regs[a+1]);
01778           SET_FLOAT_VALUE(mrb, regs[a], x - y);
01779         }
01780 #else
01781         OP_MATH_BODY(-,mrb_float,mrb_float);
01782 #endif
01783         break;
01784       default:
01785         goto L_SEND;
01786       }
01787       NEXT;
01788     }
01789 
01790     CASE(OP_MUL) {
01791       /* A B C  R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1)*/
01792       int a = GETARG_A(i);
01793 
01794       /* need to check if op is overridden */
01795       switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
01796       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
01797         {
01798           mrb_value z;
01799 
01800           z = mrb_fixnum_mul(mrb, regs[a], regs[a+1]);
01801 
01802           switch (mrb_type(z)) {
01803           case MRB_TT_FIXNUM:
01804             {
01805               SET_INT_VALUE(regs[a], mrb_fixnum(z));
01806             }
01807             break;
01808           case MRB_TT_FLOAT:
01809             {
01810               SET_FLOAT_VALUE(mrb, regs[a], mrb_float(z));
01811             }
01812             break;
01813           default:
01814             /* cannot happen */
01815             break;
01816           }
01817         }
01818         break;
01819       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
01820         {
01821           mrb_int x = mrb_fixnum(regs[a]);
01822           mrb_float y = mrb_float(regs[a+1]);
01823           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * y);
01824         }
01825         break;
01826       case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
01827 #ifdef MRB_WORD_BOXING
01828         {
01829           mrb_float x = mrb_float(regs[a]);
01830           mrb_int y = mrb_fixnum(regs[a+1]);
01831           SET_FLOAT_VALUE(mrb, regs[a], x * y);
01832         }
01833 #else
01834         OP_MATH_BODY(*,mrb_float,mrb_fixnum);
01835 #endif
01836         break;
01837       case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
01838 #ifdef MRB_WORD_BOXING
01839         {
01840           mrb_float x = mrb_float(regs[a]);
01841           mrb_float y = mrb_float(regs[a+1]);
01842           SET_FLOAT_VALUE(mrb, regs[a], x * y);
01843         }
01844 #else
01845         OP_MATH_BODY(*,mrb_float,mrb_float);
01846 #endif
01847         break;
01848       default:
01849         goto L_SEND;
01850       }
01851       NEXT;
01852     }
01853 
01854     CASE(OP_DIV) {
01855       /* A B C  R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/
01856       int a = GETARG_A(i);
01857 
01858       /* need to check if op is overridden */
01859       switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
01860       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
01861         {
01862           mrb_int x = mrb_fixnum(regs[a]);
01863           mrb_int y = mrb_fixnum(regs[a+1]);
01864           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / (mrb_float)y);
01865         }
01866         break;
01867       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
01868         {
01869           mrb_int x = mrb_fixnum(regs[a]);
01870           mrb_float y = mrb_float(regs[a+1]);
01871           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / y);
01872         }
01873         break;
01874       case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
01875 #ifdef MRB_WORD_BOXING
01876         {
01877           mrb_float x = mrb_float(regs[a]);
01878           mrb_int y = mrb_fixnum(regs[a+1]);
01879           SET_FLOAT_VALUE(mrb, regs[a], x / y);
01880         }
01881 #else
01882         OP_MATH_BODY(/,mrb_float,mrb_fixnum);
01883 #endif
01884         break;
01885       case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
01886 #ifdef MRB_WORD_BOXING
01887         {
01888           mrb_float x = mrb_float(regs[a]);
01889           mrb_float y = mrb_float(regs[a+1]);
01890           SET_FLOAT_VALUE(mrb, regs[a], x / y);
01891         }
01892 #else
01893         OP_MATH_BODY(/,mrb_float,mrb_float);
01894 #endif
01895         break;
01896       default:
01897         goto L_SEND;
01898       }
01899 #ifdef MRB_NAN_BOXING
01900       if (isnan(mrb_float(regs[a]))) {
01901         regs[a] = mrb_float_value(mrb, mrb_float(regs[a]));
01902       }
01903 #endif
01904       NEXT;
01905     }
01906 
01907     CASE(OP_ADDI) {
01908       /* A B C  R(A) := R(A)+C (Syms[B]=:+)*/
01909       int a = GETARG_A(i);
01910 
01911       /* need to check if + is overridden */
01912       switch (mrb_type(regs[a])) {
01913       case MRB_TT_FIXNUM:
01914         {
01915           mrb_int x = mrb_fixnum(regs[a]);
01916           mrb_int y = GETARG_C(i);
01917           mrb_int z;
01918 
01919           if (mrb_int_add_overflow(x, y, &z)) {
01920             SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y);
01921             break;
01922           }
01923           mrb_fixnum(regs[a]) = z;
01924         }
01925         break;
01926       case MRB_TT_FLOAT:
01927 #ifdef MRB_WORD_BOXING
01928         {
01929           mrb_float x = mrb_float(regs[a]);
01930           SET_FLOAT_VALUE(mrb, regs[a], x + GETARG_C(i));
01931         }
01932 #else
01933         mrb_float(regs[a]) += GETARG_C(i);
01934 #endif
01935         break;
01936       default:
01937         SET_INT_VALUE(regs[a+1], GETARG_C(i));
01938         i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1);
01939         goto L_SEND;
01940       }
01941       NEXT;
01942     }
01943 
01944     CASE(OP_SUBI) {
01945       /* A B C  R(A) := R(A)-C (Syms[B]=:-)*/
01946       int a = GETARG_A(i);
01947       mrb_value *regs_a = regs + a;
01948 
01949       /* need to check if + is overridden */
01950       switch (mrb_type(regs_a[0])) {
01951       case MRB_TT_FIXNUM:
01952         {
01953           mrb_int x = mrb_fixnum(regs_a[0]);
01954           mrb_int y = GETARG_C(i);
01955           mrb_int z;
01956 
01957           if (mrb_int_sub_overflow(x, y, &z)) {
01958             SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y);
01959           }
01960           else {
01961             mrb_fixnum(regs_a[0]) = z;
01962           }
01963         }
01964         break;
01965       case MRB_TT_FLOAT:
01966 #ifdef MRB_WORD_BOXING
01967         {
01968           mrb_float x = mrb_float(regs[a]);
01969           SET_FLOAT_VALUE(mrb, regs[a], x - GETARG_C(i));
01970         }
01971 #else
01972         mrb_float(regs_a[0]) -= GETARG_C(i);
01973 #endif
01974         break;
01975       default:
01976         SET_INT_VALUE(regs_a[1], GETARG_C(i));
01977         i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1);
01978         goto L_SEND;
01979       }
01980       NEXT;
01981     }
01982 
01983 #define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1]))
01984 
01985 #define OP_CMP(op) do {\
01986   int result;\
01987   /* need to check if - is overridden */\
01988   switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
01989   case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\
01990     result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\
01991     break;\
01992   case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\
01993     result = OP_CMP_BODY(op,mrb_fixnum,mrb_float);\
01994     break;\
01995   case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\
01996     result = OP_CMP_BODY(op,mrb_float,mrb_fixnum);\
01997     break;\
01998   case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\
01999     result = OP_CMP_BODY(op,mrb_float,mrb_float);\
02000     break;\
02001   default:\
02002     goto L_SEND;\
02003   }\
02004   if (result) {\
02005     SET_TRUE_VALUE(regs[a]);\
02006   }\
02007   else {\
02008     SET_FALSE_VALUE(regs[a]);\
02009   }\
02010 } while(0)
02011 
02012     CASE(OP_EQ) {
02013       /* A B C  R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1)*/
02014       int a = GETARG_A(i);
02015       if (mrb_obj_eq(mrb, regs[a], regs[a+1])) {
02016         SET_TRUE_VALUE(regs[a]);
02017       }
02018       else {
02019         OP_CMP(==);
02020       }
02021       NEXT;
02022     }
02023 
02024     CASE(OP_LT) {
02025       /* A B C  R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1)*/
02026       int a = GETARG_A(i);
02027       OP_CMP(<);
02028       NEXT;
02029     }
02030 
02031     CASE(OP_LE) {
02032       /* A B C  R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1)*/
02033       int a = GETARG_A(i);
02034       OP_CMP(<=);
02035       NEXT;
02036     }
02037 
02038     CASE(OP_GT) {
02039       /* A B C  R(A) := R(A)>R(A+1) (Syms[B]=:>,C=1)*/
02040       int a = GETARG_A(i);
02041       OP_CMP(>);
02042       NEXT;
02043     }
02044 
02045     CASE(OP_GE) {
02046       /* A B C  R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1)*/
02047       int a = GETARG_A(i);
02048       OP_CMP(>=);
02049       NEXT;
02050     }
02051 
02052     CASE(OP_ARRAY) {
02053       /* A B C          R(A) := ary_new(R(B),R(B+1)..R(B+C)) */
02054       regs[GETARG_A(i)] = mrb_ary_new_from_values(mrb, GETARG_C(i), &regs[GETARG_B(i)]);
02055       ARENA_RESTORE(mrb, ai);
02056       NEXT;
02057     }
02058 
02059     CASE(OP_ARYCAT) {
02060       /* A B            mrb_ary_concat(R(A),R(B)) */
02061       mrb_ary_concat(mrb, regs[GETARG_A(i)],
02062                      mrb_ary_splat(mrb, regs[GETARG_B(i)]));
02063       ARENA_RESTORE(mrb, ai);
02064       NEXT;
02065     }
02066 
02067     CASE(OP_ARYPUSH) {
02068       /* A B            R(A).push(R(B)) */
02069       mrb_ary_push(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]);
02070       NEXT;
02071     }
02072 
02073     CASE(OP_AREF) {
02074       /* A B C          R(A) := R(B)[C] */
02075       int a = GETARG_A(i);
02076       int c = GETARG_C(i);
02077       mrb_value v = regs[GETARG_B(i)];
02078 
02079       if (!mrb_array_p(v)) {
02080         if (c == 0) {
02081           regs[GETARG_A(i)] = v;
02082         }
02083         else {
02084           SET_NIL_VALUE(regs[a]);
02085         }
02086       }
02087       else {
02088         regs[GETARG_A(i)] = mrb_ary_ref(mrb, v, c);
02089       }
02090       NEXT;
02091     }
02092 
02093     CASE(OP_ASET) {
02094       /* A B C          R(B)[C] := R(A) */
02095       mrb_ary_set(mrb, regs[GETARG_B(i)], GETARG_C(i), regs[GETARG_A(i)]);
02096       NEXT;
02097     }
02098 
02099     CASE(OP_APOST) {
02100       /* A B C  *R(A),R(A+1)..R(A+C) := R(A) */
02101       int a = GETARG_A(i);
02102       mrb_value v = regs[a];
02103       int pre  = GETARG_B(i);
02104       int post = GETARG_C(i);
02105 
02106       if (!mrb_array_p(v)) {
02107         regs[a++] = mrb_ary_new_capa(mrb, 0);
02108         while (post--) {
02109           SET_NIL_VALUE(regs[a]);
02110           a++;
02111         }
02112       }
02113       else {
02114         struct RArray *ary = mrb_ary_ptr(v);
02115         int len = ary->len;
02116         int idx;
02117 
02118         if (len > pre + post) {
02119           regs[a++] = mrb_ary_new_from_values(mrb, len - pre - post, ary->ptr+pre);
02120           while (post--) {
02121             regs[a++] = ary->ptr[len-post-1];
02122           }
02123         }
02124         else {
02125           regs[a++] = mrb_ary_new_capa(mrb, 0);
02126           for (idx=0; idx+pre<len; idx++) {
02127             regs[a+idx] = ary->ptr[pre+idx];
02128           }
02129           while (idx < post) {
02130             SET_NIL_VALUE(regs[a+idx]);
02131             idx++;
02132           }
02133         }
02134       }
02135       ARENA_RESTORE(mrb, ai);
02136       NEXT;
02137     }
02138 
02139     CASE(OP_STRING) {
02140       /* A Bx           R(A) := str_new(Lit(Bx)) */
02141       regs[GETARG_A(i)] = mrb_str_dup(mrb, pool[GETARG_Bx(i)]);
02142       ARENA_RESTORE(mrb, ai);
02143       NEXT;
02144     }
02145 
02146     CASE(OP_STRCAT) {
02147       /* A B    R(A).concat(R(B)) */
02148       mrb_str_concat(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]);
02149       NEXT;
02150     }
02151 
02152     CASE(OP_HASH) {
02153       /* A B C   R(A) := hash_new(R(B),R(B+1)..R(B+C)) */
02154       int b = GETARG_B(i);
02155       int c = GETARG_C(i);
02156       int lim = b+c*2;
02157       mrb_value hash = mrb_hash_new_capa(mrb, c);
02158 
02159       while (b < lim) {
02160         mrb_hash_set(mrb, hash, regs[b], regs[b+1]);
02161         b+=2;
02162       }
02163       regs[GETARG_A(i)] = hash;
02164       ARENA_RESTORE(mrb, ai);
02165       NEXT;
02166     }
02167 
02168     CASE(OP_LAMBDA) {
02169       /* A b c  R(A) := lambda(SEQ[b],c) (b:c = 14:2) */
02170       struct RProc *p;
02171       int c = GETARG_c(i);
02172 
02173       if (c & OP_L_CAPTURE) {
02174         p = mrb_closure_new(mrb, irep->reps[GETARG_b(i)]);
02175       }
02176       else {
02177         p = mrb_proc_new(mrb, irep->reps[GETARG_b(i)]);
02178         if (c & OP_L_METHOD) {
02179           if (p->target_class->tt == MRB_TT_SCLASS) {
02180             mrb_value klass;
02181             klass = mrb_obj_iv_get(mrb,
02182                                    (struct RObject *)p->target_class,
02183                                    mrb_intern_lit(mrb, "__attached__"));
02184             p->target_class = mrb_class_ptr(klass);
02185           }
02186         }
02187       }
02188       if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT;
02189       regs[GETARG_A(i)] = mrb_obj_value(p);
02190       ARENA_RESTORE(mrb, ai);
02191       NEXT;
02192     }
02193 
02194     CASE(OP_OCLASS) {
02195       /* A      R(A) := ::Object */
02196       regs[GETARG_A(i)] = mrb_obj_value(mrb->object_class);
02197       NEXT;
02198     }
02199 
02200     CASE(OP_CLASS) {
02201       /* A B    R(A) := newclass(R(A),Syms(B),R(A+1)) */
02202       struct RClass *c = 0;
02203       int a = GETARG_A(i);
02204       mrb_value base, super;
02205       mrb_sym id = syms[GETARG_B(i)];
02206 
02207       base = regs[a];
02208       super = regs[a+1];
02209       if (mrb_nil_p(base)) {
02210         base = mrb_obj_value(mrb->c->ci->target_class);
02211       }
02212       c = mrb_vm_define_class(mrb, base, super, id);
02213       regs[a] = mrb_obj_value(c);
02214       ARENA_RESTORE(mrb, ai);
02215       NEXT;
02216     }
02217 
02218     CASE(OP_MODULE) {
02219       /* A B            R(A) := newmodule(R(A),Syms(B)) */
02220       struct RClass *c = 0;
02221       int a = GETARG_A(i);
02222       mrb_value base;
02223       mrb_sym id = syms[GETARG_B(i)];
02224 
02225       base = regs[a];
02226       if (mrb_nil_p(base)) {
02227         base = mrb_obj_value(mrb->c->ci->target_class);
02228       }
02229       c = mrb_vm_define_module(mrb, base, id);
02230       regs[a] = mrb_obj_value(c);
02231       ARENA_RESTORE(mrb, ai);
02232       NEXT;
02233     }
02234 
02235     CASE(OP_EXEC) {
02236       /* A Bx   R(A) := blockexec(R(A),SEQ[Bx]) */
02237       int a = GETARG_A(i);
02238       mrb_callinfo *ci;
02239       mrb_value recv = regs[a];
02240       struct RProc *p;
02241 
02242       /* prepare stack */
02243       ci = cipush(mrb);
02244       ci->pc = pc + 1;
02245       ci->acc = a;
02246       ci->mid = 0;
02247       ci->stackent = mrb->c->stack;
02248       ci->argc = 0;
02249       ci->target_class = mrb_class_ptr(recv);
02250 
02251       /* prepare stack */
02252       mrb->c->stack += a;
02253 
02254       p = mrb_proc_new(mrb, irep->reps[GETARG_Bx(i)]);
02255       p->target_class = ci->target_class;
02256       ci->proc = p;
02257 
02258       if (MRB_PROC_CFUNC_P(p)) {
02259         ci->nregs = 0;
02260         mrb->c->stack[0] = p->body.func(mrb, recv);
02261         mrb_gc_arena_restore(mrb, ai);
02262         if (mrb->exc) goto L_RAISE;
02263         /* pop stackpos */
02264         regs = mrb->c->stack = mrb->c->ci->stackent;
02265         cipop(mrb);
02266         NEXT;
02267       }
02268       else {
02269         irep = p->body.irep;
02270         pool = irep->pool;
02271         syms = irep->syms;
02272         stack_extend(mrb, irep->nregs, 1);
02273         ci->nregs = irep->nregs;
02274         regs = mrb->c->stack;
02275         pc = irep->iseq;
02276         JUMP;
02277       }
02278     }
02279 
02280     CASE(OP_METHOD) {
02281       /* A B            R(A).newmethod(Syms(B),R(A+1)) */
02282       int a = GETARG_A(i);
02283       struct RClass *c = mrb_class_ptr(regs[a]);
02284 
02285       mrb_define_method_vm(mrb, c, syms[GETARG_B(i)], regs[a+1]);
02286       ARENA_RESTORE(mrb, ai);
02287       NEXT;
02288     }
02289 
02290     CASE(OP_SCLASS) {
02291       /* A B    R(A) := R(B).singleton_class */
02292       regs[GETARG_A(i)] = mrb_singleton_class(mrb, regs[GETARG_B(i)]);
02293       ARENA_RESTORE(mrb, ai);
02294       NEXT;
02295     }
02296 
02297     CASE(OP_TCLASS) {
02298       /* A      R(A) := target_class */
02299       if (!mrb->c->ci->target_class) {
02300         mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module");
02301         mrb->exc = mrb_obj_ptr(exc);
02302         goto L_RAISE;
02303       }
02304       regs[GETARG_A(i)] = mrb_obj_value(mrb->c->ci->target_class);
02305       NEXT;
02306     }
02307 
02308     CASE(OP_RANGE) {
02309       /* A B C  R(A) := range_new(R(B),R(B+1),C) */
02310       int b = GETARG_B(i);
02311       regs[GETARG_A(i)] = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i));
02312       ARENA_RESTORE(mrb, ai);
02313       NEXT;
02314     }
02315 
02316     CASE(OP_DEBUG) {
02317       /* A B C    debug print R(A),R(B),R(C) */
02318 #ifdef ENABLE_DEBUG
02319       mrb->debug_op_hook(mrb, irep, pc, regs);
02320 #else
02321 #ifdef ENABLE_STDIO
02322       printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i));
02323 #else
02324       abort();
02325 #endif
02326 #endif
02327       NEXT;
02328     }
02329 
02330     CASE(OP_STOP) {
02331       /*        stop VM */
02332     L_STOP:
02333       {
02334         int eidx_stop = mrb->c->ci == mrb->c->cibase ? 0 : mrb->c->ci[-1].eidx;
02335         int eidx = mrb->c->ci->eidx;
02336         while (eidx > eidx_stop) {
02337           ecall(mrb, --eidx);
02338         }
02339       }
02340       ERR_PC_CLR(mrb);
02341       mrb->jmp = prev_jmp;
02342       if (mrb->exc) {
02343         return mrb_obj_value(mrb->exc);
02344       }
02345       return regs[irep->nlocals];
02346     }
02347 
02348     CASE(OP_ERR) {
02349       /* Bx     raise RuntimeError with message Lit(Bx) */
02350       mrb_value msg = mrb_str_dup(mrb, pool[GETARG_Bx(i)]);
02351       mrb_value exc;
02352 
02353       if (GETARG_A(i) == 0) {
02354         exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, msg);
02355       }
02356       else {
02357         exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg);
02358       }
02359       mrb->exc = mrb_obj_ptr(exc);
02360       goto L_RAISE;
02361     }
02362   }
02363   END_DISPATCH;
02364 
02365   }
02366   MRB_CATCH(&c_jmp) {
02367     exc_catched = TRUE;
02368     goto RETRY_TRY_BLOCK;
02369   }
02370   MRB_END_EXC(&c_jmp);
02371 }
02372 
02373 MRB_API mrb_value
02374 mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
02375 {
02376   return mrb_context_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */
02377 }
02378 
02379 MRB_API mrb_value
02380 mrb_toplevel_run_keep(mrb_state *mrb, struct RProc *proc, unsigned int stack_keep)
02381 {
02382   mrb_callinfo *ci;
02383   mrb_value v;
02384 
02385   if (!mrb->c->cibase || mrb->c->ci == mrb->c->cibase) {
02386     return mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep);
02387   }
02388   ci = cipush(mrb);
02389   ci->nregs = 1;   /* protect the receiver */
02390   ci->acc = CI_ACC_SKIP;
02391   ci->target_class = mrb->object_class;
02392   v = mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep);
02393   cipop(mrb);
02394 
02395   return v;
02396 }
02397 
02398 MRB_API mrb_value
02399 mrb_toplevel_run(mrb_state *mrb, struct RProc *proc)
02400 {
02401   return mrb_toplevel_run_keep(mrb, proc, 0);
02402 }
02403