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