1 /*
2 ** vm.c - virtual machine for mruby
3 **
4 ** See Copyright Notice in mruby.h
5 */
6 
7 #include <stddef.h>
8 #include <stdarg.h>
9 #include <math.h>
10 #include <mruby.h>
11 #include <mruby/array.h>
12 #include <mruby/class.h>
13 #include <mruby/hash.h>
14 #include <mruby/irep.h>
15 #include <mruby/numeric.h>
16 #include <mruby/proc.h>
17 #include <mruby/range.h>
18 #include <mruby/string.h>
19 #include <mruby/variable.h>
20 #include <mruby/error.h>
21 #include <mruby/opcode.h>
22 #include "value_array.h"
23 #include <mruby/throw.h>
24 
25 #ifdef MRB_DISABLE_STDIO
26 #if defined(__cplusplus)
27 extern "C" {
28 #endif
29 void abort(void);
30 #if defined(__cplusplus)
31 }  /* extern "C" { */
32 #endif
33 #endif
34 
35 #define STACK_INIT_SIZE 128
36 #define CALLINFO_INIT_SIZE 32
37 
38 #ifndef ENSURE_STACK_INIT_SIZE
39 #define ENSURE_STACK_INIT_SIZE 16
40 #endif
41 
42 #ifndef RESCUE_STACK_INIT_SIZE
43 #define RESCUE_STACK_INIT_SIZE 16
44 #endif
45 
46 /* Define amount of linear stack growth. */
47 #ifndef MRB_STACK_GROWTH
48 #define MRB_STACK_GROWTH 128
49 #endif
50 
51 /* Maximum mrb_funcall() depth. Should be set lower on memory constrained systems. */
52 #ifndef MRB_FUNCALL_DEPTH_MAX
53 #define MRB_FUNCALL_DEPTH_MAX 512
54 #endif
55 
56 /* Maximum depth of ecall() recursion. */
57 #ifndef MRB_ECALL_DEPTH_MAX
58 #define MRB_ECALL_DEPTH_MAX 512
59 #endif
60 
61 /* Maximum stack depth. Should be set lower on memory constrained systems.
62 The value below allows about 60000 recursive calls in the simplest case. */
63 #ifndef MRB_STACK_MAX
64 #define MRB_STACK_MAX (0x40000 - MRB_STACK_GROWTH)
65 #endif
66 
67 #ifdef VM_DEBUG
68 # define DEBUG(x) (x)
69 #else
70 # define DEBUG(x)
71 #endif
72 
73 
74 #ifndef MRB_GC_FIXED_ARENA
75 static void
mrb_gc_arena_shrink(mrb_state * mrb,int idx)76 mrb_gc_arena_shrink(mrb_state *mrb, int idx)
77 {
78   mrb_gc *gc = &mrb->gc;
79   int capa = gc->arena_capa;
80 
81   if (idx < capa / 4) {
82     capa >>= 2;
83     if (capa < MRB_GC_ARENA_SIZE) {
84       capa = MRB_GC_ARENA_SIZE;
85     }
86     if (capa != gc->arena_capa) {
87       gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*capa);
88       gc->arena_capa = capa;
89     }
90   }
91 }
92 #else
93 #define mrb_gc_arena_shrink(mrb,idx)
94 #endif
95 
96 #define CALL_MAXARGS 127
97 
98 void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args);
99 
100 static inline void
stack_clear(mrb_value * from,size_t count)101 stack_clear(mrb_value *from, size_t count)
102 {
103 #ifndef MRB_NAN_BOXING
104   const mrb_value mrb_value_zero = { { 0 } };
105 
106   while (count-- > 0) {
107     *from++ = mrb_value_zero;
108   }
109 #else
110   while (count-- > 0) {
111     SET_NIL_VALUE(*from);
112     from++;
113   }
114 #endif
115 }
116 
117 static inline void
stack_copy(mrb_value * dst,const mrb_value * src,size_t size)118 stack_copy(mrb_value *dst, const mrb_value *src, size_t size)
119 {
120   while (size-- > 0) {
121     *dst++ = *src++;
122   }
123 }
124 
125 static void
stack_init(mrb_state * mrb)126 stack_init(mrb_state *mrb)
127 {
128   struct mrb_context *c = mrb->c;
129 
130   /* mrb_assert(mrb->stack == NULL); */
131   c->stbase = (mrb_value *)mrb_calloc(mrb, STACK_INIT_SIZE, sizeof(mrb_value));
132   c->stend = c->stbase + STACK_INIT_SIZE;
133   c->stack = c->stbase;
134 
135   /* mrb_assert(ci == NULL); */
136   c->cibase = (mrb_callinfo *)mrb_calloc(mrb, CALLINFO_INIT_SIZE, sizeof(mrb_callinfo));
137   c->ciend = c->cibase + CALLINFO_INIT_SIZE;
138   c->ci = c->cibase;
139   c->ci->target_class = mrb->object_class;
140   c->ci->stackent = c->stack;
141 }
142 
143 static inline void
envadjust(mrb_state * mrb,mrb_value * oldbase,mrb_value * newbase,size_t oldsize)144 envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase, size_t oldsize)
145 {
146   mrb_callinfo *ci = mrb->c->cibase;
147 
148   if (newbase == oldbase) return;
149   while (ci <= mrb->c->ci) {
150     struct REnv *e = ci->env;
151     mrb_value *st;
152 
153     if (e && MRB_ENV_STACK_SHARED_P(e) &&
154         (st = e->stack) && oldbase <= st && st < oldbase+oldsize) {
155       ptrdiff_t off = e->stack - oldbase;
156 
157       e->stack = newbase + off;
158     }
159 
160     if (ci->proc && MRB_PROC_ENV_P(ci->proc) && ci->env != MRB_PROC_ENV(ci->proc)) {
161       e = MRB_PROC_ENV(ci->proc);
162 
163       if (e && MRB_ENV_STACK_SHARED_P(e) &&
164           (st = e->stack) && oldbase <= st && st < oldbase+oldsize) {
165         ptrdiff_t off = e->stack - oldbase;
166 
167         e->stack = newbase + off;
168       }
169     }
170 
171     ci->stackent = newbase + (ci->stackent - oldbase);
172     ci++;
173   }
174 }
175 
176 /** def rec ; $deep =+ 1 ; if $deep > 1000 ; return 0 ; end ; rec ; end  */
177 
178 static void
stack_extend_alloc(mrb_state * mrb,mrb_int room)179 stack_extend_alloc(mrb_state *mrb, mrb_int room)
180 {
181   mrb_value *oldbase = mrb->c->stbase;
182   mrb_value *newstack;
183   size_t oldsize = mrb->c->stend - mrb->c->stbase;
184   size_t size = oldsize;
185   size_t off = mrb->c->stack - mrb->c->stbase;
186 
187   if (off > size) size = off;
188 #ifdef MRB_STACK_EXTEND_DOUBLING
189   if ((size_t)room <= size)
190     size *= 2;
191   else
192     size += room;
193 #else
194   /* Use linear stack growth.
195      It is slightly slower than doubling the stack space,
196      but it saves memory on small devices. */
197   if (room <= MRB_STACK_GROWTH)
198     size += MRB_STACK_GROWTH;
199   else
200     size += room;
201 #endif
202 
203   newstack = (mrb_value *)mrb_realloc(mrb, mrb->c->stbase, sizeof(mrb_value) * size);
204   if (newstack == NULL) {
205     mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
206   }
207   stack_clear(&(newstack[oldsize]), size - oldsize);
208   envadjust(mrb, oldbase, newstack, oldsize);
209   mrb->c->stbase = newstack;
210   mrb->c->stack = mrb->c->stbase + off;
211   mrb->c->stend = mrb->c->stbase + size;
212 
213   /* Raise an exception if the new stack size will be too large,
214      to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */
215   if (size > MRB_STACK_MAX) {
216     mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
217   }
218 }
219 
220 MRB_API void
mrb_stack_extend(mrb_state * mrb,mrb_int room)221 mrb_stack_extend(mrb_state *mrb, mrb_int room)
222 {
223   if (mrb->c->stack + room >= mrb->c->stend) {
224     stack_extend_alloc(mrb, room);
225   }
226 }
227 
228 static inline struct REnv*
uvenv(mrb_state * mrb,int up)229 uvenv(mrb_state *mrb, int up)
230 {
231   struct RProc *proc = mrb->c->ci->proc;
232   struct REnv *e;
233 
234   while (up--) {
235     proc = proc->upper;
236     if (!proc) return NULL;
237   }
238   e = MRB_PROC_ENV(proc);
239   if (e) return e;              /* proc has enclosed env */
240   else {
241     mrb_callinfo *ci = mrb->c->ci;
242     mrb_callinfo *cb = mrb->c->cibase;
243 
244     while (cb <= ci) {
245       if (ci->proc == proc) {
246         return ci->env;
247       }
248       ci--;
249     }
250   }
251   return NULL;
252 }
253 
254 static inline struct RProc*
top_proc(mrb_state * mrb,struct RProc * proc)255 top_proc(mrb_state *mrb, struct RProc *proc)
256 {
257   while (proc->upper) {
258     if (MRB_PROC_SCOPE_P(proc) || MRB_PROC_STRICT_P(proc))
259       return proc;
260     proc = proc->upper;
261   }
262   return proc;
263 }
264 
265 #define CI_ACC_SKIP    -1
266 #define CI_ACC_DIRECT  -2
267 #define CI_ACC_RESUMED -3
268 
269 static inline mrb_callinfo*
cipush(mrb_state * mrb)270 cipush(mrb_state *mrb)
271 {
272   struct mrb_context *c = mrb->c;
273   static const mrb_callinfo ci_zero = { 0 };
274   mrb_callinfo *ci = c->ci;
275 
276   int ridx = ci->ridx;
277 
278   if (ci + 1 == c->ciend) {
279     ptrdiff_t size = ci - c->cibase;
280 
281     c->cibase = (mrb_callinfo *)mrb_realloc(mrb, c->cibase, sizeof(mrb_callinfo)*size*2);
282     c->ci = c->cibase + size;
283     c->ciend = c->cibase + size * 2;
284   }
285   ci = ++c->ci;
286   *ci = ci_zero;
287   ci->epos = mrb->c->eidx;
288   ci->ridx = ridx;
289 
290   return ci;
291 }
292 
293 void
mrb_env_unshare(mrb_state * mrb,struct REnv * e)294 mrb_env_unshare(mrb_state *mrb, struct REnv *e)
295 {
296   if (e == NULL) return;
297   else {
298     size_t len = (size_t)MRB_ENV_STACK_LEN(e);
299     mrb_value *p;
300 
301     if (!MRB_ENV_STACK_SHARED_P(e)) return;
302     if (e->cxt != mrb->c) return;
303     if (e == mrb->c->cibase->env) return; /* for mirb */
304     p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
305     if (len > 0) {
306       stack_copy(p, e->stack, len);
307     }
308     e->stack = p;
309     MRB_ENV_UNSHARE_STACK(e);
310     mrb_write_barrier(mrb, (struct RBasic *)e);
311   }
312 }
313 
314 static inline void
cipop(mrb_state * mrb)315 cipop(mrb_state *mrb)
316 {
317   struct mrb_context *c = mrb->c;
318   struct REnv *env = c->ci->env;
319 
320   c->ci--;
321   if (env) mrb_env_unshare(mrb, env);
322 }
323 
324 void mrb_exc_set(mrb_state *mrb, mrb_value exc);
325 
326 static void
ecall(mrb_state * mrb)327 ecall(mrb_state *mrb)
328 {
329   struct RProc *p;
330   struct mrb_context *c = mrb->c;
331   mrb_callinfo *ci = c->ci;
332   struct RObject *exc;
333   struct REnv *env;
334   ptrdiff_t cioff;
335   int ai = mrb_gc_arena_save(mrb);
336   uint16_t i = --c->eidx;
337   int nregs;
338 
339   if (i<0) return;
340   /* restrict total call depth of ecall() */
341   if (++mrb->ecall_nest > MRB_ECALL_DEPTH_MAX) {
342     mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
343   }
344   p = c->ensure[i];
345   if (!p) return;
346   mrb_assert(!MRB_PROC_CFUNC_P(p));
347   c->ensure[i] = NULL;
348   nregs = p->upper->body.irep->nregs;
349   if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc) &&
350       ci->proc->body.irep->nregs > nregs) {
351     nregs = ci->proc->body.irep->nregs;
352   }
353   cioff = ci - c->cibase;
354   ci = cipush(mrb);
355   ci->stackent = mrb->c->stack;
356   ci->mid = ci[-1].mid;
357   ci->acc = CI_ACC_SKIP;
358   ci->argc = 0;
359   ci->proc = p;
360   ci->target_class = MRB_PROC_TARGET_CLASS(p);
361   env = MRB_PROC_ENV(p);
362   mrb_assert(env);
363   c->stack += nregs;
364   exc = mrb->exc; mrb->exc = 0;
365   if (exc) {
366     mrb_gc_protect(mrb, mrb_obj_value(exc));
367   }
368   if (mrb->c->fib) {
369     mrb_gc_protect(mrb, mrb_obj_value(mrb->c->fib));
370   }
371   mrb_run(mrb, p, env->stack[0]);
372   mrb->c = c;
373   c->ci = c->cibase + cioff;
374   if (!mrb->exc) mrb->exc = exc;
375   mrb_gc_arena_restore(mrb, ai);
376   mrb->ecall_nest--;
377 }
378 
379 #ifndef MRB_FUNCALL_ARGC_MAX
380 #define MRB_FUNCALL_ARGC_MAX 16
381 #endif
382 
383 MRB_API mrb_value
mrb_funcall(mrb_state * mrb,mrb_value self,const char * name,mrb_int argc,...)384 mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, mrb_int argc, ...)
385 {
386   mrb_value argv[MRB_FUNCALL_ARGC_MAX];
387   va_list ap;
388   mrb_int i;
389   mrb_sym mid = mrb_intern_cstr(mrb, name);
390 
391   if (argc > MRB_FUNCALL_ARGC_MAX) {
392     mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" MRB_STRINGIZE(MRB_FUNCALL_ARGC_MAX) ")");
393   }
394 
395   va_start(ap, argc);
396   for (i = 0; i < argc; i++) {
397     argv[i] = va_arg(ap, mrb_value);
398   }
399   va_end(ap);
400   return mrb_funcall_argv(mrb, self, mid, argc, argv);
401 }
402 
403 static int
ci_nregs(mrb_callinfo * ci)404 ci_nregs(mrb_callinfo *ci)
405 {
406   struct RProc *p;
407   int n = 0;
408 
409   if (!ci) return 3;
410   p = ci->proc;
411   if (!p) {
412     if (ci->argc < 0) return 3;
413     return ci->argc+2;
414   }
415   if (!MRB_PROC_CFUNC_P(p) && p->body.irep) {
416     n = p->body.irep->nregs;
417   }
418   if (ci->argc < 0) {
419     if (n < 3) n = 3; /* self + args + blk */
420   }
421   if (ci->argc > n) {
422     n = ci->argc + 2; /* self + blk */
423   }
424   return n;
425 }
426 
427 MRB_API mrb_value
mrb_funcall_with_block(mrb_state * mrb,mrb_value self,mrb_sym mid,mrb_int argc,const mrb_value * argv,mrb_value blk)428 mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk)
429 {
430   mrb_value val;
431 
432   if (!mrb->jmp) {
433     struct mrb_jmpbuf c_jmp;
434     ptrdiff_t nth_ci = mrb->c->ci - mrb->c->cibase;
435 
436     MRB_TRY(&c_jmp) {
437       mrb->jmp = &c_jmp;
438       /* recursive call */
439       val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk);
440       mrb->jmp = 0;
441     }
442     MRB_CATCH(&c_jmp) { /* error */
443       while (nth_ci < (mrb->c->ci - mrb->c->cibase)) {
444         mrb->c->stack = mrb->c->ci->stackent;
445         cipop(mrb);
446       }
447       mrb->jmp = 0;
448       val = mrb_obj_value(mrb->exc);
449     }
450     MRB_END_EXC(&c_jmp);
451     mrb->jmp = 0;
452   }
453   else {
454     mrb_method_t m;
455     struct RClass *c;
456     mrb_callinfo *ci;
457     int n = ci_nregs(mrb->c->ci);
458     ptrdiff_t voff = -1;
459 
460     if (!mrb->c->stack) {
461       stack_init(mrb);
462     }
463     if (argc < 0) {
464       mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%S)", mrb_fixnum_value(argc));
465     }
466     c = mrb_class(mrb, self);
467     m = mrb_method_search_vm(mrb, &c, mid);
468     if (MRB_METHOD_UNDEF_P(m)) {
469       mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
470       mrb_value args = mrb_ary_new_from_values(mrb, argc, argv);
471       m = mrb_method_search_vm(mrb, &c, missing);
472       if (MRB_METHOD_UNDEF_P(m)) {
473         mrb_method_missing(mrb, mid, self, args);
474       }
475       mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
476       mrb_stack_extend(mrb, n+2);
477       mrb->c->stack[n+1] = args;
478       argc = -1;
479     }
480     if (mrb->c->ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) {
481       mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
482     }
483     ci = cipush(mrb);
484     ci->mid = mid;
485     ci->stackent = mrb->c->stack;
486     ci->argc = (int)argc;
487     ci->target_class = c;
488     mrb->c->stack = mrb->c->stack + n;
489     if (mrb->c->stbase <= argv && argv < mrb->c->stend) {
490       voff = argv - mrb->c->stbase;
491     }
492     if (MRB_METHOD_CFUNC_P(m)) {
493       mrb_stack_extend(mrb, argc + 2);
494     }
495     else if (argc >= CALL_MAXARGS) {
496       mrb_value args = mrb_ary_new_from_values(mrb, argc, argv);
497 
498       mrb_stack_extend(mrb, 3);
499       mrb->c->stack[1] = args;
500       ci->argc = -1;
501       argc = 1;
502     }
503     else {
504       struct RProc *p = MRB_METHOD_PROC(m);
505 
506       ci->proc = p;
507       if (argc < 0) argc = 1;
508       mrb_stack_extend(mrb, p->body.irep->nregs + argc);
509     }
510     if (voff >= 0) {
511       argv = mrb->c->stbase + voff;
512     }
513     mrb->c->stack[0] = self;
514     if (ci->argc > 0) {
515       stack_copy(mrb->c->stack+1, argv, argc);
516     }
517     mrb->c->stack[argc+1] = blk;
518 
519     if (MRB_METHOD_CFUNC_P(m)) {
520       int ai = mrb_gc_arena_save(mrb);
521 
522       ci->acc = CI_ACC_DIRECT;
523       if (MRB_METHOD_PROC_P(m)) {
524         ci->proc = MRB_METHOD_PROC(m);
525       }
526       val = MRB_METHOD_CFUNC(m)(mrb, self);
527       mrb->c->stack = mrb->c->ci->stackent;
528       cipop(mrb);
529       mrb_gc_arena_restore(mrb, ai);
530     }
531     else {
532       ci->acc = CI_ACC_SKIP;
533       val = mrb_run(mrb, MRB_METHOD_PROC(m), self);
534     }
535   }
536   mrb_gc_protect(mrb, val);
537   return val;
538 }
539 
540 MRB_API mrb_value
mrb_funcall_argv(mrb_state * mrb,mrb_value self,mrb_sym mid,mrb_int argc,const mrb_value * argv)541 mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv)
542 {
543   return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value());
544 }
545 
546 mrb_value
mrb_exec_irep(mrb_state * mrb,mrb_value self,struct RProc * p)547 mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p)
548 {
549   mrb_callinfo *ci = mrb->c->ci;
550   int keep, nregs;
551 
552   mrb->c->stack[0] = self;
553   ci->proc = p;
554   if (MRB_PROC_CFUNC_P(p)) {
555     return MRB_PROC_CFUNC(p)(mrb, self);
556   }
557   nregs = p->body.irep->nregs;
558   if (ci->argc < 0) keep = 3;
559   else keep = ci->argc + 2;
560   if (nregs < keep) {
561     mrb_stack_extend(mrb, keep);
562   }
563   else {
564     mrb_stack_extend(mrb, nregs);
565     stack_clear(mrb->c->stack+keep, nregs-keep);
566   }
567 
568   ci = cipush(mrb);
569   ci->target_class = 0;
570   ci->pc = p->body.irep->iseq;
571   ci->stackent = mrb->c->stack;
572   ci->acc = 0;
573 
574   return self;
575 }
576 
577 /* 15.3.1.3.4  */
578 /* 15.3.1.3.44 */
579 /*
580  *  call-seq:
581  *     obj.send(symbol [, args...])        -> obj
582  *     obj.__send__(symbol [, args...])      -> obj
583  *
584  *  Invokes the method identified by _symbol_, passing it any
585  *  arguments specified. You can use <code>__send__</code> if the name
586  *  +send+ clashes with an existing method in _obj_.
587  *
588  *     class Klass
589  *       def hello(*args)
590  *         "Hello " + args.join(' ')
591  *       end
592  *     end
593  *     k = Klass.new
594  *     k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"
595  */
596 MRB_API mrb_value
mrb_f_send(mrb_state * mrb,mrb_value self)597 mrb_f_send(mrb_state *mrb, mrb_value self)
598 {
599   mrb_sym name;
600   mrb_value block, *argv, *regs;
601   mrb_int argc, i, len;
602   mrb_method_t m;
603   struct RClass *c;
604   mrb_callinfo *ci;
605 
606   mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block);
607   ci = mrb->c->ci;
608   if (ci->acc < 0) {
609   funcall:
610     return mrb_funcall_with_block(mrb, self, name, argc, argv, block);
611   }
612 
613   c = mrb_class(mrb, self);
614   m = mrb_method_search_vm(mrb, &c, name);
615   if (MRB_METHOD_UNDEF_P(m)) {            /* call method_mising */
616     goto funcall;
617   }
618 
619   ci->mid = name;
620   ci->target_class = c;
621   regs = mrb->c->stack+1;
622   /* remove first symbol from arguments */
623   if (ci->argc >= 0) {
624     for (i=0,len=ci->argc; i<len; i++) {
625       regs[i] = regs[i+1];
626     }
627     ci->argc--;
628   }
629   else {                     /* variable length arguments */
630     mrb_ary_shift(mrb, regs[0]);
631   }
632 
633   if (MRB_METHOD_CFUNC_P(m)) {
634     if (MRB_METHOD_PROC_P(m)) {
635       ci->proc = MRB_METHOD_PROC(m);
636     }
637     return MRB_METHOD_CFUNC(m)(mrb, self);
638   }
639   return mrb_exec_irep(mrb, self, MRB_METHOD_PROC(m));
640 }
641 
642 static mrb_value
eval_under(mrb_state * mrb,mrb_value self,mrb_value blk,struct RClass * c)643 eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
644 {
645   struct RProc *p;
646   mrb_callinfo *ci;
647   int nregs;
648 
649   if (mrb_nil_p(blk)) {
650     mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
651   }
652   ci = mrb->c->ci;
653   if (ci->acc == CI_ACC_DIRECT) {
654     ci->target_class = c;
655     return mrb_yield_cont(mrb, blk, self, 1, &self);
656   }
657   ci->target_class = c;
658   p = mrb_proc_ptr(blk);
659   ci->proc = p;
660   ci->argc = 1;
661   ci->mid = ci[-1].mid;
662   if (MRB_PROC_CFUNC_P(p)) {
663     mrb_stack_extend(mrb, 3);
664     mrb->c->stack[0] = self;
665     mrb->c->stack[1] = self;
666     mrb->c->stack[2] = mrb_nil_value();
667     return MRB_PROC_CFUNC(p)(mrb, self);
668   }
669   nregs = p->body.irep->nregs;
670   if (nregs < 3) nregs = 3;
671   mrb_stack_extend(mrb, nregs);
672   mrb->c->stack[0] = self;
673   mrb->c->stack[1] = self;
674   stack_clear(mrb->c->stack+2, nregs-2);
675   ci = cipush(mrb);
676   ci->target_class = 0;
677   ci->pc = p->body.irep->iseq;
678   ci->stackent = mrb->c->stack;
679   ci->acc = 0;
680 
681   return self;
682 }
683 
684 /* 15.2.2.4.35 */
685 /*
686  *  call-seq:
687  *     mod.class_eval {| | block }  -> obj
688  *     mod.module_eval {| | block } -> obj
689  *
690  *  Evaluates block in the context of _mod_. This can
691  *  be used to add methods to a class. <code>module_eval</code> returns
692  *  the result of evaluating its argument.
693  */
694 mrb_value
mrb_mod_module_eval(mrb_state * mrb,mrb_value mod)695 mrb_mod_module_eval(mrb_state *mrb, mrb_value mod)
696 {
697   mrb_value a, b;
698 
699   if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
700     mrb_raise(mrb, E_NOTIMP_ERROR, "module_eval/class_eval with string not implemented");
701   }
702   return eval_under(mrb, mod, b, mrb_class_ptr(mod));
703 }
704 
705 /* 15.3.1.3.18 */
706 /*
707  *  call-seq:
708  *     obj.instance_eval {| | block }                       -> obj
709  *
710  *  Evaluates the given block,within  the context of the receiver (_obj_).
711  *  In order to set the context, the variable +self+ is set to _obj_ while
712  *  the code is executing, giving the code access to _obj_'s
713  *  instance variables. In the version of <code>instance_eval</code>
714  *  that takes a +String+, the optional second and third
715  *  parameters supply a filename and starting line number that are used
716  *  when reporting compilation errors.
717  *
718  *     class KlassWithSecret
719  *       def initialize
720  *         @secret = 99
721  *       end
722  *     end
723  *     k = KlassWithSecret.new
724  *     k.instance_eval { @secret }   #=> 99
725  */
726 mrb_value
mrb_obj_instance_eval(mrb_state * mrb,mrb_value self)727 mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
728 {
729   mrb_value a, b;
730   mrb_value cv;
731   struct RClass *c;
732 
733   if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
734     mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented");
735   }
736   switch (mrb_type(self)) {
737   case MRB_TT_SYMBOL:
738   case MRB_TT_FIXNUM:
739 #ifndef MRB_WITHOUT_FLOAT
740   case MRB_TT_FLOAT:
741 #endif
742     c = 0;
743     break;
744   default:
745     cv = mrb_singleton_class(mrb, self);
746     c = mrb_class_ptr(cv);
747     break;
748   }
749   return eval_under(mrb, self, b, c);
750 }
751 
752 MRB_API mrb_value
mrb_yield_with_class(mrb_state * mrb,mrb_value b,mrb_int argc,const mrb_value * argv,mrb_value self,struct RClass * c)753 mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c)
754 {
755   struct RProc *p;
756   mrb_sym mid = mrb->c->ci->mid;
757   mrb_callinfo *ci;
758   mrb_value val;
759   int n;
760 
761   if (mrb_nil_p(b)) {
762     mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
763   }
764   ci = mrb->c->ci;
765   n = ci_nregs(ci);
766   if (ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) {
767     mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
768   }
769   p = mrb_proc_ptr(b);
770   ci = cipush(mrb);
771   ci->mid = mid;
772   ci->proc = p;
773   ci->stackent = mrb->c->stack;
774   ci->argc = (int)argc;
775   ci->target_class = c;
776   ci->acc = CI_ACC_SKIP;
777   n = MRB_PROC_CFUNC_P(p) ? (int)(argc+2) : p->body.irep->nregs;
778   mrb->c->stack = mrb->c->stack + n;
779   mrb_stack_extend(mrb, n);
780 
781   mrb->c->stack[0] = self;
782   if (argc > 0) {
783     stack_copy(mrb->c->stack+1, argv, argc);
784   }
785   mrb->c->stack[argc+1] = mrb_nil_value();
786 
787   if (MRB_PROC_CFUNC_P(p)) {
788     val = MRB_PROC_CFUNC(p)(mrb, self);
789     mrb->c->stack = mrb->c->ci->stackent;
790     cipop(mrb);
791   }
792   else {
793     val = mrb_run(mrb, p, self);
794   }
795   return val;
796 }
797 
798 MRB_API mrb_value
mrb_yield_argv(mrb_state * mrb,mrb_value b,mrb_int argc,const mrb_value * argv)799 mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv)
800 {
801   struct RProc *p = mrb_proc_ptr(b);
802 
803   return mrb_yield_with_class(mrb, b, argc, argv, MRB_PROC_ENV(p)->stack[0], MRB_PROC_TARGET_CLASS(p));
804 }
805 
806 MRB_API mrb_value
mrb_yield(mrb_state * mrb,mrb_value b,mrb_value arg)807 mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg)
808 {
809   struct RProc *p = mrb_proc_ptr(b);
810 
811   return mrb_yield_with_class(mrb, b, 1, &arg, MRB_PROC_ENV(p)->stack[0], MRB_PROC_TARGET_CLASS(p));
812 }
813 
814 mrb_value
mrb_yield_cont(mrb_state * mrb,mrb_value b,mrb_value self,mrb_int argc,const mrb_value * argv)815 mrb_yield_cont(mrb_state *mrb, mrb_value b, mrb_value self, mrb_int argc, const mrb_value *argv)
816 {
817   struct RProc *p;
818   mrb_callinfo *ci;
819 
820   if (mrb_nil_p(b)) {
821     mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
822   }
823   if (mrb_type(b) != MRB_TT_PROC) {
824     mrb_raise(mrb, E_TYPE_ERROR, "not a block");
825   }
826 
827   p = mrb_proc_ptr(b);
828   ci = mrb->c->ci;
829 
830   mrb_stack_extend(mrb, 3);
831   mrb->c->stack[1] = mrb_ary_new_from_values(mrb, argc, argv);
832   mrb->c->stack[2] = mrb_nil_value();
833   ci->argc = -1;
834   return mrb_exec_irep(mrb, self, p);
835 }
836 
837 mrb_value
mrb_mod_s_nesting(mrb_state * mrb,mrb_value mod)838 mrb_mod_s_nesting(mrb_state *mrb, mrb_value mod)
839 {
840   struct RProc *proc;
841   mrb_value ary;
842   struct RClass *c = NULL;
843 
844   mrb_get_args(mrb, "");
845   ary = mrb_ary_new(mrb);
846   proc = mrb->c->ci[-1].proc;   /* callee proc */
847   mrb_assert(!MRB_PROC_CFUNC_P(proc));
848   while (proc) {
849     if (MRB_PROC_SCOPE_P(proc)) {
850       struct RClass *c2 = MRB_PROC_TARGET_CLASS(proc);
851 
852       if (c2 != c) {
853         c = c2;
854         mrb_ary_push(mrb, ary, mrb_obj_value(c));
855       }
856     }
857     proc = proc->upper;
858   }
859   return ary;
860 }
861 
862 static struct RBreak*
break_new(mrb_state * mrb,struct RProc * p,mrb_value val)863 break_new(mrb_state *mrb, struct RProc *p, mrb_value val)
864 {
865   struct RBreak *brk;
866 
867   brk = (struct RBreak*)mrb_obj_alloc(mrb, MRB_TT_BREAK, NULL);
868   brk->proc = p;
869   brk->val = val;
870 
871   return brk;
872 }
873 
874 typedef enum {
875   LOCALJUMP_ERROR_RETURN = 0,
876   LOCALJUMP_ERROR_BREAK = 1,
877   LOCALJUMP_ERROR_YIELD = 2
878 } localjump_error_kind;
879 
880 static void
localjump_error(mrb_state * mrb,localjump_error_kind kind)881 localjump_error(mrb_state *mrb, localjump_error_kind kind)
882 {
883   char kind_str[3][7] = { "return", "break", "yield" };
884   char kind_str_len[] = { 6, 5, 5 };
885   static const char lead[] = "unexpected ";
886   mrb_value msg;
887   mrb_value exc;
888 
889   msg = mrb_str_new_capa(mrb, sizeof(lead) + 7);
890   mrb_str_cat(mrb, msg, lead, sizeof(lead) - 1);
891   mrb_str_cat(mrb, msg, kind_str[kind], kind_str_len[kind]);
892   exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg);
893   mrb_exc_set(mrb, exc);
894 }
895 
896 static void
argnum_error(mrb_state * mrb,mrb_int num)897 argnum_error(mrb_state *mrb, mrb_int num)
898 {
899   mrb_value exc;
900   mrb_value str;
901   mrb_int argc = mrb->c->ci->argc;
902 
903   if (argc < 0) {
904     mrb_value args = mrb->c->stack[1];
905     if (mrb_array_p(args)) {
906       argc = RARRAY_LEN(args);
907     }
908   }
909   if (mrb->c->ci->mid) {
910     str = mrb_format(mrb, "'%S': wrong number of arguments (%S for %S)",
911                   mrb_sym2str(mrb, mrb->c->ci->mid),
912                   mrb_fixnum_value(argc), mrb_fixnum_value(num));
913   }
914   else {
915     str = mrb_format(mrb, "wrong number of arguments (%S for %S)",
916                      mrb_fixnum_value(argc), mrb_fixnum_value(num));
917   }
918   exc = mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str);
919   mrb_exc_set(mrb, exc);
920 }
921 
922 #define ERR_PC_SET(mrb) mrb->c->ci->err = pc0;
923 #define ERR_PC_CLR(mrb) mrb->c->ci->err = 0;
924 #ifdef MRB_ENABLE_DEBUG_HOOK
925 #define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs));
926 #else
927 #define CODE_FETCH_HOOK(mrb, irep, pc, regs)
928 #endif
929 
930 #ifdef MRB_BYTECODE_DECODE_OPTION
931 #define BYTECODE_DECODER(x) ((mrb)->bytecode_decoder)?(mrb)->bytecode_decoder((mrb), (x)):(x)
932 #else
933 #define BYTECODE_DECODER(x) (x)
934 #endif
935 
936 #ifndef MRB_DISABLE_DIRECT_THREADING
937 #if defined __GNUC__ || defined __clang__ || defined __INTEL_COMPILER
938 #define DIRECT_THREADED
939 #endif
940 #endif /* ifndef MRB_DISABLE_DIRECT_THREADING */
941 
942 #ifndef DIRECT_THREADED
943 
944 #define INIT_DISPATCH for (;;) { insn = BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (insn) {
945 #define CASE(insn,ops) case insn: pc0=pc++; FETCH_ ## ops ();; L_ ## insn ## _BODY:
946 #define NEXT break
947 #define JUMP NEXT
948 #define END_DISPATCH }}
949 
950 #else
951 
952 #define INIT_DISPATCH JUMP; return mrb_nil_value();
953 #define CASE(insn,ops) L_ ## insn: pc0=pc++; FETCH_ ## ops (); L_ ## insn ## _BODY:
954 #define NEXT insn=BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[insn]
955 #define JUMP NEXT
956 
957 #define END_DISPATCH
958 
959 #endif
960 
961 MRB_API mrb_value
mrb_vm_run(mrb_state * mrb,struct RProc * proc,mrb_value self,unsigned int stack_keep)962 mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep)
963 {
964   mrb_irep *irep = proc->body.irep;
965   mrb_value result;
966   struct mrb_context *c = mrb->c;
967   ptrdiff_t cioff = c->ci - c->cibase;
968   unsigned int nregs = irep->nregs;
969 
970   if (!c->stack) {
971     stack_init(mrb);
972   }
973   if (stack_keep > nregs)
974     nregs = stack_keep;
975   mrb_stack_extend(mrb, nregs);
976   stack_clear(c->stack + stack_keep, nregs - stack_keep);
977   c->stack[0] = self;
978   result = mrb_vm_exec(mrb, proc, irep->iseq);
979   if (mrb->c != c) {
980     if (mrb->c->fib) {
981       mrb_write_barrier(mrb, (struct RBasic*)mrb->c->fib);
982     }
983     mrb->c = c;
984   }
985   else if (c->ci - c->cibase > cioff) {
986     c->ci = c->cibase + cioff;
987   }
988   return result;
989 }
990 
991 static mrb_bool
check_target_class(mrb_state * mrb)992 check_target_class(mrb_state *mrb)
993 {
994   if (!mrb->c->ci->target_class) {
995     mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module");
996     mrb_exc_set(mrb, exc);
997     return FALSE;
998   }
999   return TRUE;
1000 }
1001 
1002 void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self);
1003 
1004 MRB_API mrb_value
mrb_vm_exec(mrb_state * mrb,struct RProc * proc,mrb_code * pc)1005 mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
1006 {
1007   /* mrb_assert(mrb_proc_cfunc_p(proc)) */
1008   mrb_code *pc0 = pc;
1009   mrb_irep *irep = proc->body.irep;
1010   mrb_value *pool = irep->pool;
1011   mrb_sym *syms = irep->syms;
1012   mrb_code insn;
1013   int ai = mrb_gc_arena_save(mrb);
1014   struct mrb_jmpbuf *prev_jmp = mrb->jmp;
1015   struct mrb_jmpbuf c_jmp;
1016   uint32_t a;
1017   uint16_t b;
1018   uint8_t c;
1019   mrb_sym mid;
1020 
1021 #ifdef DIRECT_THREADED
1022   static void *optable[] = {
1023 #define OPCODE(x,_) &&L_OP_ ## x,
1024 #include "mruby/ops.h"
1025 #undef OPCODE
1026   };
1027 #endif
1028 
1029   mrb_bool exc_catched = FALSE;
1030 RETRY_TRY_BLOCK:
1031 
1032   MRB_TRY(&c_jmp) {
1033 
1034   if (exc_catched) {
1035     exc_catched = FALSE;
1036     mrb_gc_arena_restore(mrb, ai);
1037     if (mrb->exc && mrb->exc->tt == MRB_TT_BREAK)
1038       goto L_BREAK;
1039     goto L_RAISE;
1040   }
1041   mrb->jmp = &c_jmp;
1042   mrb->c->ci->proc = proc;
1043 
1044 #define regs (mrb->c->stack)
1045   INIT_DISPATCH {
1046     CASE(OP_NOP, Z) {
1047       /* do nothing */
1048       NEXT;
1049     }
1050 
1051     CASE(OP_MOVE, BB) {
1052       regs[a] = regs[b];
1053       NEXT;
1054     }
1055 
1056     CASE(OP_LOADL, BB) {
1057 #ifdef MRB_WORD_BOXING
1058       mrb_value val = pool[b];
1059 #ifndef MRB_WITHOUT_FLOAT
1060       if (mrb_float_p(val)) {
1061         val = mrb_float_value(mrb, mrb_float(val));
1062       }
1063 #endif
1064       regs[a] = val;
1065 #else
1066       regs[a] = pool[b];
1067 #endif
1068       NEXT;
1069     }
1070 
1071     CASE(OP_LOADI, BB) {
1072       SET_INT_VALUE(regs[a], b);
1073       NEXT;
1074     }
1075 
1076     CASE(OP_LOADINEG, BB) {
1077       SET_INT_VALUE(regs[a], -b);
1078       NEXT;
1079     }
1080 
1081     CASE(OP_LOADI__1,B) goto L_LOADI;
1082     CASE(OP_LOADI_0,B) goto L_LOADI;
1083     CASE(OP_LOADI_1,B) goto L_LOADI;
1084     CASE(OP_LOADI_2,B) goto L_LOADI;
1085     CASE(OP_LOADI_3,B) goto L_LOADI;
1086     CASE(OP_LOADI_4,B) goto L_LOADI;
1087     CASE(OP_LOADI_5,B) goto L_LOADI;
1088     CASE(OP_LOADI_6,B) goto L_LOADI;
1089     CASE(OP_LOADI_7, B) {
1090     L_LOADI:
1091       SET_INT_VALUE(regs[a], (mrb_int)insn - (mrb_int)OP_LOADI_0);
1092       NEXT;
1093     }
1094 
1095     CASE(OP_LOADSYM, BB) {
1096       SET_SYM_VALUE(regs[a], syms[b]);
1097       NEXT;
1098     }
1099 
1100     CASE(OP_LOADNIL, B) {
1101       SET_NIL_VALUE(regs[a]);
1102       NEXT;
1103     }
1104 
1105     CASE(OP_LOADSELF, B) {
1106       regs[a] = regs[0];
1107       NEXT;
1108     }
1109 
1110     CASE(OP_LOADT, B) {
1111       SET_TRUE_VALUE(regs[a]);
1112       NEXT;
1113     }
1114 
1115     CASE(OP_LOADF, B) {
1116       SET_FALSE_VALUE(regs[a]);
1117       NEXT;
1118     }
1119 
1120     CASE(OP_GETGV, BB) {
1121       mrb_value val = mrb_gv_get(mrb, syms[b]);
1122       regs[a] = val;
1123       NEXT;
1124     }
1125 
1126     CASE(OP_SETGV, BB) {
1127       mrb_gv_set(mrb, syms[b], regs[a]);
1128       NEXT;
1129     }
1130 
1131     CASE(OP_GETSV, BB) {
1132       mrb_value val = mrb_vm_special_get(mrb, b);
1133       regs[a] = val;
1134       NEXT;
1135     }
1136 
1137     CASE(OP_SETSV, BB) {
1138       mrb_vm_special_set(mrb, b, regs[a]);
1139       NEXT;
1140     }
1141 
1142     CASE(OP_GETIV, BB) {
1143       regs[a] = mrb_iv_get(mrb, regs[0], syms[b]);
1144       NEXT;
1145     }
1146 
1147     CASE(OP_SETIV, BB) {
1148       mrb_iv_set(mrb, regs[0], syms[b], regs[a]);
1149       NEXT;
1150     }
1151 
1152     CASE(OP_GETCV, BB) {
1153       mrb_value val;
1154       ERR_PC_SET(mrb);
1155       val = mrb_vm_cv_get(mrb, syms[b]);
1156       ERR_PC_CLR(mrb);
1157       regs[a] = val;
1158       NEXT;
1159     }
1160 
1161     CASE(OP_SETCV, BB) {
1162       mrb_vm_cv_set(mrb, syms[b], regs[a]);
1163       NEXT;
1164     }
1165 
1166     CASE(OP_GETCONST, BB) {
1167       mrb_value val;
1168       mrb_sym sym = syms[b];
1169 
1170       ERR_PC_SET(mrb);
1171       val = mrb_vm_const_get(mrb, sym);
1172       ERR_PC_CLR(mrb);
1173       regs[a] = val;
1174       NEXT;
1175     }
1176 
1177     CASE(OP_SETCONST, BB) {
1178       mrb_vm_const_set(mrb, syms[b], regs[a]);
1179       NEXT;
1180     }
1181 
1182     CASE(OP_GETMCNST, BB) {
1183       mrb_value val;
1184 
1185       ERR_PC_SET(mrb);
1186       val = mrb_const_get(mrb, regs[a], syms[b]);
1187       ERR_PC_CLR(mrb);
1188       regs[a] = val;
1189       NEXT;
1190     }
1191 
1192     CASE(OP_SETMCNST, BB) {
1193       mrb_const_set(mrb, regs[a+1], syms[b], regs[a]);
1194       NEXT;
1195     }
1196 
1197     CASE(OP_GETUPVAR, BBB) {
1198       mrb_value *regs_a = regs + a;
1199       struct REnv *e = uvenv(mrb, c);
1200 
1201       if (e && b < MRB_ENV_STACK_LEN(e)) {
1202         *regs_a = e->stack[b];
1203       }
1204       else {
1205         *regs_a = mrb_nil_value();
1206       }
1207       NEXT;
1208     }
1209 
1210     CASE(OP_SETUPVAR, BBB) {
1211       struct REnv *e = uvenv(mrb, c);
1212 
1213       if (e) {
1214         mrb_value *regs_a = regs + a;
1215 
1216         if (b < MRB_ENV_STACK_LEN(e)) {
1217           e->stack[b] = *regs_a;
1218           mrb_write_barrier(mrb, (struct RBasic*)e);
1219         }
1220       }
1221       NEXT;
1222     }
1223 
1224     CASE(OP_JMP, S) {
1225       pc = irep->iseq+a;
1226       JUMP;
1227     }
1228     CASE(OP_JMPIF, BS) {
1229       if (mrb_test(regs[a])) {
1230         pc = irep->iseq+b;
1231         JUMP;
1232       }
1233       NEXT;
1234     }
1235     CASE(OP_JMPNOT, BS) {
1236       if (!mrb_test(regs[a])) {
1237         pc = irep->iseq+b;
1238         JUMP;
1239       }
1240       NEXT;
1241     }
1242     CASE(OP_JMPNIL, BS) {
1243       if (mrb_nil_p(regs[a])) {
1244         pc = irep->iseq+b;
1245         JUMP;
1246       }
1247       NEXT;
1248     }
1249 
1250     CASE(OP_ONERR, S) {
1251       /* check rescue stack */
1252       if (mrb->c->ci->ridx == UINT16_MAX-1) {
1253         mrb_value exc = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "too many nested rescues");
1254         mrb_exc_set(mrb, exc);
1255         goto L_RAISE;
1256       }
1257       /* expand rescue stack */
1258       if (mrb->c->rsize <= mrb->c->ci->ridx) {
1259         if (mrb->c->rsize == 0) mrb->c->rsize = RESCUE_STACK_INIT_SIZE;
1260         else {
1261           mrb->c->rsize *= 2;
1262           if (mrb->c->rsize <= mrb->c->ci->ridx) {
1263             mrb->c->rsize = UINT16_MAX;
1264           }
1265         }
1266         mrb->c->rescue = (uint16_t*)mrb_realloc(mrb, mrb->c->rescue, sizeof(uint16_t)*mrb->c->rsize);
1267       }
1268       /* push rescue stack */
1269       mrb->c->rescue[mrb->c->ci->ridx++] = a;
1270       NEXT;
1271     }
1272 
1273     CASE(OP_EXCEPT, B) {
1274       mrb_value exc = mrb_obj_value(mrb->exc);
1275       mrb->exc = 0;
1276       regs[a] = exc;
1277       NEXT;
1278     }
1279     CASE(OP_RESCUE, BB) {
1280       mrb_value exc = regs[a];  /* exc on stack */
1281       mrb_value e = regs[b];
1282       struct RClass *ec;
1283 
1284       switch (mrb_type(e)) {
1285       case MRB_TT_CLASS:
1286       case MRB_TT_MODULE:
1287         break;
1288       default:
1289         {
1290           mrb_value exc;
1291 
1292           exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR,
1293                                     "class or module required for rescue clause");
1294           mrb_exc_set(mrb, exc);
1295           goto L_RAISE;
1296         }
1297       }
1298       ec = mrb_class_ptr(e);
1299       regs[b] = mrb_bool_value(mrb_obj_is_kind_of(mrb, exc, ec));
1300       NEXT;
1301     }
1302 
1303     CASE(OP_POPERR, B) {
1304       mrb->c->ci->ridx -= a;
1305       NEXT;
1306     }
1307 
1308     CASE(OP_RAISE, B) {
1309       mrb_exc_set(mrb, regs[a]);
1310       goto L_RAISE;
1311     }
1312 
1313     CASE(OP_EPUSH, B) {
1314       struct RProc *p;
1315 
1316       p = mrb_closure_new(mrb, irep->reps[a]);
1317       /* check ensure stack */
1318       if (mrb->c->eidx == UINT16_MAX-1) {
1319         mrb_value exc = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "too many nested ensures");
1320         mrb_exc_set(mrb, exc);
1321         goto L_RAISE;
1322       }
1323       /* expand ensure stack */
1324       if (mrb->c->esize <= mrb->c->eidx+1) {
1325         if (mrb->c->esize == 0) mrb->c->esize = ENSURE_STACK_INIT_SIZE;
1326         else {
1327           mrb->c->esize *= 2;
1328           if (mrb->c->esize <= mrb->c->eidx) {
1329             mrb->c->esize = UINT16_MAX;
1330           }
1331         }
1332         mrb->c->ensure = (struct RProc**)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*)*mrb->c->esize);
1333       }
1334       /* push ensure stack */
1335       mrb->c->ensure[mrb->c->eidx++] = p;
1336       mrb->c->ensure[mrb->c->eidx] = NULL;
1337       mrb_gc_arena_restore(mrb, ai);
1338       NEXT;
1339     }
1340 
1341     CASE(OP_EPOP, B) {
1342       mrb_callinfo *ci = mrb->c->ci;
1343       unsigned int n, epos = ci->epos;
1344       mrb_value self = regs[0];
1345       struct RClass *target_class = ci->target_class;
1346 
1347       if (mrb->c->eidx <= epos) {
1348         NEXT;
1349       }
1350 
1351       if (a > (int)mrb->c->eidx - epos)
1352         a = mrb->c->eidx - epos;
1353       for (n=0; n<a; n++) {
1354         int nregs = irep->nregs;
1355 
1356         proc = mrb->c->ensure[epos+n];
1357         mrb->c->ensure[epos+n] = NULL;
1358         if (proc == NULL) continue;
1359         irep = proc->body.irep;
1360         ci = cipush(mrb);
1361         ci->mid = ci[-1].mid;
1362         ci->argc = 0;
1363         ci->proc = proc;
1364         ci->stackent = mrb->c->stack;
1365         ci->target_class = target_class;
1366         ci->pc = pc;
1367         ci->acc = nregs;
1368         mrb->c->stack += ci->acc;
1369         mrb_stack_extend(mrb, irep->nregs);
1370         regs[0] = self;
1371         pc = irep->iseq;
1372       }
1373       pool = irep->pool;
1374       syms = irep->syms;
1375       mrb->c->eidx = epos;
1376       JUMP;
1377     }
1378 
1379     CASE(OP_SENDV, BB) {
1380       c = CALL_MAXARGS;
1381       goto L_SEND;
1382     };
1383 
1384     CASE(OP_SENDVB, BB) {
1385       c = CALL_MAXARGS;
1386       goto L_SENDB;
1387     };
1388 
1389     CASE(OP_SEND, BBB)
1390     L_SEND:
1391     {
1392       /* push nil after arguments */
1393       int bidx = (c == CALL_MAXARGS) ? a+2 : a+c+1;
1394       SET_NIL_VALUE(regs[bidx]);
1395       goto L_SENDB;
1396     };
1397     L_SEND_SYM:
1398     {
1399       /* push nil after arguments */
1400       int bidx = (c == CALL_MAXARGS) ? a+2 : a+c+1;
1401       SET_NIL_VALUE(regs[bidx]);
1402       goto L_SENDB_SYM;
1403     };
1404 
1405     CASE(OP_SENDB, BBB)
1406     L_SENDB:
1407     mid = syms[b];
1408     L_SENDB_SYM:
1409     {
1410       int argc = (c == CALL_MAXARGS) ? -1 : c;
1411       int bidx = (argc < 0) ? a+2 : a+c+1;
1412       mrb_method_t m;
1413       struct RClass *cls;
1414       mrb_callinfo *ci = mrb->c->ci;
1415       mrb_value recv, blk;
1416 
1417       mrb_assert(bidx < irep->nregs);
1418 
1419       recv = regs[a];
1420       blk = regs[bidx];
1421       if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) {
1422         blk = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc");
1423         /* The stack might have been reallocated during mrb_convert_type(),
1424            see #3622 */
1425         regs[bidx] = blk;
1426       }
1427       cls = mrb_class(mrb, recv);
1428       m = mrb_method_search_vm(mrb, &cls, mid);
1429       if (MRB_METHOD_UNDEF_P(m)) {
1430         mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
1431         m = mrb_method_search_vm(mrb, &cls, missing);
1432         if (MRB_METHOD_UNDEF_P(m) || (missing == mrb->c->ci->mid && mrb_obj_eq(mrb, regs[0], recv))) {
1433           mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, c, regs+a+1);
1434           ERR_PC_SET(mrb);
1435           mrb_method_missing(mrb, mid, recv, args);
1436         }
1437         if (argc >= 0) {
1438           if (a+2 >= irep->nregs) {
1439             mrb_stack_extend(mrb, a+3);
1440           }
1441           regs[a+1] = mrb_ary_new_from_values(mrb, c, regs+a+1);
1442           regs[a+2] = blk;
1443           argc = -1;
1444         }
1445         mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(mid));
1446         mid = missing;
1447       }
1448 
1449       /* push callinfo */
1450       ci = cipush(mrb);
1451       ci->mid = mid;
1452       ci->stackent = mrb->c->stack;
1453       ci->target_class = cls;
1454       ci->argc = argc;
1455 
1456       ci->pc = pc;
1457       ci->acc = a;
1458 
1459       /* prepare stack */
1460       mrb->c->stack += a;
1461 
1462       if (MRB_METHOD_CFUNC_P(m)) {
1463         if (MRB_METHOD_PROC_P(m)) {
1464           struct RProc *p = MRB_METHOD_PROC(m);
1465 
1466           ci->proc = p;
1467           recv = p->body.func(mrb, recv);
1468         }
1469         else {
1470           recv = MRB_METHOD_FUNC(m)(mrb, recv);
1471         }
1472         mrb_gc_arena_restore(mrb, ai);
1473         mrb_gc_arena_shrink(mrb, ai);
1474         if (mrb->exc) goto L_RAISE;
1475         ci = mrb->c->ci;
1476         if (mrb_type(blk) == MRB_TT_PROC) {
1477           struct RProc *p = mrb_proc_ptr(blk);
1478           if (p && !MRB_PROC_STRICT_P(p) && MRB_PROC_ENV(p) == ci[-1].env) {
1479             p->flags |= MRB_PROC_ORPHAN;
1480           }
1481         }
1482         if (!ci->target_class) { /* return from context modifying method (resume/yield) */
1483           if (ci->acc == CI_ACC_RESUMED) {
1484             mrb->jmp = prev_jmp;
1485             return recv;
1486           }
1487           else {
1488             mrb_assert(!MRB_PROC_CFUNC_P(ci[-1].proc));
1489             proc = ci[-1].proc;
1490             irep = proc->body.irep;
1491             pool = irep->pool;
1492             syms = irep->syms;
1493           }
1494         }
1495         mrb->c->stack[0] = recv;
1496         /* pop stackpos */
1497         mrb->c->stack = ci->stackent;
1498         pc = ci->pc;
1499         cipop(mrb);
1500         JUMP;
1501       }
1502       else {
1503         /* setup environment for calling method */
1504         proc = ci->proc = MRB_METHOD_PROC(m);
1505         irep = proc->body.irep;
1506         pool = irep->pool;
1507         syms = irep->syms;
1508         mrb_stack_extend(mrb, (argc < 0 && irep->nregs < 3) ? 3 : irep->nregs);
1509         pc = irep->iseq;
1510         JUMP;
1511       }
1512     }
1513 
1514     CASE(OP_CALL, Z) {
1515       mrb_callinfo *ci;
1516       mrb_value recv = mrb->c->stack[0];
1517       struct RProc *m = mrb_proc_ptr(recv);
1518 
1519       /* replace callinfo */
1520       ci = mrb->c->ci;
1521       ci->target_class = MRB_PROC_TARGET_CLASS(m);
1522       ci->proc = m;
1523       if (MRB_PROC_ENV_P(m)) {
1524         mrb_sym mid;
1525         struct REnv *e = MRB_PROC_ENV(m);
1526 
1527         mid = e->mid;
1528         if (mid) ci->mid = mid;
1529         if (!e->stack) {
1530           e->stack = mrb->c->stack;
1531         }
1532       }
1533 
1534       /* prepare stack */
1535       if (MRB_PROC_CFUNC_P(m)) {
1536         recv = MRB_PROC_CFUNC(m)(mrb, recv);
1537         mrb_gc_arena_restore(mrb, ai);
1538         mrb_gc_arena_shrink(mrb, ai);
1539         if (mrb->exc) goto L_RAISE;
1540         /* pop stackpos */
1541         ci = mrb->c->ci;
1542         mrb->c->stack = ci->stackent;
1543         regs[ci->acc] = recv;
1544         pc = ci->pc;
1545         cipop(mrb);
1546         irep = mrb->c->ci->proc->body.irep;
1547         pool = irep->pool;
1548         syms = irep->syms;
1549         JUMP;
1550       }
1551       else {
1552         /* setup environment for calling method */
1553         proc = m;
1554         irep = m->body.irep;
1555         if (!irep) {
1556           mrb->c->stack[0] = mrb_nil_value();
1557           a = 0;
1558           c = OP_R_NORMAL;
1559           goto L_OP_RETURN_BODY;
1560         }
1561         pool = irep->pool;
1562         syms = irep->syms;
1563         mrb_stack_extend(mrb, irep->nregs);
1564         if (ci->argc < 0) {
1565           if (irep->nregs > 3) {
1566             stack_clear(regs+3, irep->nregs-3);
1567           }
1568         }
1569         else if (ci->argc+2 < irep->nregs) {
1570           stack_clear(regs+ci->argc+2, irep->nregs-ci->argc-2);
1571         }
1572         if (MRB_PROC_ENV_P(m)) {
1573           regs[0] = MRB_PROC_ENV(m)->stack[0];
1574         }
1575         pc = irep->iseq;
1576         JUMP;
1577       }
1578     }
1579 
1580     CASE(OP_SUPER, BB) {
1581       int argc = (b == CALL_MAXARGS) ? -1 : b;
1582       int bidx = (argc < 0) ? a+2 : a+b+1;
1583       mrb_method_t m;
1584       struct RClass *cls;
1585       mrb_callinfo *ci = mrb->c->ci;
1586       mrb_value recv, blk;
1587       mrb_sym mid = ci->mid;
1588       struct RClass* target_class = MRB_PROC_TARGET_CLASS(ci->proc);
1589 
1590       mrb_assert(bidx < irep->nregs);
1591 
1592       if (mid == 0 || !target_class) {
1593         mrb_value exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method");
1594         mrb_exc_set(mrb, exc);
1595         goto L_RAISE;
1596       }
1597       if (target_class->tt == MRB_TT_MODULE) {
1598         target_class = ci->target_class;
1599         if (target_class->tt != MRB_TT_ICLASS) {
1600           mrb_value exc = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "superclass info lost [mruby limitations]");
1601           mrb_exc_set(mrb, exc);
1602           goto L_RAISE;
1603         }
1604       }
1605       recv = regs[0];
1606       if (!mrb_obj_is_kind_of(mrb, recv, target_class)) {
1607         mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR,
1608                                             "self has wrong type to call super in this context");
1609         mrb_exc_set(mrb, exc);
1610         goto L_RAISE;
1611       }
1612       blk = regs[bidx];
1613       if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) {
1614         blk = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc");
1615         /* The stack or ci stack might have been reallocated during
1616            mrb_convert_type(), see #3622 and #3784 */
1617         regs[bidx] = blk;
1618         ci = mrb->c->ci;
1619       }
1620       cls = target_class->super;
1621       m = mrb_method_search_vm(mrb, &cls, mid);
1622       if (MRB_METHOD_UNDEF_P(m)) {
1623         mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
1624 
1625         if (mid != missing) {
1626           cls = mrb_class(mrb, recv);
1627         }
1628         m = mrb_method_search_vm(mrb, &cls, missing);
1629         if (MRB_METHOD_UNDEF_P(m)) {
1630           mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, b, regs+a+1);
1631           ERR_PC_SET(mrb);
1632           mrb_method_missing(mrb, mid, recv, args);
1633         }
1634         mid = missing;
1635         if (argc >= 0) {
1636           if (a+2 >= irep->nregs) {
1637             mrb_stack_extend(mrb, a+3);
1638           }
1639           regs[a+1] = mrb_ary_new_from_values(mrb, b, regs+a+1);
1640           regs[a+2] = blk;
1641           argc = -1;
1642         }
1643         mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid));
1644       }
1645 
1646       /* push callinfo */
1647       ci = cipush(mrb);
1648       ci->mid = mid;
1649       ci->stackent = mrb->c->stack;
1650       ci->target_class = cls;
1651       ci->pc = pc;
1652       ci->argc = argc;
1653 
1654       /* prepare stack */
1655       mrb->c->stack += a;
1656       mrb->c->stack[0] = recv;
1657 
1658       if (MRB_METHOD_CFUNC_P(m)) {
1659         mrb_value v;
1660 
1661         if (MRB_METHOD_PROC_P(m)) {
1662           ci->proc = MRB_METHOD_PROC(m);
1663         }
1664         v = MRB_METHOD_CFUNC(m)(mrb, recv);
1665         mrb_gc_arena_restore(mrb, ai);
1666         if (mrb->exc) goto L_RAISE;
1667         ci = mrb->c->ci;
1668         if (!ci->target_class) { /* return from context modifying method (resume/yield) */
1669           if (ci->acc == CI_ACC_RESUMED) {
1670             mrb->jmp = prev_jmp;
1671             return v;
1672           }
1673           else {
1674             mrb_assert(!MRB_PROC_CFUNC_P(ci[-1].proc));
1675             proc = ci[-1].proc;
1676             irep = proc->body.irep;
1677             pool = irep->pool;
1678             syms = irep->syms;
1679           }
1680         }
1681         mrb->c->stack[0] = v;
1682         /* pop stackpos */
1683         mrb->c->stack = ci->stackent;
1684         pc = ci->pc;
1685         cipop(mrb);
1686         JUMP;
1687       }
1688       else {
1689         /* fill callinfo */
1690         ci->acc = a;
1691 
1692         /* setup environment for calling method */
1693         proc = ci->proc = MRB_METHOD_PROC(m);
1694         irep = proc->body.irep;
1695         pool = irep->pool;
1696         syms = irep->syms;
1697         mrb_stack_extend(mrb, (argc < 0 && irep->nregs < 3) ? 3 : irep->nregs);
1698         pc = irep->iseq;
1699         JUMP;
1700       }
1701     }
1702 
1703     CASE(OP_ARGARY, BS) {
1704       int m1 = (b>>11)&0x3f;
1705       int r  = (b>>10)&0x1;
1706       int m2 = (b>>5)&0x1f;
1707       int kd = (b>>4)&0x1;
1708       int lv = (b>>0)&0xf;
1709       mrb_value *stack;
1710 
1711       if (mrb->c->ci->mid == 0 || mrb->c->ci->target_class == NULL) {
1712         mrb_value exc;
1713 
1714       L_NOSUPER:
1715         exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method");
1716         mrb_exc_set(mrb, exc);
1717         goto L_RAISE;
1718       }
1719       if (lv == 0) stack = regs + 1;
1720       else {
1721         struct REnv *e = uvenv(mrb, lv-1);
1722         if (!e) goto L_NOSUPER;
1723         if (MRB_ENV_STACK_LEN(e) <= m1+r+m2+kd+1)
1724           goto L_NOSUPER;
1725         stack = e->stack + 1;
1726       }
1727       if (r == 0) {
1728         regs[a] = mrb_ary_new_from_values(mrb, m1+m2+kd, stack);
1729       }
1730       else {
1731         mrb_value *pp = NULL;
1732         struct RArray *rest;
1733         int len = 0;
1734 
1735         if (mrb_array_p(stack[m1])) {
1736           struct RArray *ary = mrb_ary_ptr(stack[m1]);
1737 
1738           pp = ARY_PTR(ary);
1739           len = (int)ARY_LEN(ary);
1740         }
1741         regs[a] = mrb_ary_new_capa(mrb, m1+len+m2+kd);
1742         rest = mrb_ary_ptr(regs[a]);
1743         if (m1 > 0) {
1744           stack_copy(ARY_PTR(rest), stack, m1);
1745         }
1746         if (len > 0) {
1747           stack_copy(ARY_PTR(rest)+m1, pp, len);
1748         }
1749         if (m2 > 0) {
1750           stack_copy(ARY_PTR(rest)+m1+len, stack+m1+1, m2);
1751         }
1752         if (kd) {
1753           stack_copy(ARY_PTR(rest)+m1+len+m2, stack+m1+m2+1, kd);
1754         }
1755         ARY_SET_LEN(rest, m1+len+m2+kd);
1756       }
1757       regs[a+1] = stack[m1+r+m2];
1758       mrb_gc_arena_restore(mrb, ai);
1759       NEXT;
1760     }
1761 
1762     CASE(OP_ENTER, W) {
1763       int m1 = MRB_ASPEC_REQ(a);
1764       int o  = MRB_ASPEC_OPT(a);
1765       int r  = MRB_ASPEC_REST(a);
1766       int m2 = MRB_ASPEC_POST(a);
1767       int kd = (MRB_ASPEC_KEY(a) > 0 || MRB_ASPEC_KDICT(a))? 1 : 0;
1768       /* unused
1769       int b  = MRB_ASPEC_BLOCK(a);
1770       */
1771       int argc = mrb->c->ci->argc;
1772       mrb_value *argv = regs+1;
1773       mrb_value * const argv0 = argv;
1774       int const len = m1 + o + r + m2;
1775       int const blk_pos = len + kd + 1;
1776       mrb_value *blk = &argv[argc < 0 ? 1 : argc];
1777       mrb_value kdict;
1778       int kargs = kd;
1779 
1780       /* arguments is passed with Array */
1781       if (argc < 0) {
1782         struct RArray *ary = mrb_ary_ptr(regs[1]);
1783         argv = ARY_PTR(ary);
1784         argc = (int)ARY_LEN(ary);
1785         mrb_gc_protect(mrb, regs[1]);
1786       }
1787 
1788       /* strict argument check */
1789       if (mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc)) {
1790         if (argc < m1 + m2 || (r == 0 && argc > len + kd)) {
1791           argnum_error(mrb, m1+m2);
1792           goto L_RAISE;
1793         }
1794       }
1795       /* extract first argument array to arguments */
1796       else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) {
1797         mrb_gc_protect(mrb, argv[0]);
1798         argc = (int)RARRAY_LEN(argv[0]);
1799         argv = RARRAY_PTR(argv[0]);
1800       }
1801 
1802       if (kd) {
1803         /* check last arguments is hash if method takes keyword arguments */
1804         if (argc == m1+m2) {
1805           kdict = mrb_hash_new(mrb);
1806           kargs = 0;
1807         }
1808         else {
1809           if (argv && argc > 0 && mrb_hash_p(argv[argc-1])) {
1810             kdict = argv[argc-1];
1811             mrb_hash_check_kdict(mrb, kdict);
1812           }
1813           else if (r || argc <= m1+m2+o
1814                    || !(mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc))) {
1815             kdict = mrb_hash_new(mrb);
1816             kargs = 0;
1817           }
1818           else {
1819             argnum_error(mrb, m1+m2);
1820             goto L_RAISE;
1821           }
1822           if (MRB_ASPEC_KEY(a) > 0) {
1823             kdict = mrb_hash_dup(mrb, kdict);
1824           }
1825         }
1826       }
1827 
1828       /* no rest arguments */
1829       if (argc-kargs < len) {
1830         int mlen = m2;
1831         if (argc < m1+m2) {
1832           mlen = m1 < argc ? argc - m1 : 0;
1833         }
1834         regs[blk_pos] = *blk; /* move block */
1835         if (kd) regs[len + 1] = kdict;
1836 
1837         /* copy mandatory and optional arguments */
1838         if (argv0 != argv) {
1839           value_move(&regs[1], argv, argc-mlen); /* m1 + o */
1840         }
1841         if (argc < m1) {
1842           stack_clear(&regs[argc+1], m1-argc);
1843         }
1844         /* copy post mandatory arguments */
1845         if (mlen) {
1846           value_move(&regs[len-m2+1], &argv[argc-mlen], mlen);
1847         }
1848         if (mlen < m2) {
1849           stack_clear(&regs[len-m2+mlen+1], m2-mlen);
1850         }
1851         /* initalize rest arguments with empty Array */
1852         if (r) {
1853           regs[m1+o+1] = mrb_ary_new_capa(mrb, 0);
1854         }
1855         /* skip initailizer of passed arguments */
1856         if (o > 0 && argc-kargs > m1+m2)
1857           pc += (argc - kargs - m1 - m2)*3;
1858       }
1859       else {
1860         int rnum = 0;
1861         if (argv0 != argv) {
1862           regs[blk_pos] = *blk; /* move block */
1863           if (kd) regs[len + 1] = kdict;
1864           value_move(&regs[1], argv, m1+o);
1865         }
1866         if (r) {
1867           mrb_value ary;
1868 
1869           rnum = argc-m1-o-m2-kargs;
1870           ary = mrb_ary_new_from_values(mrb, rnum, argv+m1+o);
1871           regs[m1+o+1] = ary;
1872         }
1873         if (m2) {
1874           if (argc-m2 > m1) {
1875             value_move(&regs[m1+o+r+1], &argv[m1+o+rnum], m2);
1876           }
1877         }
1878         if (argv0 == argv) {
1879           regs[blk_pos] = *blk; /* move block */
1880           if (kd) regs[len + 1] = kdict;
1881         }
1882         pc += o*3;
1883       }
1884 
1885       /* format arguments for generated code */
1886       mrb->c->ci->argc = len + kd;
1887 
1888       /* clear local (but non-argument) variables */
1889       if (irep->nlocals-blk_pos-1 > 0) {
1890         stack_clear(&regs[blk_pos+1], irep->nlocals-blk_pos-1);
1891       }
1892       JUMP;
1893     }
1894 
1895     CASE(OP_KARG, BB) {
1896       mrb_value k = mrb_symbol_value(syms[b]);
1897       mrb_value kdict = regs[mrb->c->ci->argc];
1898 
1899       if (!mrb_hash_p(kdict) || !mrb_hash_key_p(mrb, kdict, k)) {
1900         mrb_value str = mrb_format(mrb, "missing keyword: %S", k);
1901         mrb_exc_set(mrb, mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str));
1902         goto L_RAISE;
1903       }
1904       regs[a] = mrb_hash_get(mrb, kdict, k);
1905       mrb_hash_delete_key(mrb, kdict, k);
1906       NEXT;
1907     }
1908 
1909     CASE(OP_KEY_P, BB) {
1910       mrb_value k = mrb_symbol_value(syms[b]);
1911       mrb_value kdict = regs[mrb->c->ci->argc];
1912       mrb_bool key_p = FALSE;
1913 
1914       if (mrb_hash_p(kdict)) {
1915         key_p = mrb_hash_key_p(mrb, kdict, k);
1916       }
1917       regs[a] = mrb_bool_value(key_p);
1918       NEXT;
1919     }
1920 
1921     CASE(OP_KEYEND, Z) {
1922       mrb_value kdict = regs[mrb->c->ci->argc];
1923 
1924       if (mrb_hash_p(kdict) && !mrb_hash_empty_p(mrb, kdict)) {
1925         mrb_value keys = mrb_hash_keys(mrb, kdict);
1926         mrb_value key1 = RARRAY_PTR(keys)[0];
1927         mrb_value str = mrb_format(mrb, "unknown keyword: %S", key1);
1928         mrb_exc_set(mrb, mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str));
1929         goto L_RAISE;
1930       }
1931       NEXT;
1932     }
1933 
1934     CASE(OP_BREAK, B) {
1935       c = OP_R_BREAK;
1936       goto L_RETURN;
1937     }
1938     CASE(OP_RETURN_BLK, B) {
1939       c = OP_R_RETURN;
1940       goto L_RETURN;
1941     }
1942     CASE(OP_RETURN, B)
1943     c = OP_R_NORMAL;
1944     L_RETURN:
1945     {
1946        mrb_callinfo *ci;
1947 
1948 #define ecall_adjust() do {\
1949   ptrdiff_t cioff = ci - mrb->c->cibase;\
1950   ecall(mrb);\
1951   ci = mrb->c->cibase + cioff;\
1952 } while (0)
1953 
1954       ci = mrb->c->ci;
1955       if (ci->mid) {
1956         mrb_value blk;
1957 
1958         if (ci->argc < 0) {
1959           blk = regs[2];
1960         }
1961         else {
1962           blk = regs[ci->argc+1];
1963         }
1964         if (mrb_type(blk) == MRB_TT_PROC) {
1965           struct RProc *p = mrb_proc_ptr(blk);
1966 
1967           if (!MRB_PROC_STRICT_P(p) &&
1968               ci > mrb->c->cibase && MRB_PROC_ENV(p) == ci[-1].env) {
1969             p->flags |= MRB_PROC_ORPHAN;
1970           }
1971         }
1972       }
1973 
1974       if (mrb->exc) {
1975         mrb_callinfo *ci0;
1976 
1977       L_RAISE:
1978         ci0 = ci = mrb->c->ci;
1979         if (ci == mrb->c->cibase) {
1980           if (ci->ridx == 0) goto L_FTOP;
1981           goto L_RESCUE;
1982         }
1983         while (ci[0].ridx == ci[-1].ridx) {
1984           cipop(mrb);
1985           mrb->c->stack = ci->stackent;
1986           if (ci->acc == CI_ACC_SKIP && prev_jmp) {
1987             mrb->jmp = prev_jmp;
1988             MRB_THROW(prev_jmp);
1989           }
1990           ci = mrb->c->ci;
1991           if (ci == mrb->c->cibase) {
1992             if (ci->ridx == 0) {
1993             L_FTOP:             /* fiber top */
1994               if (mrb->c == mrb->root_c) {
1995                 mrb->c->stack = mrb->c->stbase;
1996                 goto L_STOP;
1997               }
1998               else {
1999                 struct mrb_context *c = mrb->c;
2000 
2001                 while (c->eidx > ci->epos) {
2002                   ecall_adjust();
2003                 }
2004                 c->status = MRB_FIBER_TERMINATED;
2005                 mrb->c = c->prev;
2006                 c->prev = NULL;
2007                 goto L_RAISE;
2008               }
2009             }
2010             break;
2011           }
2012           /* call ensure only when we skip this callinfo */
2013           if (ci[0].ridx == ci[-1].ridx) {
2014             while (mrb->c->eidx > ci->epos) {
2015               ecall_adjust();
2016             }
2017           }
2018         }
2019       L_RESCUE:
2020         if (ci->ridx == 0) goto L_STOP;
2021         proc = ci->proc;
2022         irep = proc->body.irep;
2023         pool = irep->pool;
2024         syms = irep->syms;
2025         if (ci < ci0) {
2026           mrb->c->stack = ci[1].stackent;
2027         }
2028         mrb_stack_extend(mrb, irep->nregs);
2029         pc = irep->iseq+mrb->c->rescue[--ci->ridx];
2030       }
2031       else {
2032         int acc;
2033         mrb_value v;
2034         struct RProc *dst;
2035 
2036         ci = mrb->c->ci;
2037         v = regs[a];
2038         mrb_gc_protect(mrb, v);
2039         switch (c) {
2040         case OP_R_RETURN:
2041           /* Fall through to OP_R_NORMAL otherwise */
2042           if (ci->acc >=0 && MRB_PROC_ENV_P(proc) && !MRB_PROC_STRICT_P(proc)) {
2043             mrb_callinfo *cibase = mrb->c->cibase;
2044             dst = top_proc(mrb, proc);
2045 
2046             if (MRB_PROC_ENV_P(dst)) {
2047               struct REnv *e = MRB_PROC_ENV(dst);
2048 
2049               if (!MRB_ENV_STACK_SHARED_P(e) || e->cxt != mrb->c) {
2050                 localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
2051                 goto L_RAISE;
2052               }
2053             }
2054             while (cibase <= ci && ci->proc != dst) {
2055               if (ci->acc < 0) {
2056                 localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
2057                 goto L_RAISE;
2058               }
2059               ci--;
2060             }
2061             if (ci <= cibase) {
2062               localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
2063               goto L_RAISE;
2064             }
2065             break;
2066           }
2067           /* fallthrough */
2068         case OP_R_NORMAL:
2069         NORMAL_RETURN:
2070           if (ci == mrb->c->cibase) {
2071             struct mrb_context *c = mrb->c;
2072 
2073             if (!c->prev) { /* toplevel return */
2074               regs[irep->nlocals] = v;
2075               goto L_STOP;
2076             }
2077             if (c->prev->ci == c->prev->cibase) {
2078               mrb_value exc = mrb_exc_new_str_lit(mrb, E_FIBER_ERROR, "double resume");
2079               mrb_exc_set(mrb, exc);
2080               goto L_RAISE;
2081             }
2082             while (c->eidx > 0) {
2083               ecall(mrb);
2084             }
2085             /* automatic yield at the end */
2086             c->status = MRB_FIBER_TERMINATED;
2087             mrb->c = c->prev;
2088             c->prev = NULL;
2089             mrb->c->status = MRB_FIBER_RUNNING;
2090             ci = mrb->c->ci;
2091           }
2092           break;
2093         case OP_R_BREAK:
2094           if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN;
2095           if (MRB_PROC_ORPHAN_P(proc)) {
2096             mrb_value exc;
2097 
2098           L_BREAK_ERROR:
2099             exc = mrb_exc_new_str_lit(mrb, E_LOCALJUMP_ERROR,
2100                                       "break from proc-closure");
2101             mrb_exc_set(mrb, exc);
2102             goto L_RAISE;
2103           }
2104           if (!MRB_PROC_ENV_P(proc) || !MRB_ENV_STACK_SHARED_P(MRB_PROC_ENV(proc))) {
2105             goto L_BREAK_ERROR;
2106           }
2107           else {
2108             struct REnv *e = MRB_PROC_ENV(proc);
2109 
2110             if (e->cxt != mrb->c) {
2111               goto L_BREAK_ERROR;
2112             }
2113           }
2114           while (mrb->c->eidx > mrb->c->ci->epos) {
2115             ecall_adjust();
2116           }
2117           /* break from fiber block */
2118           if (ci == mrb->c->cibase && ci->pc) {
2119             struct mrb_context *c = mrb->c;
2120 
2121             mrb->c = c->prev;
2122             c->prev = NULL;
2123             ci = mrb->c->ci;
2124           }
2125           if (ci->acc < 0) {
2126             mrb_gc_arena_restore(mrb, ai);
2127             mrb->c->vmexec = FALSE;
2128             mrb->exc = (struct RObject*)break_new(mrb, proc, v);
2129             mrb->jmp = prev_jmp;
2130             MRB_THROW(prev_jmp);
2131           }
2132           if (FALSE) {
2133           L_BREAK:
2134             v = ((struct RBreak*)mrb->exc)->val;
2135             proc = ((struct RBreak*)mrb->exc)->proc;
2136             mrb->exc = NULL;
2137             ci = mrb->c->ci;
2138           }
2139           mrb->c->stack = ci->stackent;
2140           proc = proc->upper;
2141           while (mrb->c->cibase < ci &&  ci[-1].proc != proc) {
2142             if (ci[-1].acc == CI_ACC_SKIP) {
2143               while (ci < mrb->c->ci) {
2144                 cipop(mrb);
2145               }
2146               goto L_BREAK_ERROR;
2147             }
2148             ci--;
2149           }
2150           if (ci == mrb->c->cibase) {
2151             goto L_BREAK_ERROR;
2152           }
2153           break;
2154         default:
2155           /* cannot happen */
2156           break;
2157         }
2158         while (ci < mrb->c->ci) {
2159           cipop(mrb);
2160         }
2161         ci[0].ridx = ci[-1].ridx;
2162         while (mrb->c->eidx > ci->epos) {
2163           ecall_adjust();
2164         }
2165         if (mrb->c->vmexec && !ci->target_class) {
2166           mrb_gc_arena_restore(mrb, ai);
2167           mrb->c->vmexec = FALSE;
2168           mrb->jmp = prev_jmp;
2169           return v;
2170         }
2171         acc = ci->acc;
2172         mrb->c->stack = ci->stackent;
2173         cipop(mrb);
2174         if (acc == CI_ACC_SKIP || acc == CI_ACC_DIRECT) {
2175           mrb_gc_arena_restore(mrb, ai);
2176           mrb->jmp = prev_jmp;
2177           return v;
2178         }
2179         pc = ci->pc;
2180         ci = mrb->c->ci;
2181         DEBUG(fprintf(stderr, "from :%s\n", mrb_sym2name(mrb, ci->mid)));
2182         proc = mrb->c->ci->proc;
2183         irep = proc->body.irep;
2184         pool = irep->pool;
2185         syms = irep->syms;
2186 
2187         regs[acc] = v;
2188         mrb_gc_arena_restore(mrb, ai);
2189       }
2190       JUMP;
2191     }
2192 
2193     CASE(OP_BLKPUSH, BS) {
2194       int m1 = (b>>11)&0x3f;
2195       int r  = (b>>10)&0x1;
2196       int m2 = (b>>5)&0x1f;
2197       int kd = (b>>4)&0x1;
2198       int lv = (b>>0)&0xf;
2199       mrb_value *stack;
2200 
2201       if (lv == 0) stack = regs + 1;
2202       else {
2203         struct REnv *e = uvenv(mrb, lv-1);
2204         if (!e || (!MRB_ENV_STACK_SHARED_P(e) && e->mid == 0) ||
2205             MRB_ENV_STACK_LEN(e) <= m1+r+m2+1) {
2206           localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
2207           goto L_RAISE;
2208         }
2209         stack = e->stack + 1;
2210       }
2211       if (mrb_nil_p(stack[m1+r+m2])) {
2212         localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
2213         goto L_RAISE;
2214       }
2215       regs[a] = stack[m1+r+m2+kd];
2216       NEXT;
2217     }
2218 
2219 #define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff))
2220 #define OP_MATH_BODY(op,v1,v2) do {\
2221   v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\
2222 } while(0)
2223 
2224     CASE(OP_ADD, B) {
2225       /* need to check if op is overridden */
2226       switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
2227       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
2228         {
2229           mrb_int x, y, z;
2230           mrb_value *regs_a = regs + a;
2231 
2232           x = mrb_fixnum(regs_a[0]);
2233           y = mrb_fixnum(regs_a[1]);
2234           if (mrb_int_add_overflow(x, y, &z)) {
2235 #ifndef MRB_WITHOUT_FLOAT
2236             SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y);
2237             break;
2238 #endif
2239           }
2240           SET_INT_VALUE(regs[a], z);
2241         }
2242         break;
2243 #ifndef MRB_WITHOUT_FLOAT
2244       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
2245         {
2246           mrb_int x = mrb_fixnum(regs[a]);
2247           mrb_float y = mrb_float(regs[a+1]);
2248           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + y);
2249         }
2250         break;
2251       case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
2252 #ifdef MRB_WORD_BOXING
2253         {
2254           mrb_float x = mrb_float(regs[a]);
2255           mrb_int y = mrb_fixnum(regs[a+1]);
2256           SET_FLOAT_VALUE(mrb, regs[a], x + y);
2257         }
2258 #else
2259         OP_MATH_BODY(+,mrb_float,mrb_fixnum);
2260 #endif
2261         break;
2262       case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
2263 #ifdef MRB_WORD_BOXING
2264         {
2265           mrb_float x = mrb_float(regs[a]);
2266           mrb_float y = mrb_float(regs[a+1]);
2267           SET_FLOAT_VALUE(mrb, regs[a], x + y);
2268         }
2269 #else
2270         OP_MATH_BODY(+,mrb_float,mrb_float);
2271 #endif
2272         break;
2273 #endif
2274       case TYPES2(MRB_TT_STRING,MRB_TT_STRING):
2275         regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]);
2276         break;
2277       default:
2278         c = 1;
2279         mid = mrb_intern_lit(mrb, "+");
2280         goto L_SEND_SYM;
2281       }
2282       mrb_gc_arena_restore(mrb, ai);
2283       NEXT;
2284     }
2285 
2286     CASE(OP_SUB, B) {
2287       /* need to check if op is overridden */
2288       switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
2289       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
2290         {
2291           mrb_int x, y, z;
2292 
2293           x = mrb_fixnum(regs[a]);
2294           y = mrb_fixnum(regs[a+1]);
2295           if (mrb_int_sub_overflow(x, y, &z)) {
2296 #ifndef MRB_WITHOUT_FLOAT
2297             SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y);
2298             break;
2299 #endif
2300           }
2301           SET_INT_VALUE(regs[a], z);
2302         }
2303         break;
2304 #ifndef MRB_WITHOUT_FLOAT
2305       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
2306         {
2307           mrb_int x = mrb_fixnum(regs[a]);
2308           mrb_float y = mrb_float(regs[a+1]);
2309           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - y);
2310         }
2311         break;
2312       case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
2313 #ifdef MRB_WORD_BOXING
2314         {
2315           mrb_float x = mrb_float(regs[a]);
2316           mrb_int y = mrb_fixnum(regs[a+1]);
2317           SET_FLOAT_VALUE(mrb, regs[a], x - y);
2318         }
2319 #else
2320         OP_MATH_BODY(-,mrb_float,mrb_fixnum);
2321 #endif
2322         break;
2323       case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
2324 #ifdef MRB_WORD_BOXING
2325         {
2326           mrb_float x = mrb_float(regs[a]);
2327           mrb_float y = mrb_float(regs[a+1]);
2328           SET_FLOAT_VALUE(mrb, regs[a], x - y);
2329         }
2330 #else
2331         OP_MATH_BODY(-,mrb_float,mrb_float);
2332 #endif
2333         break;
2334 #endif
2335       default:
2336         c = 1;
2337         mid = mrb_intern_lit(mrb, "-");
2338         goto L_SEND_SYM;
2339       }
2340       NEXT;
2341     }
2342 
2343     CASE(OP_MUL, B) {
2344       /* need to check if op is overridden */
2345       switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
2346       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
2347         {
2348           mrb_int x, y, z;
2349 
2350           x = mrb_fixnum(regs[a]);
2351           y = mrb_fixnum(regs[a+1]);
2352           if (mrb_int_mul_overflow(x, y, &z)) {
2353 #ifndef MRB_WITHOUT_FLOAT
2354             SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * (mrb_float)y);
2355             break;
2356 #endif
2357           }
2358           SET_INT_VALUE(regs[a], z);
2359         }
2360         break;
2361 #ifndef MRB_WITHOUT_FLOAT
2362       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
2363         {
2364           mrb_int x = mrb_fixnum(regs[a]);
2365           mrb_float y = mrb_float(regs[a+1]);
2366           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * y);
2367         }
2368         break;
2369       case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
2370 #ifdef MRB_WORD_BOXING
2371         {
2372           mrb_float x = mrb_float(regs[a]);
2373           mrb_int y = mrb_fixnum(regs[a+1]);
2374           SET_FLOAT_VALUE(mrb, regs[a], x * y);
2375         }
2376 #else
2377         OP_MATH_BODY(*,mrb_float,mrb_fixnum);
2378 #endif
2379         break;
2380       case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
2381 #ifdef MRB_WORD_BOXING
2382         {
2383           mrb_float x = mrb_float(regs[a]);
2384           mrb_float y = mrb_float(regs[a+1]);
2385           SET_FLOAT_VALUE(mrb, regs[a], x * y);
2386         }
2387 #else
2388         OP_MATH_BODY(*,mrb_float,mrb_float);
2389 #endif
2390         break;
2391 #endif
2392       default:
2393         c = 1;
2394         mid = mrb_intern_lit(mrb, "*");
2395         goto L_SEND_SYM;
2396       }
2397       NEXT;
2398     }
2399 
2400     CASE(OP_DIV, B) {
2401 #ifndef MRB_WITHOUT_FLOAT
2402       double x, y, f;
2403 #endif
2404 
2405       /* need to check if op is overridden */
2406       switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
2407       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
2408 #ifdef MRB_WITHOUT_FLOAT
2409         {
2410           mrb_int x = mrb_fixnum(regs[a]);
2411           mrb_int y = mrb_fixnum(regs[a+1]);
2412           SET_INT_VALUE(regs[a], y ? x / y : 0);
2413         }
2414         break;
2415 #else
2416         x = (mrb_float)mrb_fixnum(regs[a]);
2417         y = (mrb_float)mrb_fixnum(regs[a+1]);
2418         break;
2419       case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
2420         x = (mrb_float)mrb_fixnum(regs[a]);
2421         y = mrb_float(regs[a+1]);
2422         break;
2423       case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
2424         x = mrb_float(regs[a]);
2425         y = (mrb_float)mrb_fixnum(regs[a+1]);
2426         break;
2427       case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
2428         x = mrb_float(regs[a]);
2429         y = mrb_float(regs[a+1]);
2430         break;
2431 #endif
2432       default:
2433         c = 1;
2434         mid = mrb_intern_lit(mrb, "/");
2435         goto L_SEND_SYM;
2436       }
2437 
2438 #ifndef MRB_WITHOUT_FLOAT
2439       if (y == 0) {
2440         if (x > 0) f = INFINITY;
2441         else if (x < 0) f = -INFINITY;
2442         else /* if (x == 0) */ f = NAN;
2443       }
2444       else {
2445         f = x / y;
2446       }
2447       SET_FLOAT_VALUE(mrb, regs[a], f);
2448 #endif
2449       NEXT;
2450     }
2451 
2452     CASE(OP_ADDI, BB) {
2453       /* need to check if + is overridden */
2454       switch (mrb_type(regs[a])) {
2455       case MRB_TT_FIXNUM:
2456         {
2457           mrb_int x = mrb_fixnum(regs[a]);
2458           mrb_int y = (mrb_int)b;
2459           mrb_int z;
2460 
2461           if (mrb_int_add_overflow(x, y, &z)) {
2462 #ifndef MRB_WITHOUT_FLOAT
2463             SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y);
2464             break;
2465 #endif
2466           }
2467           SET_INT_VALUE(regs[a], z);
2468         }
2469         break;
2470 #ifndef MRB_WITHOUT_FLOAT
2471       case MRB_TT_FLOAT:
2472 #ifdef MRB_WORD_BOXING
2473         {
2474           mrb_float x = mrb_float(regs[a]);
2475           SET_FLOAT_VALUE(mrb, regs[a], x + b);
2476         }
2477 #else
2478         mrb_float(regs[a]) += b;
2479 #endif
2480         break;
2481 #endif
2482       default:
2483         SET_INT_VALUE(regs[a+1], b);
2484         c = 1;
2485         mid = mrb_intern_lit(mrb, "+");
2486         goto L_SEND_SYM;
2487       }
2488       NEXT;
2489     }
2490 
2491     CASE(OP_SUBI, BB) {
2492       mrb_value *regs_a = regs + a;
2493 
2494       /* need to check if + is overridden */
2495       switch (mrb_type(regs_a[0])) {
2496       case MRB_TT_FIXNUM:
2497         {
2498           mrb_int x = mrb_fixnum(regs_a[0]);
2499           mrb_int y = (mrb_int)b;
2500           mrb_int z;
2501 
2502           if (mrb_int_sub_overflow(x, y, &z)) {
2503 #ifndef MRB_WITHOUT_FLOAT
2504             SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y);
2505             break;
2506 #endif
2507           }
2508           SET_INT_VALUE(regs_a[0], z);
2509         }
2510         break;
2511 #ifndef MRB_WITHOUT_FLOAT
2512       case MRB_TT_FLOAT:
2513 #ifdef MRB_WORD_BOXING
2514         {
2515           mrb_float x = mrb_float(regs[a]);
2516           SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)b);
2517         }
2518 #else
2519         mrb_float(regs_a[0]) -= b;
2520 #endif
2521         break;
2522 #endif
2523       default:
2524         SET_INT_VALUE(regs_a[1], b);
2525         c = 1;
2526         mid = mrb_intern_lit(mrb, "-");
2527         goto L_SEND_SYM;
2528       }
2529       NEXT;
2530     }
2531 
2532 #define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1]))
2533 
2534 #ifdef MRB_WITHOUT_FLOAT
2535 #define OP_CMP(op) do {\
2536   int result;\
2537   /* need to check if - is overridden */\
2538   switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
2539   case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\
2540     result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\
2541     break;\
2542   default:\
2543     c = 1;\
2544     mid = mrb_intern_lit(mrb, # op);\
2545     goto L_SEND_SYM;\
2546   }\
2547   if (result) {\
2548     SET_TRUE_VALUE(regs[a]);\
2549   }\
2550   else {\
2551     SET_FALSE_VALUE(regs[a]);\
2552   }\
2553 } while(0)
2554 #else
2555 #define OP_CMP(op) do {\
2556   int result;\
2557   /* need to check if - is overridden */\
2558   switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
2559   case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\
2560     result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\
2561     break;\
2562   case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\
2563     result = OP_CMP_BODY(op,mrb_fixnum,mrb_float);\
2564     break;\
2565   case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\
2566     result = OP_CMP_BODY(op,mrb_float,mrb_fixnum);\
2567     break;\
2568   case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\
2569     result = OP_CMP_BODY(op,mrb_float,mrb_float);\
2570     break;\
2571   default:\
2572     c = 1;\
2573     mid = mrb_intern_lit(mrb, # op);\
2574     goto L_SEND_SYM;\
2575   }\
2576   if (result) {\
2577     SET_TRUE_VALUE(regs[a]);\
2578   }\
2579   else {\
2580     SET_FALSE_VALUE(regs[a]);\
2581   }\
2582 } while(0)
2583 #endif
2584 
2585     CASE(OP_EQ, B) {
2586       if (mrb_obj_eq(mrb, regs[a], regs[a+1])) {
2587         SET_TRUE_VALUE(regs[a]);
2588       }
2589       else {
2590         OP_CMP(==);
2591       }
2592       NEXT;
2593     }
2594 
2595     CASE(OP_LT, B) {
2596       OP_CMP(<);
2597       NEXT;
2598     }
2599 
2600     CASE(OP_LE, B) {
2601       OP_CMP(<=);
2602       NEXT;
2603     }
2604 
2605     CASE(OP_GT, B) {
2606       OP_CMP(>);
2607       NEXT;
2608     }
2609 
2610     CASE(OP_GE, B) {
2611       OP_CMP(>=);
2612       NEXT;
2613     }
2614 
2615     CASE(OP_ARRAY, BB) {
2616       mrb_value v = mrb_ary_new_from_values(mrb, b, &regs[a]);
2617       regs[a] = v;
2618       mrb_gc_arena_restore(mrb, ai);
2619       NEXT;
2620     }
2621     CASE(OP_ARRAY2, BBB) {
2622       mrb_value v = mrb_ary_new_from_values(mrb, c, &regs[b]);
2623       regs[a] = v;
2624       mrb_gc_arena_restore(mrb, ai);
2625       NEXT;
2626     }
2627 
2628     CASE(OP_ARYCAT, B) {
2629       mrb_value splat = mrb_ary_splat(mrb, regs[a+1]);
2630       mrb_ary_concat(mrb, regs[a], splat);
2631       mrb_gc_arena_restore(mrb, ai);
2632       NEXT;
2633     }
2634 
2635     CASE(OP_ARYPUSH, B) {
2636       mrb_ary_push(mrb, regs[a], regs[a+1]);
2637       NEXT;
2638     }
2639 
2640     CASE(OP_ARYDUP, B) {
2641       mrb_value ary = regs[a];
2642       if (mrb_array_p(ary)) {
2643         ary = mrb_ary_new_from_values(mrb, RARRAY_LEN(ary), RARRAY_PTR(ary));
2644       }
2645       else {
2646         ary = mrb_ary_new_from_values(mrb, 1, &ary);
2647       }
2648       regs[a] = ary;
2649       NEXT;
2650     }
2651 
2652     CASE(OP_AREF, BBB) {
2653       mrb_value v = regs[b];
2654 
2655       if (!mrb_array_p(v)) {
2656         if (c == 0) {
2657           regs[a] = v;
2658         }
2659         else {
2660           SET_NIL_VALUE(regs[a]);
2661         }
2662       }
2663       else {
2664         v = mrb_ary_ref(mrb, v, c);
2665         regs[a] = v;
2666       }
2667       NEXT;
2668     }
2669 
2670     CASE(OP_ASET, BBB) {
2671       mrb_ary_set(mrb, regs[b], c, regs[a]);
2672       NEXT;
2673     }
2674 
2675     CASE(OP_APOST, BBB) {
2676       mrb_value v = regs[a];
2677       int pre  = b;
2678       int post = c;
2679       struct RArray *ary;
2680       int len, idx;
2681 
2682       if (!mrb_array_p(v)) {
2683         v = mrb_ary_new_from_values(mrb, 1, &regs[a]);
2684       }
2685       ary = mrb_ary_ptr(v);
2686       len = (int)ARY_LEN(ary);
2687       if (len > pre + post) {
2688         v = mrb_ary_new_from_values(mrb, len - pre - post, ARY_PTR(ary)+pre);
2689         regs[a++] = v;
2690         while (post--) {
2691           regs[a++] = ARY_PTR(ary)[len-post-1];
2692         }
2693       }
2694       else {
2695         v = mrb_ary_new_capa(mrb, 0);
2696         regs[a++] = v;
2697         for (idx=0; idx+pre<len; idx++) {
2698           regs[a+idx] = ARY_PTR(ary)[pre+idx];
2699         }
2700         while (idx < post) {
2701           SET_NIL_VALUE(regs[a+idx]);
2702           idx++;
2703         }
2704       }
2705       mrb_gc_arena_restore(mrb, ai);
2706       NEXT;
2707     }
2708 
2709     CASE(OP_INTERN, B) {
2710       mrb_sym sym = mrb_intern_str(mrb, regs[a]);
2711 
2712       regs[a] = mrb_symbol_value(sym);
2713       mrb_gc_arena_restore(mrb, ai);
2714       NEXT;
2715     }
2716 
2717     CASE(OP_STRING, BB) {
2718       mrb_value str = mrb_str_dup(mrb, pool[b]);
2719 
2720       regs[a] = str;
2721       mrb_gc_arena_restore(mrb, ai);
2722       NEXT;
2723     }
2724 
2725     CASE(OP_STRCAT, B) {
2726       mrb_str_concat(mrb, regs[a], regs[a+1]);
2727       NEXT;
2728     }
2729 
2730     CASE(OP_HASH, BB) {
2731       mrb_value hash = mrb_hash_new_capa(mrb, b);
2732       int i;
2733       int lim = a+b*2;
2734 
2735       for (i=a; i<lim; i+=2) {
2736         mrb_hash_set(mrb, hash, regs[i], regs[i+1]);
2737       }
2738       regs[a] = hash;
2739       mrb_gc_arena_restore(mrb, ai);
2740       NEXT;
2741     }
2742 
2743     CASE(OP_HASHADD, BB) {
2744       mrb_value hash;
2745       int i;
2746       int lim = a+b*2+1;
2747 
2748       hash = mrb_ensure_hash_type(mrb, regs[a]);
2749       for (i=a+1; i<lim; i+=2) {
2750         mrb_hash_set(mrb, hash, regs[i], regs[i+1]);
2751       }
2752       mrb_gc_arena_restore(mrb, ai);
2753       NEXT;
2754     }
2755     CASE(OP_HASHCAT, B) {
2756       mrb_value hash = mrb_ensure_hash_type(mrb, regs[a]);
2757 
2758       mrb_hash_merge(mrb, hash, regs[a+1]);
2759       mrb_gc_arena_restore(mrb, ai);
2760       NEXT;
2761     }
2762 
2763     CASE(OP_LAMBDA, BB)
2764     c = OP_L_LAMBDA;
2765     L_MAKE_LAMBDA:
2766     {
2767       struct RProc *p;
2768       mrb_irep *nirep = irep->reps[b];
2769 
2770       if (c & OP_L_CAPTURE) {
2771         p = mrb_closure_new(mrb, nirep);
2772       }
2773       else {
2774         p = mrb_proc_new(mrb, nirep);
2775         p->flags |= MRB_PROC_SCOPE;
2776       }
2777       if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT;
2778       regs[a] = mrb_obj_value(p);
2779       mrb_gc_arena_restore(mrb, ai);
2780       NEXT;
2781     }
2782     CASE(OP_BLOCK, BB) {
2783       c = OP_L_BLOCK;
2784       goto L_MAKE_LAMBDA;
2785     }
2786     CASE(OP_METHOD, BB) {
2787       c = OP_L_METHOD;
2788       goto L_MAKE_LAMBDA;
2789     }
2790 
2791     CASE(OP_RANGE_INC, B) {
2792       mrb_value val = mrb_range_new(mrb, regs[a], regs[a+1], FALSE);
2793       regs[a] = val;
2794       mrb_gc_arena_restore(mrb, ai);
2795       NEXT;
2796     }
2797 
2798     CASE(OP_RANGE_EXC, B) {
2799       mrb_value val = mrb_range_new(mrb, regs[a], regs[a+1], TRUE);
2800       regs[a] = val;
2801       mrb_gc_arena_restore(mrb, ai);
2802       NEXT;
2803     }
2804 
2805     CASE(OP_OCLASS, B) {
2806       regs[a] = mrb_obj_value(mrb->object_class);
2807       NEXT;
2808     }
2809 
2810     CASE(OP_CLASS, BB) {
2811       struct RClass *c = 0, *baseclass;
2812       mrb_value base, super;
2813       mrb_sym id = syms[b];
2814 
2815       base = regs[a];
2816       super = regs[a+1];
2817       if (mrb_nil_p(base)) {
2818         baseclass = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
2819         base = mrb_obj_value(baseclass);
2820       }
2821       c = mrb_vm_define_class(mrb, base, super, id);
2822       regs[a] = mrb_obj_value(c);
2823       mrb_gc_arena_restore(mrb, ai);
2824       NEXT;
2825     }
2826 
2827     CASE(OP_MODULE, BB) {
2828       struct RClass *cls = 0, *baseclass;
2829       mrb_value base;
2830       mrb_sym id = syms[b];
2831 
2832       base = regs[a];
2833       if (mrb_nil_p(base)) {
2834         baseclass = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
2835         base = mrb_obj_value(baseclass);
2836       }
2837       cls = mrb_vm_define_module(mrb, base, id);
2838       regs[a] = mrb_obj_value(cls);
2839       mrb_gc_arena_restore(mrb, ai);
2840       NEXT;
2841     }
2842 
2843     CASE(OP_EXEC, BB) {
2844       mrb_callinfo *ci;
2845       mrb_value recv = regs[a];
2846       struct RProc *p;
2847       mrb_irep *nirep = irep->reps[b];
2848 
2849       /* prepare closure */
2850       p = mrb_proc_new(mrb, nirep);
2851       p->c = NULL;
2852       mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)proc);
2853       MRB_PROC_SET_TARGET_CLASS(p, mrb_class_ptr(recv));
2854       p->flags |= MRB_PROC_SCOPE;
2855 
2856       /* prepare call stack */
2857       ci = cipush(mrb);
2858       ci->pc = pc;
2859       ci->acc = a;
2860       ci->mid = 0;
2861       ci->stackent = mrb->c->stack;
2862       ci->argc = 0;
2863       ci->target_class = mrb_class_ptr(recv);
2864 
2865       /* prepare stack */
2866       mrb->c->stack += a;
2867 
2868       /* setup block to call */
2869       ci->proc = p;
2870 
2871       irep = p->body.irep;
2872       pool = irep->pool;
2873       syms = irep->syms;
2874       mrb_stack_extend(mrb, irep->nregs);
2875       stack_clear(regs+1, irep->nregs-1);
2876       pc = irep->iseq;
2877       JUMP;
2878     }
2879 
2880     CASE(OP_DEF, BB) {
2881       struct RClass *target = mrb_class_ptr(regs[a]);
2882       struct RProc *p = mrb_proc_ptr(regs[a+1]);
2883       mrb_method_t m;
2884 
2885       MRB_METHOD_FROM_PROC(m, p);
2886       mrb_define_method_raw(mrb, target, syms[b], m);
2887       mrb_gc_arena_restore(mrb, ai);
2888       NEXT;
2889     }
2890 
2891     CASE(OP_SCLASS, B) {
2892       regs[a] = mrb_singleton_class(mrb, regs[a]);
2893       mrb_gc_arena_restore(mrb, ai);
2894       NEXT;
2895     }
2896 
2897     CASE(OP_TCLASS, B) {
2898       if (!check_target_class(mrb)) goto L_RAISE;
2899       regs[a] = mrb_obj_value(mrb->c->ci->target_class);
2900       NEXT;
2901     }
2902 
2903     CASE(OP_ALIAS, BB) {
2904       struct RClass *target;
2905 
2906       if (!check_target_class(mrb)) goto L_RAISE;
2907       target = mrb->c->ci->target_class;
2908       mrb_alias_method(mrb, target, syms[a], syms[b]);
2909       NEXT;
2910     }
2911     CASE(OP_UNDEF, B) {
2912       struct RClass *target;
2913 
2914       if (!check_target_class(mrb)) goto L_RAISE;
2915       target = mrb->c->ci->target_class;
2916       mrb_undef_method_id(mrb, target, syms[a]);
2917       NEXT;
2918     }
2919 
2920     CASE(OP_DEBUG, Z) {
2921       FETCH_BBB();
2922 #ifdef MRB_ENABLE_DEBUG_HOOK
2923       mrb->debug_op_hook(mrb, irep, pc, regs);
2924 #else
2925 #ifndef MRB_DISABLE_STDIO
2926       printf("OP_DEBUG %d %d %d\n", a, b, c);
2927 #else
2928       abort();
2929 #endif
2930 #endif
2931       NEXT;
2932     }
2933 
2934     CASE(OP_ERR, B) {
2935       mrb_value msg = mrb_str_dup(mrb, pool[a]);
2936       mrb_value exc;
2937 
2938       exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg);
2939       ERR_PC_SET(mrb);
2940       mrb_exc_set(mrb, exc);
2941       goto L_RAISE;
2942     }
2943 
2944     CASE(OP_EXT1, Z) {
2945       insn = READ_B();
2946       switch (insn) {
2947 #define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _1(); goto L_OP_ ## insn ## _BODY;
2948 #include "mruby/ops.h"
2949 #undef OPCODE
2950       }
2951       pc--;
2952       NEXT;
2953     }
2954     CASE(OP_EXT2, Z) {
2955       insn = READ_B();
2956       switch (insn) {
2957 #define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _2(); goto L_OP_ ## insn ## _BODY;
2958 #include "mruby/ops.h"
2959 #undef OPCODE
2960       }
2961       pc--;
2962       NEXT;
2963     }
2964     CASE(OP_EXT3, Z) {
2965       uint8_t insn = READ_B();
2966       switch (insn) {
2967 #define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _3(); goto L_OP_ ## insn ## _BODY;
2968 #include "mruby/ops.h"
2969 #undef OPCODE
2970       }
2971       pc--;
2972       NEXT;
2973     }
2974 
2975     CASE(OP_STOP, Z) {
2976       /*        stop VM */
2977     L_STOP:
2978       while (mrb->c->eidx > 0) {
2979         ecall(mrb);
2980       }
2981       mrb->c->cibase->ridx = 0;
2982       ERR_PC_CLR(mrb);
2983       mrb->jmp = prev_jmp;
2984       if (mrb->exc) {
2985         return mrb_obj_value(mrb->exc);
2986       }
2987       return regs[irep->nlocals];
2988     }
2989   }
2990   END_DISPATCH;
2991 #undef regs
2992   }
2993   MRB_CATCH(&c_jmp) {
2994     exc_catched = TRUE;
2995     goto RETRY_TRY_BLOCK;
2996   }
2997   MRB_END_EXC(&c_jmp);
2998 }
2999 
3000 MRB_API mrb_value
mrb_run(mrb_state * mrb,struct RProc * proc,mrb_value self)3001 mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
3002 {
3003   if (mrb->c->ci->argc < 0) {
3004     return mrb_vm_run(mrb, proc, self, 3); /* receiver, args and block) */
3005   }
3006   else {
3007     return mrb_vm_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */
3008   }
3009 }
3010 
3011 MRB_API mrb_value
mrb_top_run(mrb_state * mrb,struct RProc * proc,mrb_value self,unsigned int stack_keep)3012 mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep)
3013 {
3014   mrb_callinfo *ci;
3015   mrb_value v;
3016 
3017   if (!mrb->c->cibase) {
3018     return mrb_vm_run(mrb, proc, self, stack_keep);
3019   }
3020   if (mrb->c->ci == mrb->c->cibase) {
3021     return mrb_vm_run(mrb, proc, self, stack_keep);
3022   }
3023   ci = cipush(mrb);
3024   ci->mid = 0;
3025   ci->acc = CI_ACC_SKIP;
3026   ci->target_class = mrb->object_class;
3027   v = mrb_vm_run(mrb, proc, self, stack_keep);
3028   cipop(mrb);
3029 
3030   return v;
3031 }
3032 
3033 #if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus)
3034 # if !defined(MRB_ENABLE_CXX_ABI)
3035 } /* end of extern "C" */
3036 # endif
3037 mrb_int mrb_jmpbuf::jmpbuf_id = 0;
3038 # if !defined(MRB_ENABLE_CXX_ABI)
3039 extern "C" {
3040 # endif
3041 #endif
3042