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