source: EcnlProtoTool/trunk/mruby-1.2.0/src/vm.c@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 60.8 KB
Line 
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)
27extern "C" {
28#endif
29void 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/* Define amount of linear stack growth. */
39#ifndef MRB_STACK_GROWTH
40#define MRB_STACK_GROWTH 128
41#endif
42
43/* Maximum stack depth. Should be set lower on memory constrained systems.
44The value below allows about 60000 recursive calls in the simplest case. */
45#ifndef MRB_STACK_MAX
46#define MRB_STACK_MAX (0x40000 - MRB_STACK_GROWTH)
47#endif
48
49#ifdef VM_DEBUG
50# define DEBUG(x) (x)
51#else
52# define DEBUG(x)
53#endif
54
55#define ARENA_RESTORE(mrb,ai) (mrb)->gc.arena_idx = (ai)
56
57static inline void
58stack_clear(mrb_value *from, size_t count)
59{
60#ifndef MRB_NAN_BOXING
61 const mrb_value mrb_value_zero = { { 0 } };
62
63 while (count-- > 0) {
64 *from++ = mrb_value_zero;
65 }
66#else
67 while (count-- > 0) {
68 SET_NIL_VALUE(*from);
69 from++;
70 }
71#endif
72}
73
74static inline void
75stack_copy(mrb_value *dst, const mrb_value *src, size_t size)
76{
77 while (size-- > 0) {
78 *dst++ = *src++;
79 }
80}
81
82static void
83stack_init(mrb_state *mrb)
84{
85 struct mrb_context *c = mrb->c;
86
87 /* mrb_assert(mrb->stack == NULL); */
88 c->stbase = (mrb_value *)mrb_calloc(mrb, STACK_INIT_SIZE, sizeof(mrb_value));
89 c->stend = c->stbase + STACK_INIT_SIZE;
90 c->stack = c->stbase;
91
92 /* mrb_assert(ci == NULL); */
93 c->cibase = (mrb_callinfo *)mrb_calloc(mrb, CALLINFO_INIT_SIZE, sizeof(mrb_callinfo));
94 c->ciend = c->cibase + CALLINFO_INIT_SIZE;
95 c->ci = c->cibase;
96 c->ci->target_class = mrb->object_class;
97 c->ci->stackent = c->stack;
98}
99
100static inline void
101envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
102{
103 mrb_callinfo *ci = mrb->c->cibase;
104
105 if (newbase == oldbase) return;
106 while (ci <= mrb->c->ci) {
107 struct REnv *e = ci->env;
108 if (e && MRB_ENV_STACK_SHARED_P(e)) {
109 ptrdiff_t off = e->stack - oldbase;
110
111 e->stack = newbase + off;
112 }
113 ci->stackent = newbase + (ci->stackent - oldbase);
114 ci++;
115 }
116}
117
118static inline void
119init_new_stack_space(mrb_state *mrb, int room, int keep)
120{
121 if (room > keep) {
122 /* do not leave uninitialized malloc region */
123 stack_clear(&(mrb->c->stack[keep]), room - keep);
124 }
125}
126
127/** def rec ; $deep =+ 1 ; if $deep > 1000 ; return 0 ; end ; rec ; end */
128
129static void
130stack_extend_alloc(mrb_state *mrb, int room, int keep)
131{
132 mrb_value *oldbase = mrb->c->stbase;
133 int size = mrb->c->stend - mrb->c->stbase;
134 int off = mrb->c->stack - mrb->c->stbase;
135
136#ifdef MRB_STACK_EXTEND_DOUBLING
137 if (room <= size)
138 size *= 2;
139 else
140 size += room;
141#else
142 /* Use linear stack growth.
143 It is slightly slower than doubling the stack space,
144 but it saves memory on small devices. */
145 if (room <= MRB_STACK_GROWTH)
146 size += MRB_STACK_GROWTH;
147 else
148 size += room;
149#endif
150
151 mrb->c->stbase = (mrb_value *)mrb_realloc(mrb, mrb->c->stbase, sizeof(mrb_value) * size);
152 mrb->c->stack = mrb->c->stbase + off;
153 mrb->c->stend = mrb->c->stbase + size;
154 envadjust(mrb, oldbase, mrb->c->stbase);
155
156 /* Raise an exception if the new stack size will be too large,
157 to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */
158 if (size > MRB_STACK_MAX) {
159 init_new_stack_space(mrb, room, keep);
160 mrb_raise(mrb, E_SYSSTACK_ERROR, "stack level too deep. (limit=" MRB_STRINGIZE(MRB_STACK_MAX) ")");
161 }
162}
163
164static inline void
165stack_extend(mrb_state *mrb, int room, int keep)
166{
167 if (mrb->c->stack + room >= mrb->c->stend) {
168 stack_extend_alloc(mrb, room, keep);
169 }
170 init_new_stack_space(mrb, room, keep);
171}
172
173static inline struct REnv*
174uvenv(mrb_state *mrb, int up)
175{
176 struct REnv *e = mrb->c->ci->proc->env;
177
178 while (up--) {
179 if (!e) return NULL;
180 e = (struct REnv*)e->c;
181 }
182 return e;
183}
184
185static inline mrb_bool
186is_strict(mrb_state *mrb, struct REnv *e)
187{
188 int cioff = e->cioff;
189
190 if (MRB_ENV_STACK_SHARED_P(e) && mrb->c->cibase[cioff].proc &&
191 MRB_PROC_STRICT_P(mrb->c->cibase[cioff].proc)) {
192 return TRUE;
193 }
194 return FALSE;
195}
196
197static inline struct REnv*
198top_env(mrb_state *mrb, struct RProc *proc)
199{
200 struct REnv *e = proc->env;
201
202 if (is_strict(mrb, e)) return e;
203 while (e->c) {
204 e = (struct REnv*)e->c;
205 if (is_strict(mrb, e)) return e;
206 }
207 return e;
208}
209
210#define CI_ACC_SKIP -1
211#define CI_ACC_DIRECT -2
212
213static mrb_callinfo*
214cipush(mrb_state *mrb)
215{
216 struct mrb_context *c = mrb->c;
217 mrb_callinfo *ci = c->ci;
218
219 int eidx = ci->eidx;
220 int ridx = ci->ridx;
221
222 if (ci + 1 == c->ciend) {
223 ptrdiff_t size = ci - c->cibase;
224
225 c->cibase = (mrb_callinfo *)mrb_realloc(mrb, c->cibase, sizeof(mrb_callinfo)*size*2);
226 c->ci = c->cibase + size;
227 c->ciend = c->cibase + size * 2;
228 }
229 ci = ++c->ci;
230 ci->eidx = eidx;
231 ci->ridx = ridx;
232 ci->env = 0;
233 ci->pc = 0;
234 ci->err = 0;
235 ci->proc = 0;
236
237 return ci;
238}
239
240static void
241cipop(mrb_state *mrb)
242{
243 struct mrb_context *c = mrb->c;
244
245 if (c->ci->env) {
246 struct REnv *e = c->ci->env;
247 size_t len = (size_t)MRB_ENV_STACK_LEN(e);
248 mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
249
250 MRB_ENV_UNSHARE_STACK(e);
251 if (len > 0) {
252 stack_copy(p, e->stack, len);
253 }
254 e->stack = p;
255 mrb_write_barrier(mrb, (struct RBasic *)e);
256 }
257
258 c->ci--;
259}
260
261static void
262ecall(mrb_state *mrb, int i)
263{
264 struct RProc *p;
265 mrb_callinfo *ci;
266 mrb_value *self = mrb->c->stack;
267 struct RObject *exc;
268
269 if (i<0) return;
270 p = mrb->c->ensure[i];
271 if (!p) return;
272 if (mrb->c->ci->eidx > i)
273 mrb->c->ci->eidx = i;
274 ci = cipush(mrb);
275 ci->stackent = mrb->c->stack;
276 ci->mid = ci[-1].mid;
277 ci->acc = CI_ACC_SKIP;
278 ci->argc = 0;
279 ci->proc = p;
280 ci->nregs = p->body.irep->nregs;
281 ci->target_class = p->target_class;
282 mrb->c->stack = mrb->c->stack + ci[-1].nregs;
283 exc = mrb->exc; mrb->exc = 0;
284 mrb_run(mrb, p, *self);
285 mrb->c->ensure[i] = NULL;
286 if (!mrb->exc) mrb->exc = exc;
287}
288
289#ifndef MRB_FUNCALL_ARGC_MAX
290#define MRB_FUNCALL_ARGC_MAX 16
291#endif
292
293MRB_API mrb_value
294mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, mrb_int argc, ...)
295{
296 mrb_value argv[MRB_FUNCALL_ARGC_MAX];
297 va_list ap;
298 mrb_int i;
299 mrb_sym mid = mrb_intern_cstr(mrb, name);
300
301 if (argc > MRB_FUNCALL_ARGC_MAX) {
302 mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" MRB_STRINGIZE(MRB_FUNCALL_ARGC_MAX) ")");
303 }
304
305 va_start(ap, argc);
306 for (i = 0; i < argc; i++) {
307 argv[i] = va_arg(ap, mrb_value);
308 }
309 va_end(ap);
310 return mrb_funcall_argv(mrb, self, mid, argc, argv);
311}
312
313MRB_API mrb_value
314mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk)
315{
316 mrb_value val;
317
318 if (!mrb->jmp) {
319 struct mrb_jmpbuf c_jmp;
320 ptrdiff_t nth_ci = mrb->c->ci - mrb->c->cibase;
321
322 MRB_TRY(&c_jmp) {
323 mrb->jmp = &c_jmp;
324 /* recursive call */
325 val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk);
326 mrb->jmp = 0;
327 }
328 MRB_CATCH(&c_jmp) { /* error */
329 while (nth_ci < (mrb->c->ci - mrb->c->cibase)) {
330 mrb->c->stack = mrb->c->ci->stackent;
331 cipop(mrb);
332 }
333 mrb->jmp = 0;
334 val = mrb_obj_value(mrb->exc);
335 }
336 MRB_END_EXC(&c_jmp);
337 }
338 else {
339 struct RProc *p;
340 struct RClass *c;
341 mrb_sym undef = 0;
342 mrb_callinfo *ci;
343 int n;
344 ptrdiff_t voff = -1;
345
346 if (!mrb->c->stack) {
347 stack_init(mrb);
348 }
349 n = mrb->c->ci->nregs;
350 if (argc < 0) {
351 mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%S)", mrb_fixnum_value(argc));
352 }
353 c = mrb_class(mrb, self);
354 p = mrb_method_search_vm(mrb, &c, mid);
355 if (!p) {
356 undef = mid;
357 mid = mrb_intern_lit(mrb, "method_missing");
358 p = mrb_method_search_vm(mrb, &c, mid);
359 n++; argc++;
360 }
361 ci = cipush(mrb);
362 ci->mid = mid;
363 ci->proc = p;
364 ci->stackent = mrb->c->stack;
365 ci->argc = argc;
366 ci->target_class = c;
367 mrb->c->stack = mrb->c->stack + n;
368 if (mrb->c->stbase <= argv && argv < mrb->c->stend) {
369 voff = argv - mrb->c->stbase;
370 }
371 if (MRB_PROC_CFUNC_P(p)) {
372 ci->nregs = argc + 2;
373 stack_extend(mrb, ci->nregs, 0);
374 }
375 else {
376 ci->nregs = p->body.irep->nregs + n;
377 stack_extend(mrb, ci->nregs, argc+2);
378 }
379 if (voff >= 0) {
380 argv = mrb->c->stbase + voff;
381 }
382 mrb->c->stack[0] = self;
383 if (undef) {
384 mrb->c->stack[1] = mrb_symbol_value(undef);
385 if (argc > 1) {
386 stack_copy(mrb->c->stack+2, argv, argc-1);
387 }
388 }
389 else if (argc > 0) {
390 stack_copy(mrb->c->stack+1, argv, argc);
391 }
392 mrb->c->stack[argc+1] = blk;
393
394 if (MRB_PROC_CFUNC_P(p)) {
395 int ai = mrb_gc_arena_save(mrb);
396
397 ci->acc = CI_ACC_DIRECT;
398 val = p->body.func(mrb, self);
399 mrb->c->stack = mrb->c->ci->stackent;
400 cipop(mrb);
401 mrb_gc_arena_restore(mrb, ai);
402 }
403 else {
404 ci->acc = CI_ACC_SKIP;
405 val = mrb_run(mrb, p, self);
406 }
407 }
408 mrb_gc_protect(mrb, val);
409 return val;
410}
411
412MRB_API mrb_value
413mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv)
414{
415 return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value());
416}
417
418/* 15.3.1.3.4 */
419/* 15.3.1.3.44 */
420/*
421 * call-seq:
422 * obj.send(symbol [, args...]) -> obj
423 * obj.__send__(symbol [, args...]) -> obj
424 *
425 * Invokes the method identified by _symbol_, passing it any
426 * arguments specified. You can use <code>__send__</code> if the name
427 * +send+ clashes with an existing method in _obj_.
428 *
429 * class Klass
430 * def hello(*args)
431 * "Hello " + args.join(' ')
432 * end
433 * end
434 * k = Klass.new
435 * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
436 */
437MRB_API mrb_value
438mrb_f_send(mrb_state *mrb, mrb_value self)
439{
440 mrb_sym name;
441 mrb_value block, *argv, *regs;
442 mrb_int argc, i, len;
443 struct RProc *p;
444 struct RClass *c;
445 mrb_callinfo *ci;
446
447 mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block);
448
449 c = mrb_class(mrb, self);
450 p = mrb_method_search_vm(mrb, &c, name);
451
452 if (!p) { /* call method_mising */
453 return mrb_funcall_with_block(mrb, self, name, argc, argv, block);
454 }
455
456 ci = mrb->c->ci;
457 ci->mid = name;
458 ci->target_class = c;
459 ci->proc = p;
460 regs = mrb->c->stack+1;
461 /* remove first symbol from arguments */
462 if (ci->argc >= 0) {
463 for (i=0,len=ci->argc; i<len; i++) {
464 regs[i] = regs[i+1];
465 }
466 ci->argc--;
467 }
468 else { /* variable length arguments */
469 mrb_ary_shift(mrb, regs[0]);
470 }
471
472 if (MRB_PROC_CFUNC_P(p)) {
473 return p->body.func(mrb, self);
474 }
475
476 if (ci->argc < 0) {
477 stack_extend(mrb, (p->body.irep->nregs < 3) ? 3 : p->body.irep->nregs, 3);
478 }
479 else {
480 stack_extend(mrb, p->body.irep->nregs, ci->argc+2);
481 }
482
483 ci->nregs = p->body.irep->nregs;
484 ci = cipush(mrb);
485 ci->nregs = 0;
486 ci->target_class = 0;
487 ci->pc = p->body.irep->iseq;
488 ci->stackent = mrb->c->stack;
489 ci->acc = 0;
490
491 return self;
492}
493
494static mrb_value
495eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
496{
497 struct RProc *p;
498 mrb_callinfo *ci;
499
500 if (mrb_nil_p(blk)) {
501 mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
502 }
503 ci = mrb->c->ci;
504 if (ci->acc == CI_ACC_DIRECT) {
505 return mrb_yield_with_class(mrb, blk, 0, 0, self, c);
506 }
507 ci->target_class = c;
508 p = mrb_proc_ptr(blk);
509 ci->proc = p;
510 if (MRB_PROC_CFUNC_P(p)) {
511 return p->body.func(mrb, self);
512 }
513 ci->nregs = p->body.irep->nregs;
514 ci = cipush(mrb);
515 ci->nregs = 0;
516 ci->target_class = 0;
517 ci->pc = p->body.irep->iseq;
518 ci->stackent = mrb->c->stack;
519 ci->acc = 0;
520
521 return self;
522}
523
524/* 15.2.2.4.35 */
525/*
526 * call-seq:
527 * mod.class_eval {| | block } -> obj
528 * mod.module_eval {| | block } -> obj
529 *
530 * Evaluates block in the context of _mod_. This can
531 * be used to add methods to a class. <code>module_eval</code> returns
532 * the result of evaluating its argument.
533 */
534mrb_value
535mrb_mod_module_eval(mrb_state *mrb, mrb_value mod)
536{
537 mrb_value a, b;
538
539 if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
540 mrb_raise(mrb, E_NOTIMP_ERROR, "module_eval/class_eval with string not implemented");
541 }
542 return eval_under(mrb, mod, b, mrb_class_ptr(mod));
543}
544
545/* 15.3.1.3.18 */
546/*
547 * call-seq:
548 * obj.instance_eval {| | block } -> obj
549 *
550 * Evaluates the given block,within the context of the receiver (_obj_).
551 * In order to set the context, the variable +self+ is set to _obj_ while
552 * the code is executing, giving the code access to _obj_'s
553 * instance variables. In the version of <code>instance_eval</code>
554 * that takes a +String+, the optional second and third
555 * parameters supply a filename and starting line number that are used
556 * when reporting compilation errors.
557 *
558 * class KlassWithSecret
559 * def initialize
560 * @secret = 99
561 * end
562 * end
563 * k = KlassWithSecret.new
564 * k.instance_eval { @secret } #=> 99
565 */
566mrb_value
567mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
568{
569 mrb_value a, b;
570 mrb_value cv;
571 struct RClass *c;
572
573 if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
574 mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented");
575 }
576 switch (mrb_type(self)) {
577 case MRB_TT_SYMBOL:
578 case MRB_TT_FIXNUM:
579 case MRB_TT_FLOAT:
580 c = 0;
581 break;
582 default:
583 cv = mrb_singleton_class(mrb, self);
584 c = mrb_class_ptr(cv);
585 break;
586 }
587 return eval_under(mrb, self, b, c);
588}
589
590MRB_API mrb_value
591mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c)
592{
593 struct RProc *p;
594 mrb_sym mid = mrb->c->ci->mid;
595 mrb_callinfo *ci;
596 int n = mrb->c->ci->nregs;
597 mrb_value val;
598
599 if (mrb_nil_p(b)) {
600 mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
601 }
602 p = mrb_proc_ptr(b);
603 ci = cipush(mrb);
604 ci->mid = mid;
605 ci->proc = p;
606 ci->stackent = mrb->c->stack;
607 ci->argc = argc;
608 ci->target_class = c;
609 ci->acc = CI_ACC_SKIP;
610 mrb->c->stack = mrb->c->stack + n;
611 if (MRB_PROC_CFUNC_P(p)) {
612 ci->nregs = argc + 2;
613 stack_extend(mrb, ci->nregs, 0);
614 }
615 else {
616 ci->nregs = p->body.irep->nregs;
617 stack_extend(mrb, ci->nregs, argc+2);
618 }
619
620 mrb->c->stack[0] = self;
621 if (argc > 0) {
622 stack_copy(mrb->c->stack+1, argv, argc);
623 }
624 mrb->c->stack[argc+1] = mrb_nil_value();
625
626 if (MRB_PROC_CFUNC_P(p)) {
627 val = p->body.func(mrb, self);
628 mrb->c->stack = mrb->c->ci->stackent;
629 cipop(mrb);
630 }
631 else {
632 val = mrb_run(mrb, p, self);
633 }
634 return val;
635}
636
637MRB_API mrb_value
638mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv)
639{
640 struct RProc *p = mrb_proc_ptr(b);
641
642 return mrb_yield_with_class(mrb, b, argc, argv, p->env->stack[0], p->target_class);
643}
644
645MRB_API mrb_value
646mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg)
647{
648 struct RProc *p = mrb_proc_ptr(b);
649
650 return mrb_yield_with_class(mrb, b, 1, &arg, p->env->stack[0], p->target_class);
651}
652
653typedef enum {
654 LOCALJUMP_ERROR_RETURN = 0,
655 LOCALJUMP_ERROR_BREAK = 1,
656 LOCALJUMP_ERROR_YIELD = 2
657} localjump_error_kind;
658
659static void
660localjump_error(mrb_state *mrb, localjump_error_kind kind)
661{
662 char kind_str[3][7] = { "return", "break", "yield" };
663 char kind_str_len[] = { 6, 5, 5 };
664 static const char lead[] = "unexpected ";
665 mrb_value msg;
666 mrb_value exc;
667
668 msg = mrb_str_buf_new(mrb, sizeof(lead) + 7);
669 mrb_str_cat(mrb, msg, lead, sizeof(lead) - 1);
670 mrb_str_cat(mrb, msg, kind_str[kind], kind_str_len[kind]);
671 exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg);
672 mrb->exc = mrb_obj_ptr(exc);
673}
674
675static void
676argnum_error(mrb_state *mrb, mrb_int num)
677{
678 mrb_value exc;
679 mrb_value str;
680
681 if (mrb->c->ci->mid) {
682 str = mrb_format(mrb, "'%S': wrong number of arguments (%S for %S)",
683 mrb_sym2str(mrb, mrb->c->ci->mid),
684 mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num));
685 }
686 else {
687 str = mrb_format(mrb, "wrong number of arguments (%S for %S)",
688 mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num));
689 }
690 exc = mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str);
691 mrb->exc = mrb_obj_ptr(exc);
692}
693
694#define ERR_PC_SET(mrb, pc) mrb->c->ci->err = pc;
695#define ERR_PC_CLR(mrb) mrb->c->ci->err = 0;
696#ifdef MRB_ENABLE_DEBUG_HOOK
697#define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs));
698#else
699#define CODE_FETCH_HOOK(mrb, irep, pc, regs)
700#endif
701
702#if defined __GNUC__ || defined __clang__ || defined __INTEL_COMPILER
703#define DIRECT_THREADED
704#endif
705
706#ifndef DIRECT_THREADED
707
708#define INIT_DISPATCH for (;;) { i = *pc; CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (GET_OPCODE(i)) {
709#define CASE(op) case op:
710#define NEXT pc++; break
711#define JUMP break
712#define END_DISPATCH }}
713
714#else
715
716#define INIT_DISPATCH JUMP; return mrb_nil_value();
717#define CASE(op) L_ ## op:
718#define NEXT i=*++pc; CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)]
719#define JUMP i=*pc; CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)]
720
721#define END_DISPATCH
722
723#endif
724
725#define CALL_MAXARGS 127
726
727void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args);
728
729MRB_API mrb_value
730mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep)
731{
732 /* mrb_assert(mrb_proc_cfunc_p(proc)) */
733 mrb_irep *irep = proc->body.irep;
734 mrb_code *pc = irep->iseq;
735 mrb_value *pool = irep->pool;
736 mrb_sym *syms = irep->syms;
737 mrb_value *regs = NULL;
738 mrb_code i;
739 int ai = mrb_gc_arena_save(mrb);
740 struct mrb_jmpbuf *prev_jmp = mrb->jmp;
741 struct mrb_jmpbuf c_jmp;
742
743#ifdef DIRECT_THREADED
744 static void *optable[] = {
745 &&L_OP_NOP, &&L_OP_MOVE,
746 &&L_OP_LOADL, &&L_OP_LOADI, &&L_OP_LOADSYM, &&L_OP_LOADNIL,
747 &&L_OP_LOADSELF, &&L_OP_LOADT, &&L_OP_LOADF,
748 &&L_OP_GETGLOBAL, &&L_OP_SETGLOBAL, &&L_OP_GETSPECIAL, &&L_OP_SETSPECIAL,
749 &&L_OP_GETIV, &&L_OP_SETIV, &&L_OP_GETCV, &&L_OP_SETCV,
750 &&L_OP_GETCONST, &&L_OP_SETCONST, &&L_OP_GETMCNST, &&L_OP_SETMCNST,
751 &&L_OP_GETUPVAR, &&L_OP_SETUPVAR,
752 &&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_JMPNOT,
753 &&L_OP_ONERR, &&L_OP_RESCUE, &&L_OP_POPERR, &&L_OP_RAISE, &&L_OP_EPUSH, &&L_OP_EPOP,
754 &&L_OP_SEND, &&L_OP_SENDB, &&L_OP_FSEND,
755 &&L_OP_CALL, &&L_OP_SUPER, &&L_OP_ARGARY, &&L_OP_ENTER,
756 &&L_OP_KARG, &&L_OP_KDICT, &&L_OP_RETURN, &&L_OP_TAILCALL, &&L_OP_BLKPUSH,
757 &&L_OP_ADD, &&L_OP_ADDI, &&L_OP_SUB, &&L_OP_SUBI, &&L_OP_MUL, &&L_OP_DIV,
758 &&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_GT, &&L_OP_GE,
759 &&L_OP_ARRAY, &&L_OP_ARYCAT, &&L_OP_ARYPUSH, &&L_OP_AREF, &&L_OP_ASET, &&L_OP_APOST,
760 &&L_OP_STRING, &&L_OP_STRCAT, &&L_OP_HASH,
761 &&L_OP_LAMBDA, &&L_OP_RANGE, &&L_OP_OCLASS,
762 &&L_OP_CLASS, &&L_OP_MODULE, &&L_OP_EXEC,
763 &&L_OP_METHOD, &&L_OP_SCLASS, &&L_OP_TCLASS,
764 &&L_OP_DEBUG, &&L_OP_STOP, &&L_OP_ERR,
765 };
766#endif
767
768 mrb_bool exc_catched = FALSE;
769RETRY_TRY_BLOCK:
770
771 MRB_TRY(&c_jmp) {
772
773 if (exc_catched) {
774 exc_catched = FALSE;
775 goto L_RAISE;
776 }
777 mrb->jmp = &c_jmp;
778 if (!mrb->c->stack) {
779 stack_init(mrb);
780 }
781 stack_extend(mrb, irep->nregs, stack_keep);
782 mrb->c->ci->proc = proc;
783 mrb->c->ci->nregs = irep->nregs;
784 regs = mrb->c->stack;
785 regs[0] = self;
786
787 INIT_DISPATCH {
788 CASE(OP_NOP) {
789 /* do nothing */
790 NEXT;
791 }
792
793 CASE(OP_MOVE) {
794 /* A B R(A) := R(B) */
795 regs[GETARG_A(i)] = regs[GETARG_B(i)];
796 NEXT;
797 }
798
799 CASE(OP_LOADL) {
800 /* A Bx R(A) := Pool(Bx) */
801 regs[GETARG_A(i)] = pool[GETARG_Bx(i)];
802 NEXT;
803 }
804
805 CASE(OP_LOADI) {
806 /* A sBx R(A) := sBx */
807 SET_INT_VALUE(regs[GETARG_A(i)], GETARG_sBx(i));
808 NEXT;
809 }
810
811 CASE(OP_LOADSYM) {
812 /* A Bx R(A) := Syms(Bx) */
813 SET_SYM_VALUE(regs[GETARG_A(i)], syms[GETARG_Bx(i)]);
814 NEXT;
815 }
816
817 CASE(OP_LOADSELF) {
818 /* A R(A) := self */
819 regs[GETARG_A(i)] = regs[0];
820 NEXT;
821 }
822
823 CASE(OP_LOADT) {
824 /* A R(A) := true */
825 SET_TRUE_VALUE(regs[GETARG_A(i)]);
826 NEXT;
827 }
828
829 CASE(OP_LOADF) {
830 /* A R(A) := false */
831 SET_FALSE_VALUE(regs[GETARG_A(i)]);
832 NEXT;
833 }
834
835 CASE(OP_GETGLOBAL) {
836 /* A Bx R(A) := getglobal(Syms(Bx)) */
837 regs[GETARG_A(i)] = mrb_gv_get(mrb, syms[GETARG_Bx(i)]);
838 NEXT;
839 }
840
841 CASE(OP_SETGLOBAL) {
842 /* setglobal(Syms(Bx), R(A)) */
843 mrb_gv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]);
844 NEXT;
845 }
846
847 CASE(OP_GETSPECIAL) {
848 /* A Bx R(A) := Special[Bx] */
849 regs[GETARG_A(i)] = mrb_vm_special_get(mrb, GETARG_Bx(i));
850 NEXT;
851 }
852
853 CASE(OP_SETSPECIAL) {
854 /* A Bx Special[Bx] := R(A) */
855 mrb_vm_special_set(mrb, GETARG_Bx(i), regs[GETARG_A(i)]);
856 NEXT;
857 }
858
859 CASE(OP_GETIV) {
860 /* A Bx R(A) := ivget(Bx) */
861 regs[GETARG_A(i)] = mrb_vm_iv_get(mrb, syms[GETARG_Bx(i)]);
862 NEXT;
863 }
864
865 CASE(OP_SETIV) {
866 /* ivset(Syms(Bx),R(A)) */
867 mrb_vm_iv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]);
868 NEXT;
869 }
870
871 CASE(OP_GETCV) {
872 /* A Bx R(A) := cvget(Syms(Bx)) */
873 ERR_PC_SET(mrb, pc);
874 regs[GETARG_A(i)] = mrb_vm_cv_get(mrb, syms[GETARG_Bx(i)]);
875 ERR_PC_CLR(mrb);
876 NEXT;
877 }
878
879 CASE(OP_SETCV) {
880 /* cvset(Syms(Bx),R(A)) */
881 mrb_vm_cv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]);
882 NEXT;
883 }
884
885 CASE(OP_GETCONST) {
886 /* A Bx R(A) := constget(Syms(Bx)) */
887 mrb_value val;
888
889 ERR_PC_SET(mrb, pc);
890 val = mrb_vm_const_get(mrb, syms[GETARG_Bx(i)]);
891 ERR_PC_CLR(mrb);
892 regs = mrb->c->stack;
893 regs[GETARG_A(i)] = val;
894 NEXT;
895 }
896
897 CASE(OP_SETCONST) {
898 /* A Bx constset(Syms(Bx),R(A)) */
899 mrb_vm_const_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]);
900 NEXT;
901 }
902
903 CASE(OP_GETMCNST) {
904 /* A Bx R(A) := R(A)::Syms(Bx) */
905 mrb_value val;
906 int a = GETARG_A(i);
907
908 ERR_PC_SET(mrb, pc);
909 val = mrb_const_get(mrb, regs[a], syms[GETARG_Bx(i)]);
910 ERR_PC_CLR(mrb);
911 regs = mrb->c->stack;
912 regs[a] = val;
913 NEXT;
914 }
915
916 CASE(OP_SETMCNST) {
917 /* A Bx R(A+1)::Syms(Bx) := R(A) */
918 int a = GETARG_A(i);
919
920 mrb_const_set(mrb, regs[a+1], syms[GETARG_Bx(i)], regs[a]);
921 NEXT;
922 }
923
924 CASE(OP_GETUPVAR) {
925 /* A B C R(A) := uvget(B,C) */
926 mrb_value *regs_a = regs + GETARG_A(i);
927 int up = GETARG_C(i);
928
929 struct REnv *e = uvenv(mrb, up);
930
931 if (!e) {
932 *regs_a = mrb_nil_value();
933 }
934 else {
935 int idx = GETARG_B(i);
936 *regs_a = e->stack[idx];
937 }
938 NEXT;
939 }
940
941 CASE(OP_SETUPVAR) {
942 /* A B C uvset(B,C,R(A)) */
943 int up = GETARG_C(i);
944
945 struct REnv *e = uvenv(mrb, up);
946
947 if (e) {
948 mrb_value *regs_a = regs + GETARG_A(i);
949 int idx = GETARG_B(i);
950 e->stack[idx] = *regs_a;
951 mrb_write_barrier(mrb, (struct RBasic*)e);
952 }
953 NEXT;
954 }
955
956 CASE(OP_JMP) {
957 /* sBx pc+=sBx */
958 pc += GETARG_sBx(i);
959 JUMP;
960 }
961
962 CASE(OP_JMPIF) {
963 /* A sBx if R(A) pc+=sBx */
964 if (mrb_test(regs[GETARG_A(i)])) {
965 pc += GETARG_sBx(i);
966 JUMP;
967 }
968 NEXT;
969 }
970
971 CASE(OP_JMPNOT) {
972 /* A sBx if !R(A) pc+=sBx */
973 if (!mrb_test(regs[GETARG_A(i)])) {
974 pc += GETARG_sBx(i);
975 JUMP;
976 }
977 NEXT;
978 }
979
980 CASE(OP_ONERR) {
981 /* sBx pc+=sBx on exception */
982 if (mrb->c->rsize <= mrb->c->ci->ridx) {
983 if (mrb->c->rsize == 0) mrb->c->rsize = 16;
984 else mrb->c->rsize *= 2;
985 mrb->c->rescue = (mrb_code **)mrb_realloc(mrb, mrb->c->rescue, sizeof(mrb_code*) * mrb->c->rsize);
986 }
987 mrb->c->rescue[mrb->c->ci->ridx++] = pc + GETARG_sBx(i);
988 NEXT;
989 }
990
991 CASE(OP_RESCUE) {
992 /* A R(A) := exc; clear(exc) */
993 SET_OBJ_VALUE(regs[GETARG_A(i)], mrb->exc);
994 mrb->exc = 0;
995 NEXT;
996 }
997
998 CASE(OP_POPERR) {
999 /* A A.times{rescue_pop()} */
1000 int a = GETARG_A(i);
1001
1002 while (a--) {
1003 mrb->c->ci->ridx--;
1004 }
1005 NEXT;
1006 }
1007
1008 CASE(OP_RAISE) {
1009 /* A raise(R(A)) */
1010 mrb->exc = mrb_obj_ptr(regs[GETARG_A(i)]);
1011 goto L_RAISE;
1012 }
1013
1014 CASE(OP_EPUSH) {
1015 /* Bx ensure_push(SEQ[Bx]) */
1016 struct RProc *p;
1017
1018 p = mrb_closure_new(mrb, irep->reps[GETARG_Bx(i)]);
1019 /* push ensure_stack */
1020 if (mrb->c->esize <= mrb->c->ci->eidx) {
1021 if (mrb->c->esize == 0) mrb->c->esize = 16;
1022 else mrb->c->esize *= 2;
1023 mrb->c->ensure = (struct RProc **)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*) * mrb->c->esize);
1024 }
1025 mrb->c->ensure[mrb->c->ci->eidx++] = p;
1026 ARENA_RESTORE(mrb, ai);
1027 NEXT;
1028 }
1029
1030 CASE(OP_EPOP) {
1031 /* A A.times{ensure_pop().call} */
1032 int a = GETARG_A(i);
1033 mrb_callinfo *ci = mrb->c->ci;
1034 int n, eidx = ci->eidx;
1035
1036 for (n=0; n<a && (ci == mrb->c->cibase || eidx > ci[-1].eidx); n++) {
1037 ecall(mrb, --eidx);
1038 ARENA_RESTORE(mrb, ai);
1039 }
1040 NEXT;
1041 }
1042
1043 CASE(OP_LOADNIL) {
1044 /* A R(A) := nil */
1045 int a = GETARG_A(i);
1046
1047 SET_NIL_VALUE(regs[a]);
1048 NEXT;
1049 }
1050
1051 CASE(OP_SENDB) {
1052 /* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/
1053 /* fall through */
1054 };
1055
1056 L_SEND:
1057 CASE(OP_SEND) {
1058 /* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */
1059 int a = GETARG_A(i);
1060 int n = GETARG_C(i);
1061 struct RProc *m;
1062 struct RClass *c;
1063 mrb_callinfo *ci;
1064 mrb_value recv, result;
1065 mrb_sym mid = syms[GETARG_B(i)];
1066
1067 recv = regs[a];
1068 if (GET_OPCODE(i) != OP_SENDB) {
1069 if (n == CALL_MAXARGS) {
1070 SET_NIL_VALUE(regs[a+2]);
1071 }
1072 else {
1073 SET_NIL_VALUE(regs[a+n+1]);
1074 }
1075 }
1076 c = mrb_class(mrb, recv);
1077 m = mrb_method_search_vm(mrb, &c, mid);
1078 if (!m) {
1079 mrb_value sym = mrb_symbol_value(mid);
1080 mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
1081
1082 m = mrb_method_search_vm(mrb, &c, missing);
1083 if (!m) {
1084 mrb_value args;
1085
1086 if (n == CALL_MAXARGS) {
1087 args = regs[a+1];
1088 }
1089 else {
1090 args = mrb_ary_new_from_values(mrb, n, regs+a+1);
1091 }
1092 mrb_method_missing(mrb, mid, recv, args);
1093 }
1094 mid = missing;
1095 if (n == CALL_MAXARGS) {
1096 mrb_ary_unshift(mrb, regs[a+1], sym);
1097 }
1098 else {
1099 value_move(regs+a+2, regs+a+1, ++n);
1100 regs[a+1] = sym;
1101 }
1102 }
1103
1104 /* push callinfo */
1105 ci = cipush(mrb);
1106 ci->mid = mid;
1107 ci->proc = m;
1108 ci->stackent = mrb->c->stack;
1109 ci->target_class = c;
1110
1111 ci->pc = pc + 1;
1112 ci->acc = a;
1113
1114 /* prepare stack */
1115 mrb->c->stack += a;
1116
1117 if (MRB_PROC_CFUNC_P(m)) {
1118 if (n == CALL_MAXARGS) {
1119 ci->argc = -1;
1120 ci->nregs = 3;
1121 }
1122 else {
1123 ci->argc = n;
1124 ci->nregs = n + 2;
1125 }
1126 result = m->body.func(mrb, recv);
1127 mrb->c->stack[0] = result;
1128 mrb_gc_arena_restore(mrb, ai);
1129 if (mrb->exc) goto L_RAISE;
1130 /* pop stackpos */
1131 ci = mrb->c->ci;
1132 if (!ci->target_class) { /* return from context modifying method (resume/yield) */
1133 if (!MRB_PROC_CFUNC_P(ci[-1].proc)) {
1134 proc = ci[-1].proc;
1135 irep = proc->body.irep;
1136 pool = irep->pool;
1137 syms = irep->syms;
1138 }
1139 }
1140 regs = mrb->c->stack = ci->stackent;
1141 pc = ci->pc;
1142 cipop(mrb);
1143 JUMP;
1144 }
1145 else {
1146 /* setup environment for calling method */
1147 proc = mrb->c->ci->proc = m;
1148 irep = m->body.irep;
1149 pool = irep->pool;
1150 syms = irep->syms;
1151 ci->nregs = irep->nregs;
1152 if (n == CALL_MAXARGS) {
1153 ci->argc = -1;
1154 stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
1155 }
1156 else {
1157 ci->argc = n;
1158 stack_extend(mrb, irep->nregs, n+2);
1159 }
1160 regs = mrb->c->stack;
1161 pc = irep->iseq;
1162 JUMP;
1163 }
1164 }
1165
1166 CASE(OP_FSEND) {
1167 /* A B C R(A) := fcall(R(A),Syms(B),R(A+1),... ,R(A+C-1)) */
1168 NEXT;
1169 }
1170
1171 CASE(OP_CALL) {
1172 /* A R(A) := self.call(frame.argc, frame.argv) */
1173 mrb_callinfo *ci;
1174 mrb_value recv = mrb->c->stack[0];
1175 struct RProc *m = mrb_proc_ptr(recv);
1176
1177 /* replace callinfo */
1178 ci = mrb->c->ci;
1179 ci->target_class = m->target_class;
1180 ci->proc = m;
1181 if (m->env) {
1182 if (m->env->mid) {
1183 ci->mid = m->env->mid;
1184 }
1185 if (!m->env->stack) {
1186 m->env->stack = mrb->c->stack;
1187 }
1188 }
1189
1190 /* prepare stack */
1191 if (MRB_PROC_CFUNC_P(m)) {
1192 recv = m->body.func(mrb, recv);
1193 mrb_gc_arena_restore(mrb, ai);
1194 if (mrb->exc) goto L_RAISE;
1195 /* pop stackpos */
1196 ci = mrb->c->ci;
1197 regs = mrb->c->stack = ci->stackent;
1198 regs[ci->acc] = recv;
1199 pc = ci->pc;
1200 cipop(mrb);
1201 irep = mrb->c->ci->proc->body.irep;
1202 pool = irep->pool;
1203 syms = irep->syms;
1204 JUMP;
1205 }
1206 else {
1207 /* setup environment for calling method */
1208 proc = m;
1209 irep = m->body.irep;
1210 if (!irep) {
1211 mrb->c->stack[0] = mrb_nil_value();
1212 goto L_RETURN;
1213 }
1214 pool = irep->pool;
1215 syms = irep->syms;
1216 ci->nregs = irep->nregs;
1217 if (ci->argc < 0) {
1218 stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
1219 }
1220 else {
1221 stack_extend(mrb, irep->nregs, ci->argc+2);
1222 }
1223 regs = mrb->c->stack;
1224 regs[0] = m->env->stack[0];
1225 pc = irep->iseq;
1226 JUMP;
1227 }
1228 }
1229
1230 CASE(OP_SUPER) {
1231 /* A C R(A) := super(R(A+1),... ,R(A+C+1)) */
1232 mrb_value recv;
1233 mrb_callinfo *ci = mrb->c->ci;
1234 struct RProc *m;
1235 struct RClass *c;
1236 mrb_sym mid = ci->mid;
1237 int a = GETARG_A(i);
1238 int n = GETARG_C(i);
1239
1240 if (mid == 0) {
1241 mrb_value exc;
1242
1243 exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method");
1244 mrb->exc = mrb_obj_ptr(exc);
1245 goto L_RAISE;
1246 }
1247 recv = regs[0];
1248 c = mrb->c->ci->target_class->super;
1249 m = mrb_method_search_vm(mrb, &c, mid);
1250 if (!m) {
1251 mid = mrb_intern_lit(mrb, "method_missing");
1252 m = mrb_method_search_vm(mrb, &c, mid);
1253 if (n == CALL_MAXARGS) {
1254 mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid));
1255 }
1256 else {
1257 value_move(regs+a+2, regs+a+1, ++n);
1258 SET_SYM_VALUE(regs[a+1], ci->mid);
1259 }
1260 }
1261
1262 /* push callinfo */
1263 ci = cipush(mrb);
1264 ci->mid = mid;
1265 ci->proc = m;
1266 ci->stackent = mrb->c->stack;
1267 if (n == CALL_MAXARGS) {
1268 ci->argc = -1;
1269 }
1270 else {
1271 ci->argc = n;
1272 }
1273 ci->target_class = c;
1274 ci->pc = pc + 1;
1275
1276 /* prepare stack */
1277 mrb->c->stack += a;
1278 mrb->c->stack[0] = recv;
1279
1280 if (MRB_PROC_CFUNC_P(m)) {
1281 if (n == CALL_MAXARGS) {
1282 ci->nregs = 3;
1283 }
1284 else {
1285 ci->nregs = n + 2;
1286 }
1287 mrb->c->stack[0] = m->body.func(mrb, recv);
1288 mrb_gc_arena_restore(mrb, ai);
1289 if (mrb->exc) goto L_RAISE;
1290 /* pop stackpos */
1291 regs = mrb->c->stack = mrb->c->ci->stackent;
1292 cipop(mrb);
1293 NEXT;
1294 }
1295 else {
1296 /* fill callinfo */
1297 ci->acc = a;
1298
1299 /* setup environment for calling method */
1300 ci->proc = m;
1301 irep = m->body.irep;
1302 pool = irep->pool;
1303 syms = irep->syms;
1304 ci->nregs = irep->nregs;
1305 if (n == CALL_MAXARGS) {
1306 stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
1307 }
1308 else {
1309 stack_extend(mrb, irep->nregs, ci->argc+2);
1310 }
1311 regs = mrb->c->stack;
1312 pc = irep->iseq;
1313 JUMP;
1314 }
1315 }
1316
1317 CASE(OP_ARGARY) {
1318 /* A Bx R(A) := argument array (16=6:1:5:4) */
1319 int a = GETARG_A(i);
1320 int bx = GETARG_Bx(i);
1321 int m1 = (bx>>10)&0x3f;
1322 int r = (bx>>9)&0x1;
1323 int m2 = (bx>>4)&0x1f;
1324 int lv = (bx>>0)&0xf;
1325 mrb_value *stack;
1326
1327 if (lv == 0) stack = regs + 1;
1328 else {
1329 struct REnv *e = uvenv(mrb, lv-1);
1330 if (!e) {
1331 mrb_value exc;
1332
1333 exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method");
1334 mrb->exc = mrb_obj_ptr(exc);
1335 goto L_RAISE;
1336 }
1337 stack = e->stack + 1;
1338 }
1339 if (r == 0) {
1340 regs[a] = mrb_ary_new_from_values(mrb, m1+m2, stack);
1341 }
1342 else {
1343 mrb_value *pp = NULL;
1344 struct RArray *rest;
1345 int len = 0;
1346
1347 if (mrb_array_p(stack[m1])) {
1348 struct RArray *ary = mrb_ary_ptr(stack[m1]);
1349
1350 pp = ary->ptr;
1351 len = ary->len;
1352 }
1353 regs[a] = mrb_ary_new_capa(mrb, m1+len+m2);
1354 rest = mrb_ary_ptr(regs[a]);
1355 if (m1 > 0) {
1356 stack_copy(rest->ptr, stack, m1);
1357 }
1358 if (len > 0) {
1359 stack_copy(rest->ptr+m1, pp, len);
1360 }
1361 if (m2 > 0) {
1362 stack_copy(rest->ptr+m1+len, stack+m1+1, m2);
1363 }
1364 rest->len = m1+len+m2;
1365 }
1366 regs[a+1] = stack[m1+r+m2];
1367 ARENA_RESTORE(mrb, ai);
1368 NEXT;
1369 }
1370
1371 CASE(OP_ENTER) {
1372 /* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */
1373 /* number of optional arguments times OP_JMP should follow */
1374 mrb_aspec ax = GETARG_Ax(i);
1375 int m1 = MRB_ASPEC_REQ(ax);
1376 int o = MRB_ASPEC_OPT(ax);
1377 int r = MRB_ASPEC_REST(ax);
1378 int m2 = MRB_ASPEC_POST(ax);
1379 /* unused
1380 int k = MRB_ASPEC_KEY(ax);
1381 int kd = MRB_ASPEC_KDICT(ax);
1382 int b = MRB_ASPEC_BLOCK(ax);
1383 */
1384 int argc = mrb->c->ci->argc;
1385 mrb_value *argv = regs+1;
1386 mrb_value *argv0 = argv;
1387 int len = m1 + o + r + m2;
1388 mrb_value *blk = &argv[argc < 0 ? 1 : argc];
1389
1390 if (!mrb_nil_p(*blk) && mrb_type(*blk) != MRB_TT_PROC) {
1391 *blk = mrb_convert_type(mrb, *blk, MRB_TT_PROC, "Proc", "to_proc");
1392 }
1393 if (argc < 0) {
1394 struct RArray *ary = mrb_ary_ptr(regs[1]);
1395 argv = ary->ptr;
1396 argc = ary->len;
1397 mrb_gc_protect(mrb, regs[1]);
1398 }
1399 if (mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc)) {
1400 if (argc >= 0) {
1401 if (argc < m1 + m2 || (r == 0 && argc > len)) {
1402 argnum_error(mrb, m1+m2);
1403 goto L_RAISE;
1404 }
1405 }
1406 }
1407 else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) {
1408 mrb_gc_protect(mrb, argv[0]);
1409 argc = mrb_ary_ptr(argv[0])->len;
1410 argv = mrb_ary_ptr(argv[0])->ptr;
1411 }
1412 mrb->c->ci->argc = len;
1413 if (argc < len) {
1414 int mlen = m2;
1415 if (argc < m1+m2) {
1416 if (m1 < argc)
1417 mlen = argc - m1;
1418 else
1419 mlen = 0;
1420 }
1421 regs[len+1] = *blk; /* move block */
1422 SET_NIL_VALUE(regs[argc+1]);
1423 if (argv0 != argv) {
1424 value_move(&regs[1], argv, argc-mlen); /* m1 + o */
1425 }
1426 if (mlen) {
1427 value_move(&regs[len-m2+1], &argv[argc-mlen], mlen);
1428 }
1429 if (r) {
1430 regs[m1+o+1] = mrb_ary_new_capa(mrb, 0);
1431 }
1432 if (o == 0 || argc < m1+m2) pc++;
1433 else
1434 pc += argc - m1 - m2 + 1;
1435 }
1436 else {
1437 int rnum = 0;
1438 if (argv0 != argv) {
1439 regs[len+1] = *blk; /* move block */
1440 value_move(&regs[1], argv, m1+o);
1441 }
1442 if (r) {
1443 rnum = argc-m1-o-m2;
1444 regs[m1+o+1] = mrb_ary_new_from_values(mrb, rnum, argv+m1+o);
1445 }
1446 if (m2) {
1447 if (argc-m2 > m1) {
1448 value_move(&regs[m1+o+r+1], &argv[m1+o+rnum], m2);
1449 }
1450 }
1451 if (argv0 == argv) {
1452 regs[len+1] = *blk; /* move block */
1453 }
1454 pc += o + 1;
1455 }
1456 JUMP;
1457 }
1458
1459 CASE(OP_KARG) {
1460 /* A B C R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */
1461 /* if C == 2; raise unless kdict.empty? */
1462 /* OP_JMP should follow to skip init code */
1463 NEXT;
1464 }
1465
1466 CASE(OP_KDICT) {
1467 /* A C R(A) := kdict */
1468 NEXT;
1469 }
1470
1471 L_RETURN:
1472 i = MKOP_AB(OP_RETURN, GETARG_A(i), OP_R_NORMAL);
1473 /* fall through */
1474 CASE(OP_RETURN) {
1475 /* A B return R(A) (B=normal,in-block return/break) */
1476 if (mrb->exc) {
1477 mrb_callinfo *ci;
1478 int eidx;
1479
1480 L_RAISE:
1481 ci = mrb->c->ci;
1482 mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern_lit(mrb, "lastpc"), mrb_cptr_value(mrb, pc));
1483 mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern_lit(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->c->cibase));
1484 eidx = ci->eidx;
1485 if (ci == mrb->c->cibase) {
1486 if (ci->ridx == 0) goto L_STOP;
1487 goto L_RESCUE;
1488 }
1489 while (ci[0].ridx == ci[-1].ridx) {
1490 cipop(mrb);
1491 ci = mrb->c->ci;
1492 mrb->c->stack = ci[1].stackent;
1493 if (ci[1].acc == CI_ACC_SKIP && prev_jmp) {
1494 mrb->jmp = prev_jmp;
1495 MRB_THROW(prev_jmp);
1496 }
1497 if (ci == mrb->c->cibase) {
1498 while (eidx > 0) {
1499 ecall(mrb, --eidx);
1500 }
1501 if (ci->ridx == 0) {
1502 if (mrb->c == mrb->root_c) {
1503 regs = mrb->c->stack = mrb->c->stbase;
1504 goto L_STOP;
1505 }
1506 else {
1507 struct mrb_context *c = mrb->c;
1508
1509 mrb->c = c->prev;
1510 c->prev = NULL;
1511 goto L_RAISE;
1512 }
1513 }
1514 break;
1515 }
1516 /* call ensure only when we skip this callinfo */
1517 if (ci[0].ridx == ci[-1].ridx) {
1518 while (eidx > ci[-1].eidx) {
1519 ecall(mrb, --eidx);
1520 }
1521 }
1522 }
1523 L_RESCUE:
1524 if (ci->ridx == 0) goto L_STOP;
1525 proc = ci->proc;
1526 irep = proc->body.irep;
1527 pool = irep->pool;
1528 syms = irep->syms;
1529 regs = mrb->c->stack = ci[1].stackent;
1530 pc = mrb->c->rescue[--ci->ridx];
1531 }
1532 else {
1533 mrb_callinfo *ci = mrb->c->ci;
1534 int acc, eidx = mrb->c->ci->eidx;
1535 mrb_value v = regs[GETARG_A(i)];
1536
1537 switch (GETARG_B(i)) {
1538 case OP_R_RETURN:
1539 /* Fall through to OP_R_NORMAL otherwise */
1540 if (proc->env && !MRB_PROC_STRICT_P(proc)) {
1541 struct REnv *e = top_env(mrb, proc);
1542
1543 if (!MRB_ENV_STACK_SHARED_P(e)) {
1544 localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
1545 goto L_RAISE;
1546 }
1547 ci = mrb->c->cibase + e->cioff;
1548 if (ci == mrb->c->cibase) {
1549 localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
1550 goto L_RAISE;
1551 }
1552 mrb->c->stack = mrb->c->ci->stackent;
1553 mrb->c->ci = ci;
1554 break;
1555 }
1556 case OP_R_NORMAL:
1557 if (ci == mrb->c->cibase) {
1558 if (!mrb->c->prev) { /* toplevel return */
1559 localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
1560 goto L_RAISE;
1561 }
1562 if (mrb->c->prev->ci == mrb->c->prev->cibase) {
1563 mrb_value exc = mrb_exc_new_str_lit(mrb, E_FIBER_ERROR, "double resume");
1564 mrb->exc = mrb_obj_ptr(exc);
1565 goto L_RAISE;
1566 }
1567 /* automatic yield at the end */
1568 mrb->c->status = MRB_FIBER_TERMINATED;
1569 mrb->c = mrb->c->prev;
1570 mrb->c->status = MRB_FIBER_RUNNING;
1571 }
1572 ci = mrb->c->ci;
1573 break;
1574 case OP_R_BREAK:
1575 if (!proc->env || !MRB_ENV_STACK_SHARED_P(proc->env)) {
1576 localjump_error(mrb, LOCALJUMP_ERROR_BREAK);
1577 goto L_RAISE;
1578 }
1579 /* break from fiber block */
1580 if (mrb->c->ci == mrb->c->cibase && mrb->c->ci->pc) {
1581 struct mrb_context *c = mrb->c;
1582
1583 mrb->c = c->prev;
1584 c->prev = NULL;
1585 }
1586 ci = mrb->c->ci;
1587 mrb->c->stack = ci->stackent;
1588 mrb->c->ci = mrb->c->cibase + proc->env->cioff + 1;
1589 while (ci > mrb->c->ci) {
1590 if (ci[-1].acc == CI_ACC_SKIP) {
1591 mrb->c->ci = ci;
1592 break;
1593 }
1594 ci--;
1595 }
1596 break;
1597 default:
1598 /* cannot happen */
1599 break;
1600 }
1601 while (eidx > mrb->c->ci[-1].eidx) {
1602 ecall(mrb, --eidx);
1603 }
1604 cipop(mrb);
1605 acc = ci->acc;
1606 pc = ci->pc;
1607 regs = mrb->c->stack = ci->stackent;
1608 if (acc == CI_ACC_SKIP) {
1609 mrb->jmp = prev_jmp;
1610 return v;
1611 }
1612 DEBUG(printf("from :%s\n", mrb_sym2name(mrb, ci->mid)));
1613 proc = mrb->c->ci->proc;
1614 irep = proc->body.irep;
1615 pool = irep->pool;
1616 syms = irep->syms;
1617
1618 regs[acc] = v;
1619 }
1620 JUMP;
1621 }
1622
1623 CASE(OP_TAILCALL) {
1624 /* A B C return call(R(A),Syms(B),R(A+1),... ,R(A+C+1)) */
1625 int a = GETARG_A(i);
1626 int n = GETARG_C(i);
1627 struct RProc *m;
1628 struct RClass *c;
1629 mrb_callinfo *ci;
1630 mrb_value recv;
1631 mrb_sym mid = syms[GETARG_B(i)];
1632
1633 recv = regs[a];
1634 c = mrb_class(mrb, recv);
1635 m = mrb_method_search_vm(mrb, &c, mid);
1636 if (!m) {
1637 mrb_value sym = mrb_symbol_value(mid);
1638
1639 mid = mrb_intern_lit(mrb, "method_missing");
1640 m = mrb_method_search_vm(mrb, &c, mid);
1641 if (n == CALL_MAXARGS) {
1642 mrb_ary_unshift(mrb, regs[a+1], sym);
1643 }
1644 else {
1645 value_move(regs+a+2, regs+a+1, ++n);
1646 regs[a+1] = sym;
1647 }
1648 }
1649
1650 /* replace callinfo */
1651 ci = mrb->c->ci;
1652 ci->mid = mid;
1653 ci->target_class = c;
1654 if (n == CALL_MAXARGS) {
1655 ci->argc = -1;
1656 }
1657 else {
1658 ci->argc = n;
1659 }
1660
1661 /* move stack */
1662 value_move(mrb->c->stack, &regs[a], ci->argc+1);
1663
1664 if (MRB_PROC_CFUNC_P(m)) {
1665 mrb->c->stack[0] = m->body.func(mrb, recv);
1666 mrb_gc_arena_restore(mrb, ai);
1667 goto L_RETURN;
1668 }
1669 else {
1670 /* setup environment for calling method */
1671 irep = m->body.irep;
1672 pool = irep->pool;
1673 syms = irep->syms;
1674 if (ci->argc < 0) {
1675 stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
1676 }
1677 else {
1678 stack_extend(mrb, irep->nregs, ci->argc+2);
1679 }
1680 regs = mrb->c->stack;
1681 pc = irep->iseq;
1682 }
1683 JUMP;
1684 }
1685
1686 CASE(OP_BLKPUSH) {
1687 /* A Bx R(A) := block (16=6:1:5:4) */
1688 int a = GETARG_A(i);
1689 int bx = GETARG_Bx(i);
1690 int m1 = (bx>>10)&0x3f;
1691 int r = (bx>>9)&0x1;
1692 int m2 = (bx>>4)&0x1f;
1693 int lv = (bx>>0)&0xf;
1694 mrb_value *stack;
1695
1696 if (lv == 0) stack = regs + 1;
1697 else {
1698 struct REnv *e = uvenv(mrb, lv-1);
1699 if (!e) {
1700 localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
1701 goto L_RAISE;
1702 }
1703 stack = e->stack + 1;
1704 }
1705 regs[a] = stack[m1+r+m2];
1706 NEXT;
1707 }
1708
1709#define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff))
1710#define OP_MATH_BODY(op,v1,v2) do {\
1711 v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\
1712} while(0)
1713
1714 CASE(OP_ADD) {
1715 /* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)*/
1716 int a = GETARG_A(i);
1717
1718 /* need to check if op is overridden */
1719 switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
1720 case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
1721 {
1722 mrb_int x, y, z;
1723 mrb_value *regs_a = regs + a;
1724
1725 x = mrb_fixnum(regs_a[0]);
1726 y = mrb_fixnum(regs_a[1]);
1727 if (mrb_int_add_overflow(x, y, &z)) {
1728 SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y);
1729 break;
1730 }
1731 SET_INT_VALUE(regs[a], z);
1732 }
1733 break;
1734 case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
1735 {
1736 mrb_int x = mrb_fixnum(regs[a]);
1737 mrb_float y = mrb_float(regs[a+1]);
1738 SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + y);
1739 }
1740 break;
1741 case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
1742#ifdef MRB_WORD_BOXING
1743 {
1744 mrb_float x = mrb_float(regs[a]);
1745 mrb_int y = mrb_fixnum(regs[a+1]);
1746 SET_FLOAT_VALUE(mrb, regs[a], x + y);
1747 }
1748#else
1749 OP_MATH_BODY(+,mrb_float,mrb_fixnum);
1750#endif
1751 break;
1752 case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
1753#ifdef MRB_WORD_BOXING
1754 {
1755 mrb_float x = mrb_float(regs[a]);
1756 mrb_float y = mrb_float(regs[a+1]);
1757 SET_FLOAT_VALUE(mrb, regs[a], x + y);
1758 }
1759#else
1760 OP_MATH_BODY(+,mrb_float,mrb_float);
1761#endif
1762 break;
1763 case TYPES2(MRB_TT_STRING,MRB_TT_STRING):
1764 regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]);
1765 break;
1766 default:
1767 goto L_SEND;
1768 }
1769 ARENA_RESTORE(mrb, ai);
1770 NEXT;
1771 }
1772
1773 CASE(OP_SUB) {
1774 /* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)*/
1775 int a = GETARG_A(i);
1776
1777 /* need to check if op is overridden */
1778 switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
1779 case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
1780 {
1781 mrb_int x, y, z;
1782
1783 x = mrb_fixnum(regs[a]);
1784 y = mrb_fixnum(regs[a+1]);
1785 if (mrb_int_sub_overflow(x, y, &z)) {
1786 SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y);
1787 break;
1788 }
1789 SET_INT_VALUE(regs[a], z);
1790 }
1791 break;
1792 case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
1793 {
1794 mrb_int x = mrb_fixnum(regs[a]);
1795 mrb_float y = mrb_float(regs[a+1]);
1796 SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - y);
1797 }
1798 break;
1799 case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
1800#ifdef MRB_WORD_BOXING
1801 {
1802 mrb_float x = mrb_float(regs[a]);
1803 mrb_int y = mrb_fixnum(regs[a+1]);
1804 SET_FLOAT_VALUE(mrb, regs[a], x - y);
1805 }
1806#else
1807 OP_MATH_BODY(-,mrb_float,mrb_fixnum);
1808#endif
1809 break;
1810 case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
1811#ifdef MRB_WORD_BOXING
1812 {
1813 mrb_float x = mrb_float(regs[a]);
1814 mrb_float y = mrb_float(regs[a+1]);
1815 SET_FLOAT_VALUE(mrb, regs[a], x - y);
1816 }
1817#else
1818 OP_MATH_BODY(-,mrb_float,mrb_float);
1819#endif
1820 break;
1821 default:
1822 goto L_SEND;
1823 }
1824 NEXT;
1825 }
1826
1827 CASE(OP_MUL) {
1828 /* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1)*/
1829 int a = GETARG_A(i);
1830
1831 /* need to check if op is overridden */
1832 switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
1833 case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
1834 {
1835 mrb_value z;
1836
1837 z = mrb_fixnum_mul(mrb, regs[a], regs[a+1]);
1838
1839 switch (mrb_type(z)) {
1840 case MRB_TT_FIXNUM:
1841 {
1842 SET_INT_VALUE(regs[a], mrb_fixnum(z));
1843 }
1844 break;
1845 case MRB_TT_FLOAT:
1846 {
1847 SET_FLOAT_VALUE(mrb, regs[a], mrb_float(z));
1848 }
1849 break;
1850 default:
1851 /* cannot happen */
1852 break;
1853 }
1854 }
1855 break;
1856 case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
1857 {
1858 mrb_int x = mrb_fixnum(regs[a]);
1859 mrb_float y = mrb_float(regs[a+1]);
1860 SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * y);
1861 }
1862 break;
1863 case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
1864#ifdef MRB_WORD_BOXING
1865 {
1866 mrb_float x = mrb_float(regs[a]);
1867 mrb_int y = mrb_fixnum(regs[a+1]);
1868 SET_FLOAT_VALUE(mrb, regs[a], x * y);
1869 }
1870#else
1871 OP_MATH_BODY(*,mrb_float,mrb_fixnum);
1872#endif
1873 break;
1874 case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
1875#ifdef MRB_WORD_BOXING
1876 {
1877 mrb_float x = mrb_float(regs[a]);
1878 mrb_float y = mrb_float(regs[a+1]);
1879 SET_FLOAT_VALUE(mrb, regs[a], x * y);
1880 }
1881#else
1882 OP_MATH_BODY(*,mrb_float,mrb_float);
1883#endif
1884 break;
1885 default:
1886 goto L_SEND;
1887 }
1888 NEXT;
1889 }
1890
1891 CASE(OP_DIV) {
1892 /* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/
1893 int a = GETARG_A(i);
1894
1895 /* need to check if op is overridden */
1896 switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
1897 case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
1898 {
1899 mrb_int x = mrb_fixnum(regs[a]);
1900 mrb_int y = mrb_fixnum(regs[a+1]);
1901 SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / (mrb_float)y);
1902 }
1903 break;
1904 case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
1905 {
1906 mrb_int x = mrb_fixnum(regs[a]);
1907 mrb_float y = mrb_float(regs[a+1]);
1908 SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / y);
1909 }
1910 break;
1911 case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
1912#ifdef MRB_WORD_BOXING
1913 {
1914 mrb_float x = mrb_float(regs[a]);
1915 mrb_int y = mrb_fixnum(regs[a+1]);
1916 SET_FLOAT_VALUE(mrb, regs[a], x / y);
1917 }
1918#else
1919 OP_MATH_BODY(/,mrb_float,mrb_fixnum);
1920#endif
1921 break;
1922 case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
1923#ifdef MRB_WORD_BOXING
1924 {
1925 mrb_float x = mrb_float(regs[a]);
1926 mrb_float y = mrb_float(regs[a+1]);
1927 SET_FLOAT_VALUE(mrb, regs[a], x / y);
1928 }
1929#else
1930 OP_MATH_BODY(/,mrb_float,mrb_float);
1931#endif
1932 break;
1933 default:
1934 goto L_SEND;
1935 }
1936#ifdef MRB_NAN_BOXING
1937 if (isnan(mrb_float(regs[a]))) {
1938 regs[a] = mrb_float_value(mrb, mrb_float(regs[a]));
1939 }
1940#endif
1941 NEXT;
1942 }
1943
1944 CASE(OP_ADDI) {
1945 /* A B C R(A) := R(A)+C (Syms[B]=:+)*/
1946 int a = GETARG_A(i);
1947
1948 /* need to check if + is overridden */
1949 switch (mrb_type(regs[a])) {
1950 case MRB_TT_FIXNUM:
1951 {
1952 mrb_int x = mrb_fixnum(regs[a]);
1953 mrb_int y = GETARG_C(i);
1954 mrb_int z;
1955
1956 if (mrb_int_add_overflow(x, y, &z)) {
1957 SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y);
1958 break;
1959 }
1960 SET_INT_VALUE(regs[a], z);
1961 }
1962 break;
1963 case MRB_TT_FLOAT:
1964#ifdef MRB_WORD_BOXING
1965 {
1966 mrb_float x = mrb_float(regs[a]);
1967 SET_FLOAT_VALUE(mrb, regs[a], x + GETARG_C(i));
1968 }
1969#else
1970 mrb_float(regs[a]) += GETARG_C(i);
1971#endif
1972 break;
1973 default:
1974 SET_INT_VALUE(regs[a+1], GETARG_C(i));
1975 i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1);
1976 goto L_SEND;
1977 }
1978 NEXT;
1979 }
1980
1981 CASE(OP_SUBI) {
1982 /* A B C R(A) := R(A)-C (Syms[B]=:-)*/
1983 int a = GETARG_A(i);
1984 mrb_value *regs_a = regs + a;
1985
1986 /* need to check if + is overridden */
1987 switch (mrb_type(regs_a[0])) {
1988 case MRB_TT_FIXNUM:
1989 {
1990 mrb_int x = mrb_fixnum(regs_a[0]);
1991 mrb_int y = GETARG_C(i);
1992 mrb_int z;
1993
1994 if (mrb_int_sub_overflow(x, y, &z)) {
1995 SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y);
1996 }
1997 else {
1998 SET_INT_VALUE(regs_a[0], z);
1999 }
2000 }
2001 break;
2002 case MRB_TT_FLOAT:
2003#ifdef MRB_WORD_BOXING
2004 {
2005 mrb_float x = mrb_float(regs[a]);
2006 SET_FLOAT_VALUE(mrb, regs[a], x - GETARG_C(i));
2007 }
2008#else
2009 mrb_float(regs_a[0]) -= GETARG_C(i);
2010#endif
2011 break;
2012 default:
2013 SET_INT_VALUE(regs_a[1], GETARG_C(i));
2014 i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1);
2015 goto L_SEND;
2016 }
2017 NEXT;
2018 }
2019
2020#define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1]))
2021
2022#define OP_CMP(op) do {\
2023 int result;\
2024 /* need to check if - is overridden */\
2025 switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
2026 case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\
2027 result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\
2028 break;\
2029 case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\
2030 result = OP_CMP_BODY(op,mrb_fixnum,mrb_float);\
2031 break;\
2032 case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\
2033 result = OP_CMP_BODY(op,mrb_float,mrb_fixnum);\
2034 break;\
2035 case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\
2036 result = OP_CMP_BODY(op,mrb_float,mrb_float);\
2037 break;\
2038 default:\
2039 goto L_SEND;\
2040 }\
2041 if (result) {\
2042 SET_TRUE_VALUE(regs[a]);\
2043 }\
2044 else {\
2045 SET_FALSE_VALUE(regs[a]);\
2046 }\
2047} while(0)
2048
2049 CASE(OP_EQ) {
2050 /* A B C R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1)*/
2051 int a = GETARG_A(i);
2052 if (mrb_obj_eq(mrb, regs[a], regs[a+1])) {
2053 SET_TRUE_VALUE(regs[a]);
2054 }
2055 else {
2056 OP_CMP(==);
2057 }
2058 NEXT;
2059 }
2060
2061 CASE(OP_LT) {
2062 /* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1)*/
2063 int a = GETARG_A(i);
2064 OP_CMP(<);
2065 NEXT;
2066 }
2067
2068 CASE(OP_LE) {
2069 /* A B C R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1)*/
2070 int a = GETARG_A(i);
2071 OP_CMP(<=);
2072 NEXT;
2073 }
2074
2075 CASE(OP_GT) {
2076 /* A B C R(A) := R(A)>R(A+1) (Syms[B]=:>,C=1)*/
2077 int a = GETARG_A(i);
2078 OP_CMP(>);
2079 NEXT;
2080 }
2081
2082 CASE(OP_GE) {
2083 /* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1)*/
2084 int a = GETARG_A(i);
2085 OP_CMP(>=);
2086 NEXT;
2087 }
2088
2089 CASE(OP_ARRAY) {
2090 /* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */
2091 regs[GETARG_A(i)] = mrb_ary_new_from_values(mrb, GETARG_C(i), &regs[GETARG_B(i)]);
2092 ARENA_RESTORE(mrb, ai);
2093 NEXT;
2094 }
2095
2096 CASE(OP_ARYCAT) {
2097 /* A B mrb_ary_concat(R(A),R(B)) */
2098 mrb_ary_concat(mrb, regs[GETARG_A(i)],
2099 mrb_ary_splat(mrb, regs[GETARG_B(i)]));
2100 ARENA_RESTORE(mrb, ai);
2101 NEXT;
2102 }
2103
2104 CASE(OP_ARYPUSH) {
2105 /* A B R(A).push(R(B)) */
2106 mrb_ary_push(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]);
2107 NEXT;
2108 }
2109
2110 CASE(OP_AREF) {
2111 /* A B C R(A) := R(B)[C] */
2112 int a = GETARG_A(i);
2113 int c = GETARG_C(i);
2114 mrb_value v = regs[GETARG_B(i)];
2115
2116 if (!mrb_array_p(v)) {
2117 if (c == 0) {
2118 regs[GETARG_A(i)] = v;
2119 }
2120 else {
2121 SET_NIL_VALUE(regs[a]);
2122 }
2123 }
2124 else {
2125 regs[GETARG_A(i)] = mrb_ary_ref(mrb, v, c);
2126 }
2127 NEXT;
2128 }
2129
2130 CASE(OP_ASET) {
2131 /* A B C R(B)[C] := R(A) */
2132 mrb_ary_set(mrb, regs[GETARG_B(i)], GETARG_C(i), regs[GETARG_A(i)]);
2133 NEXT;
2134 }
2135
2136 CASE(OP_APOST) {
2137 /* A B C *R(A),R(A+1)..R(A+C) := R(A) */
2138 int a = GETARG_A(i);
2139 mrb_value v = regs[a];
2140 int pre = GETARG_B(i);
2141 int post = GETARG_C(i);
2142
2143 struct RArray *ary;
2144 int len, idx;
2145
2146 if (!mrb_array_p(v)) {
2147 v = mrb_ary_new_from_values(mrb, 1, &regs[a]);
2148 }
2149 ary = mrb_ary_ptr(v);
2150 len = ary->len;
2151 if (len > pre + post) {
2152 regs[a++] = mrb_ary_new_from_values(mrb, len - pre - post, ary->ptr+pre);
2153 while (post--) {
2154 regs[a++] = ary->ptr[len-post-1];
2155 }
2156 }
2157 else {
2158 regs[a++] = mrb_ary_new_capa(mrb, 0);
2159 for (idx=0; idx+pre<len; idx++) {
2160 regs[a+idx] = ary->ptr[pre+idx];
2161 }
2162 while (idx < post) {
2163 SET_NIL_VALUE(regs[a+idx]);
2164 idx++;
2165 }
2166 }
2167 ARENA_RESTORE(mrb, ai);
2168 NEXT;
2169 }
2170
2171 CASE(OP_STRING) {
2172 /* A Bx R(A) := str_new(Lit(Bx)) */
2173 regs[GETARG_A(i)] = mrb_str_dup(mrb, pool[GETARG_Bx(i)]);
2174 ARENA_RESTORE(mrb, ai);
2175 NEXT;
2176 }
2177
2178 CASE(OP_STRCAT) {
2179 /* A B R(A).concat(R(B)) */
2180 mrb_str_concat(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]);
2181 regs = mrb->c->stack;
2182 NEXT;
2183 }
2184
2185 CASE(OP_HASH) {
2186 /* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */
2187 int b = GETARG_B(i);
2188 int c = GETARG_C(i);
2189 int lim = b+c*2;
2190 mrb_value hash = mrb_hash_new_capa(mrb, c);
2191
2192 while (b < lim) {
2193 mrb_hash_set(mrb, hash, regs[b], regs[b+1]);
2194 b+=2;
2195 }
2196 regs[GETARG_A(i)] = hash;
2197 ARENA_RESTORE(mrb, ai);
2198 NEXT;
2199 }
2200
2201 CASE(OP_LAMBDA) {
2202 /* A b c R(A) := lambda(SEQ[b],c) (b:c = 14:2) */
2203 struct RProc *p;
2204 int c = GETARG_c(i);
2205
2206 if (c & OP_L_CAPTURE) {
2207 p = mrb_closure_new(mrb, irep->reps[GETARG_b(i)]);
2208 }
2209 else {
2210 p = mrb_proc_new(mrb, irep->reps[GETARG_b(i)]);
2211 }
2212 if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT;
2213 regs[GETARG_A(i)] = mrb_obj_value(p);
2214 ARENA_RESTORE(mrb, ai);
2215 NEXT;
2216 }
2217
2218 CASE(OP_OCLASS) {
2219 /* A R(A) := ::Object */
2220 regs[GETARG_A(i)] = mrb_obj_value(mrb->object_class);
2221 NEXT;
2222 }
2223
2224 CASE(OP_CLASS) {
2225 /* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */
2226 struct RClass *c = 0;
2227 int a = GETARG_A(i);
2228 mrb_value base, super;
2229 mrb_sym id = syms[GETARG_B(i)];
2230
2231 base = regs[a];
2232 super = regs[a+1];
2233 if (mrb_nil_p(base)) {
2234 base = mrb_obj_value(mrb->c->ci->target_class);
2235 }
2236 c = mrb_vm_define_class(mrb, base, super, id);
2237 regs[a] = mrb_obj_value(c);
2238 ARENA_RESTORE(mrb, ai);
2239 NEXT;
2240 }
2241
2242 CASE(OP_MODULE) {
2243 /* A B R(A) := newmodule(R(A),Syms(B)) */
2244 struct RClass *c = 0;
2245 int a = GETARG_A(i);
2246 mrb_value base;
2247 mrb_sym id = syms[GETARG_B(i)];
2248
2249 base = regs[a];
2250 if (mrb_nil_p(base)) {
2251 base = mrb_obj_value(mrb->c->ci->target_class);
2252 }
2253 c = mrb_vm_define_module(mrb, base, id);
2254 regs[a] = mrb_obj_value(c);
2255 ARENA_RESTORE(mrb, ai);
2256 NEXT;
2257 }
2258
2259 CASE(OP_EXEC) {
2260 /* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */
2261 int a = GETARG_A(i);
2262 mrb_callinfo *ci;
2263 mrb_value recv = regs[a];
2264 struct RProc *p;
2265
2266 /* prepare stack */
2267 ci = cipush(mrb);
2268 ci->pc = pc + 1;
2269 ci->acc = a;
2270 ci->mid = 0;
2271 ci->stackent = mrb->c->stack;
2272 ci->argc = 0;
2273 ci->target_class = mrb_class_ptr(recv);
2274
2275 /* prepare stack */
2276 mrb->c->stack += a;
2277
2278 p = mrb_proc_new(mrb, irep->reps[GETARG_Bx(i)]);
2279 p->target_class = ci->target_class;
2280 ci->proc = p;
2281
2282 if (MRB_PROC_CFUNC_P(p)) {
2283 ci->nregs = 0;
2284 mrb->c->stack[0] = p->body.func(mrb, recv);
2285 mrb_gc_arena_restore(mrb, ai);
2286 if (mrb->exc) goto L_RAISE;
2287 /* pop stackpos */
2288 regs = mrb->c->stack = mrb->c->ci->stackent;
2289 cipop(mrb);
2290 NEXT;
2291 }
2292 else {
2293 irep = p->body.irep;
2294 pool = irep->pool;
2295 syms = irep->syms;
2296 stack_extend(mrb, irep->nregs, 1);
2297 ci->nregs = irep->nregs;
2298 regs = mrb->c->stack;
2299 pc = irep->iseq;
2300 JUMP;
2301 }
2302 }
2303
2304 CASE(OP_METHOD) {
2305 /* A B R(A).newmethod(Syms(B),R(A+1)) */
2306 int a = GETARG_A(i);
2307 struct RClass *c = mrb_class_ptr(regs[a]);
2308 struct RProc *p = mrb_proc_ptr(regs[a+1]);
2309
2310 mrb_define_method_raw(mrb, c, syms[GETARG_B(i)], p);
2311 ARENA_RESTORE(mrb, ai);
2312 NEXT;
2313 }
2314
2315 CASE(OP_SCLASS) {
2316 /* A B R(A) := R(B).singleton_class */
2317 regs[GETARG_A(i)] = mrb_singleton_class(mrb, regs[GETARG_B(i)]);
2318 ARENA_RESTORE(mrb, ai);
2319 NEXT;
2320 }
2321
2322 CASE(OP_TCLASS) {
2323 /* A R(A) := target_class */
2324 if (!mrb->c->ci->target_class) {
2325 mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module");
2326 mrb->exc = mrb_obj_ptr(exc);
2327 goto L_RAISE;
2328 }
2329 regs[GETARG_A(i)] = mrb_obj_value(mrb->c->ci->target_class);
2330 NEXT;
2331 }
2332
2333 CASE(OP_RANGE) {
2334 /* A B C R(A) := range_new(R(B),R(B+1),C) */
2335 int b = GETARG_B(i);
2336 regs[GETARG_A(i)] = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i));
2337 ARENA_RESTORE(mrb, ai);
2338 NEXT;
2339 }
2340
2341 CASE(OP_DEBUG) {
2342 /* A B C debug print R(A),R(B),R(C) */
2343#ifdef MRB_ENABLE_DEBUG_HOOK
2344 mrb->debug_op_hook(mrb, irep, pc, regs);
2345#else
2346#ifndef MRB_DISABLE_STDIO
2347 printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i));
2348#else
2349 abort();
2350#endif
2351#endif
2352 NEXT;
2353 }
2354
2355 CASE(OP_STOP) {
2356 /* stop VM */
2357 L_STOP:
2358 {
2359 int eidx_stop = mrb->c->ci == mrb->c->cibase ? 0 : mrb->c->ci[-1].eidx;
2360 int eidx = mrb->c->ci->eidx;
2361 while (eidx > eidx_stop) {
2362 ecall(mrb, --eidx);
2363 }
2364 }
2365 ERR_PC_CLR(mrb);
2366 mrb->jmp = prev_jmp;
2367 if (mrb->exc) {
2368 return mrb_obj_value(mrb->exc);
2369 }
2370 return regs[irep->nlocals];
2371 }
2372
2373 CASE(OP_ERR) {
2374 /* Bx raise RuntimeError with message Lit(Bx) */
2375 mrb_value msg = mrb_str_dup(mrb, pool[GETARG_Bx(i)]);
2376 mrb_value exc;
2377
2378 if (GETARG_A(i) == 0) {
2379 exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, msg);
2380 }
2381 else {
2382 exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg);
2383 }
2384 mrb->exc = mrb_obj_ptr(exc);
2385 goto L_RAISE;
2386 }
2387 }
2388 END_DISPATCH;
2389
2390 }
2391 MRB_CATCH(&c_jmp) {
2392 exc_catched = TRUE;
2393 goto RETRY_TRY_BLOCK;
2394 }
2395 MRB_END_EXC(&c_jmp);
2396}
2397
2398MRB_API mrb_value
2399mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
2400{
2401 return mrb_context_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */
2402}
2403
2404MRB_API mrb_value
2405mrb_toplevel_run_keep(mrb_state *mrb, struct RProc *proc, unsigned int stack_keep)
2406{
2407 mrb_callinfo *ci;
2408 mrb_value v;
2409
2410 if (!mrb->c->cibase || mrb->c->ci == mrb->c->cibase) {
2411 return mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep);
2412 }
2413 ci = cipush(mrb);
2414 ci->nregs = 1; /* protect the receiver */
2415 ci->acc = CI_ACC_SKIP;
2416 ci->target_class = mrb->object_class;
2417 v = mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep);
2418 cipop(mrb);
2419
2420 return v;
2421}
2422
2423MRB_API mrb_value
2424mrb_toplevel_run(mrb_state *mrb, struct RProc *proc)
2425{
2426 return mrb_toplevel_run_keep(mrb, proc, 0);
2427}
Note: See TracBrowser for help on using the repository browser.