00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status);
00015 static inline VALUE rb_vm_set_finish_env(rb_thread_t * th);
00016 static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref);
00017 static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
00018 static inline VALUE vm_backtrace(rb_thread_t *th, int lev);
00019 static int vm_backtrace_each(rb_thread_t *th, int lev, void (*init)(void *), rb_backtrace_iter_func *iter, void *arg);
00020 static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr);
00021 static VALUE vm_exec(rb_thread_t *th);
00022 static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref);
00023 static int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary);
00024
00025 typedef enum call_type {
00026 CALL_PUBLIC,
00027 CALL_FCALL,
00028 CALL_VCALL,
00029 CALL_TYPE_MAX
00030 } call_type;
00031
00032 static VALUE send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope);
00033
00034 static inline VALUE
00035 vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv,
00036 const rb_method_entry_t *me)
00037 {
00038 const rb_method_definition_t *def = me->def;
00039 VALUE val;
00040 VALUE klass = me->klass;
00041 const rb_block_t *blockptr = 0;
00042
00043 if (!def) return Qnil;
00044 if (th->passed_block) {
00045 blockptr = th->passed_block;
00046 th->passed_block = 0;
00047 }
00048
00049 again:
00050 switch (def->type) {
00051 case VM_METHOD_TYPE_ISEQ: {
00052 rb_control_frame_t *reg_cfp;
00053 int i;
00054
00055 rb_vm_set_finish_env(th);
00056 reg_cfp = th->cfp;
00057
00058 CHECK_STACK_OVERFLOW(reg_cfp, argc + 1);
00059
00060 *reg_cfp->sp++ = recv;
00061 for (i = 0; i < argc; i++) {
00062 *reg_cfp->sp++ = argv[i];
00063 }
00064
00065 vm_setup_method(th, reg_cfp, recv, argc, blockptr, 0 , me);
00066 val = vm_exec(th);
00067 break;
00068 }
00069 case VM_METHOD_TYPE_NOTIMPLEMENTED:
00070 case VM_METHOD_TYPE_CFUNC: {
00071 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
00072 {
00073 rb_control_frame_t *reg_cfp = th->cfp;
00074 rb_control_frame_t *cfp =
00075 vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
00076 recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
00077
00078 cfp->me = me;
00079 val = call_cfunc(def->body.cfunc.func, recv, def->body.cfunc.argc, argc, argv);
00080
00081 if (reg_cfp != th->cfp + 1) {
00082 rb_bug("cfp consistency error - call0");
00083 }
00084 vm_pop_frame(th);
00085 }
00086 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, id, klass);
00087 break;
00088 }
00089 case VM_METHOD_TYPE_ATTRSET: {
00090 if (argc != 1) {
00091 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
00092 }
00093 val = rb_ivar_set(recv, def->body.attr.id, argv[0]);
00094 break;
00095 }
00096 case VM_METHOD_TYPE_IVAR: {
00097 if (argc != 0) {
00098 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
00099 }
00100 val = rb_attr_get(recv, def->body.attr.id);
00101 break;
00102 }
00103 case VM_METHOD_TYPE_BMETHOD: {
00104 val = vm_call_bmethod(th, recv, argc, argv, blockptr, me);
00105 break;
00106 }
00107 case VM_METHOD_TYPE_ZSUPER: {
00108 klass = RCLASS_SUPER(klass);
00109 if (!klass || !(me = rb_method_entry(klass, id))) {
00110 return method_missing(recv, id, argc, argv, NOEX_SUPER);
00111 }
00112 RUBY_VM_CHECK_INTS();
00113 if (!(def = me->def)) return Qnil;
00114 goto again;
00115 }
00116 case VM_METHOD_TYPE_MISSING: {
00117 VALUE new_args = rb_ary_new4(argc, argv);
00118
00119 RB_GC_GUARD(new_args);
00120 rb_ary_unshift(new_args, ID2SYM(id));
00121 th->passed_block = blockptr;
00122 return rb_funcall2(recv, idMethodMissing,
00123 argc+1, RARRAY_PTR(new_args));
00124 }
00125 case VM_METHOD_TYPE_OPTIMIZED: {
00126 switch (def->body.optimize_type) {
00127 case OPTIMIZED_METHOD_TYPE_SEND:
00128 val = send_internal(argc, argv, recv, CALL_FCALL);
00129 break;
00130 case OPTIMIZED_METHOD_TYPE_CALL: {
00131 rb_proc_t *proc;
00132 GetProcPtr(recv, proc);
00133 val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr);
00134 break;
00135 }
00136 default:
00137 rb_bug("vm_call0: unsupported optimized method type (%d)", def->body.optimize_type);
00138 val = Qundef;
00139 break;
00140 }
00141 break;
00142 }
00143 default:
00144 rb_bug("vm_call0: unsupported method type (%d)", def->type);
00145 val = Qundef;
00146 }
00147 RUBY_VM_CHECK_INTS();
00148 return val;
00149 }
00150
00151 VALUE
00152 rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv,
00153 const rb_method_entry_t *me)
00154 {
00155 return vm_call0(th, recv, id, argc, argv, me);
00156 }
00157
00158 static inline VALUE
00159 vm_call_super(rb_thread_t *th, int argc, const VALUE *argv)
00160 {
00161 VALUE recv = th->cfp->self;
00162 VALUE klass;
00163 ID id;
00164 rb_method_entry_t *me;
00165 rb_control_frame_t *cfp = th->cfp;
00166
00167 if (!cfp->iseq) {
00168 klass = cfp->me->klass;
00169 klass = RCLASS_SUPER(klass);
00170
00171 if (klass == 0) {
00172 klass = vm_search_normal_superclass(cfp->me->klass, recv);
00173 }
00174 id = cfp->me->def->original_id;
00175 }
00176 else {
00177 rb_bug("vm_call_super: should not be reached");
00178 }
00179
00180 me = rb_method_entry(klass, id);
00181 if (!me) {
00182 return method_missing(recv, id, argc, argv, NOEX_SUPER);
00183 }
00184
00185 return vm_call0(th, recv, id, argc, argv, me);
00186 }
00187
00188 VALUE
00189 rb_call_super(int argc, const VALUE *argv)
00190 {
00191 PASS_PASSED_BLOCK();
00192 return vm_call_super(GET_THREAD(), argc, argv);
00193 }
00194
00195 static inline void
00196 stack_check(void)
00197 {
00198 rb_thread_t *th = GET_THREAD();
00199
00200 if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) && ruby_stack_check()) {
00201 rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
00202 rb_exc_raise(sysstack_error);
00203 }
00204 }
00205
00206 static inline rb_method_entry_t *rb_search_method_entry(VALUE recv, ID mid);
00207 static inline int rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self);
00208 #define NOEX_OK NOEX_NOSUPER
00209
00224 static inline VALUE
00225 rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
00226 call_type scope, VALUE self)
00227 {
00228 rb_method_entry_t *me = rb_search_method_entry(recv, mid);
00229 rb_thread_t *th = GET_THREAD();
00230 int call_status = rb_method_call_status(th, me, scope, self);
00231
00232 if (call_status != NOEX_OK) {
00233 return method_missing(recv, mid, argc, argv, call_status);
00234 }
00235 stack_check();
00236 return vm_call0(th, recv, mid, argc, argv, me);
00237 }
00238
00239 struct rescue_funcall_args {
00240 VALUE recv;
00241 VALUE sym;
00242 int argc;
00243 VALUE *argv;
00244 };
00245
00246 static VALUE
00247 check_funcall_exec(struct rescue_funcall_args *args)
00248 {
00249 VALUE new_args = rb_ary_new4(args->argc, args->argv);
00250
00251 RB_GC_GUARD(new_args);
00252 rb_ary_unshift(new_args, args->sym);
00253 return rb_funcall2(args->recv, idMethodMissing,
00254 args->argc+1, RARRAY_PTR(new_args));
00255 }
00256
00257 static VALUE
00258 check_funcall_failed(struct rescue_funcall_args *args, VALUE e)
00259 {
00260 if (rb_respond_to(args->recv, SYM2ID(args->sym))) {
00261 rb_exc_raise(e);
00262 }
00263 return Qundef;
00264 }
00265
00266 static VALUE
00267 check_funcall(VALUE recv, ID mid, int argc, VALUE *argv)
00268 {
00269 VALUE klass = CLASS_OF(recv);
00270 const rb_method_entry_t *me;
00271 rb_thread_t *th = GET_THREAD();
00272 int call_status;
00273
00274 me = rb_method_entry(klass, idRespond_to);
00275 if (me && !(me->flag & NOEX_BASIC)) {
00276 VALUE args[2];
00277 int arity = rb_method_entry_arity(me);
00278
00279 if (arity < 1 || arity > 3) arity = 2;
00280
00281 args[0] = ID2SYM(mid);
00282 args[1] = Qtrue;
00283 if (!RTEST(vm_call0(th, recv, idRespond_to, arity, args, me))) {
00284 return Qundef;
00285 }
00286 }
00287
00288 me = rb_search_method_entry(recv, mid);
00289 call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef);
00290 if (call_status != NOEX_OK) {
00291 if (rb_method_basic_definition_p(klass, idMethodMissing)) {
00292 return Qundef;
00293 }
00294 else {
00295 struct rescue_funcall_args args;
00296
00297 th->method_missing_reason = 0;
00298 args.recv = recv;
00299 args.sym = ID2SYM(mid);
00300 args.argc = argc;
00301 args.argv = argv;
00302 return rb_rescue2(check_funcall_exec, (VALUE)&args,
00303 check_funcall_failed, (VALUE)&args,
00304 rb_eNoMethodError, (VALUE)0);
00305 }
00306 }
00307 stack_check();
00308 return vm_call0(th, recv, mid, argc, argv, me);
00309 }
00310
00311 VALUE
00312 rb_check_funcall(VALUE recv, ID mid, int argc, VALUE *argv)
00313 {
00314 return check_funcall(recv, mid, argc, argv);
00315 }
00316
00317 static const char *
00318 rb_type_str(enum ruby_value_type type)
00319 {
00320 #define type_case(t) case t: return #t;
00321 switch (type) {
00322 type_case(T_NONE)
00323 type_case(T_OBJECT)
00324 type_case(T_CLASS)
00325 type_case(T_MODULE)
00326 type_case(T_FLOAT)
00327 type_case(T_STRING)
00328 type_case(T_REGEXP)
00329 type_case(T_ARRAY)
00330 type_case(T_HASH)
00331 type_case(T_STRUCT)
00332 type_case(T_BIGNUM)
00333 type_case(T_FILE)
00334 type_case(T_DATA)
00335 type_case(T_MATCH)
00336 type_case(T_COMPLEX)
00337 type_case(T_RATIONAL)
00338 type_case(T_NIL)
00339 type_case(T_TRUE)
00340 type_case(T_FALSE)
00341 type_case(T_SYMBOL)
00342 type_case(T_FIXNUM)
00343 type_case(T_UNDEF)
00344 type_case(T_NODE)
00345 type_case(T_ICLASS)
00346 type_case(T_ZOMBIE)
00347 default: return NULL;
00348 }
00349 #undef type_case
00350 }
00351
00352 static inline rb_method_entry_t *
00353 rb_search_method_entry(VALUE recv, ID mid)
00354 {
00355 VALUE klass = CLASS_OF(recv);
00356
00357 if (!klass) {
00358 VALUE flags, klass;
00359 if (IMMEDIATE_P(recv)) {
00360 rb_raise(rb_eNotImpError,
00361 "method `%s' called on unexpected immediate object (%p)",
00362 rb_id2name(mid), (void *)recv);
00363 }
00364 flags = RBASIC(recv)->flags;
00365 klass = RBASIC(recv)->klass;
00366 if (flags == 0) {
00367 rb_raise(rb_eNotImpError,
00368 "method `%s' called on terminated object"
00369 " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
00370 rb_id2name(mid), (void *)recv, flags, klass);
00371 }
00372 else {
00373 int type = BUILTIN_TYPE(recv);
00374 const char *typestr = rb_type_str(type);
00375 if (typestr && T_OBJECT <= type && type < T_NIL)
00376 rb_raise(rb_eNotImpError,
00377 "method `%s' called on hidden %s object"
00378 " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
00379 rb_id2name(mid), typestr, (void *)recv, flags, klass);
00380 if (typestr)
00381 rb_raise(rb_eNotImpError,
00382 "method `%s' called on unexpected %s object"
00383 " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
00384 rb_id2name(mid), typestr, (void *)recv, flags, klass);
00385 else
00386 rb_raise(rb_eNotImpError,
00387 "method `%s' called on broken T_???" "(0x%02x) object"
00388 " (%p flags=0x%"PRIxVALUE" klass=0x%"PRIxVALUE")",
00389 rb_id2name(mid), type, (void *)recv, flags, klass);
00390 }
00391 }
00392 return rb_method_entry(klass, mid);
00393 }
00394
00395 static inline int
00396 rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self)
00397 {
00398 VALUE klass;
00399 ID oid;
00400 int noex;
00401
00402 if (UNDEFINED_METHOD_ENTRY_P(me)) {
00403 return scope == CALL_VCALL ? NOEX_VCALL : 0;
00404 }
00405 klass = me->klass;
00406 oid = me->def->original_id;
00407 noex = me->flag;
00408
00409 if (oid != idMethodMissing) {
00410
00411 if (UNLIKELY(noex)) {
00412 if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == CALL_PUBLIC) {
00413 return NOEX_PRIVATE;
00414 }
00415
00416
00417 if (((noex & NOEX_MASK) & NOEX_PROTECTED) && scope == CALL_PUBLIC) {
00418 VALUE defined_class = klass;
00419
00420 if (TYPE(defined_class) == T_ICLASS) {
00421 defined_class = RBASIC(defined_class)->klass;
00422 }
00423
00424 if (self == Qundef) {
00425 self = th->cfp->self;
00426 }
00427 if (!rb_obj_is_kind_of(self, defined_class)) {
00428 return NOEX_PROTECTED;
00429 }
00430 }
00431
00432 if (NOEX_SAFE(noex) > th->safe_level) {
00433 rb_raise(rb_eSecurityError, "calling insecure method: %s",
00434 rb_id2name(me->called_id));
00435 }
00436 }
00437 }
00438 return NOEX_OK;
00439 }
00440
00441
00453 static inline VALUE
00454 rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
00455 {
00456 return rb_call0(recv, mid, argc, argv, scope, Qundef);
00457 }
00458
00459 NORETURN(static void raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv,
00460 VALUE obj, int call_status));
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 static VALUE
00496 rb_method_missing(int argc, const VALUE *argv, VALUE obj)
00497 {
00498 rb_thread_t *th = GET_THREAD();
00499 raise_method_missing(th, argc, argv, obj, th->method_missing_reason);
00500 return Qnil;
00501 }
00502
00503 #define NOEX_MISSING 0x80
00504
00505 static void
00506 raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj,
00507 int last_call_status)
00508 {
00509 ID id;
00510 VALUE exc = rb_eNoMethodError;
00511 const char *format = 0;
00512
00513 if (argc == 0 || !SYMBOL_P(argv[0])) {
00514 rb_raise(rb_eArgError, "no id given");
00515 }
00516
00517 stack_check();
00518
00519 id = SYM2ID(argv[0]);
00520
00521 if (last_call_status & NOEX_PRIVATE) {
00522 format = "private method `%s' called for %s";
00523 }
00524 else if (last_call_status & NOEX_PROTECTED) {
00525 format = "protected method `%s' called for %s";
00526 }
00527 else if (last_call_status & NOEX_VCALL) {
00528 format = "undefined local variable or method `%s' for %s";
00529 exc = rb_eNameError;
00530 }
00531 else if (last_call_status & NOEX_SUPER) {
00532 format = "super: no superclass method `%s' for %s";
00533 }
00534 if (!format) {
00535 format = "undefined method `%s' for %s";
00536 }
00537
00538 {
00539 int n = 0;
00540 VALUE mesg;
00541 VALUE args[3];
00542
00543 mesg = rb_const_get(exc, rb_intern("message"));
00544 if (rb_method_basic_definition_p(CLASS_OF(mesg), '!')) {
00545 args[n++] = rb_name_err_mesg_new(mesg, rb_str_new2(format), obj, argv[0]);
00546 }
00547 else {
00548 args[n++] = rb_funcall(mesg, '!', 3, rb_str_new2(format), obj, argv[0]);
00549 }
00550 args[n++] = argv[0];
00551 if (exc == rb_eNoMethodError) {
00552 args[n++] = rb_ary_new4(argc - 1, argv + 1);
00553 }
00554 exc = rb_class_new_instance(n, args, exc);
00555
00556 if (!(last_call_status & NOEX_MISSING)) {
00557 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00558 }
00559 rb_exc_raise(exc);
00560 }
00561 }
00562
00563 static inline VALUE
00564 method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
00565 {
00566 VALUE *nargv, result, argv_ary = 0;
00567 rb_thread_t *th = GET_THREAD();
00568 const rb_block_t *blockptr = th->passed_block;
00569
00570 th->method_missing_reason = call_status;
00571 th->passed_block = 0;
00572
00573 if (id == idMethodMissing) {
00574 raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING);
00575 }
00576 else if (id == ID_ALLOCATOR) {
00577 rb_raise(rb_eTypeError, "allocator undefined for %s",
00578 rb_class2name(obj));
00579 }
00580
00581 if (argc < 0x100) {
00582 nargv = ALLOCA_N(VALUE, argc + 1);
00583 }
00584 else {
00585 argv_ary = rb_ary_tmp_new(argc + 1);
00586 nargv = RARRAY_PTR(argv_ary);
00587 }
00588 nargv[0] = ID2SYM(id);
00589 MEMCPY(nargv + 1, argv, VALUE, argc);
00590
00591 if (rb_method_basic_definition_p(CLASS_OF(obj) , idMethodMissing)) {
00592 raise_method_missing(th, argc+1, nargv, obj, call_status | NOEX_MISSING);
00593 }
00594 th->passed_block = blockptr;
00595 result = rb_funcall2(obj, idMethodMissing, argc + 1, nargv);
00596 if (argv_ary) rb_ary_clear(argv_ary);
00597 return result;
00598 }
00599
00600 void
00601 rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv,
00602 VALUE obj, int call_status)
00603 {
00604 th->passed_block = 0;
00605 raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING);
00606 }
00607
00616 VALUE
00617 rb_apply(VALUE recv, ID mid, VALUE args)
00618 {
00619 int argc;
00620 VALUE *argv;
00621
00622 argc = RARRAY_LENINT(args);
00623 argv = ALLOCA_N(VALUE, argc);
00624 MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
00625 return rb_call(recv, mid, argc, argv, CALL_FCALL);
00626 }
00627
00637 VALUE
00638 rb_funcall(VALUE recv, ID mid, int n, ...)
00639 {
00640 VALUE *argv;
00641 va_list ar;
00642
00643 if (n > 0) {
00644 long i;
00645
00646 va_init_list(ar, n);
00647
00648 argv = ALLOCA_N(VALUE, n);
00649
00650 for (i = 0; i < n; i++) {
00651 argv[i] = va_arg(ar, VALUE);
00652 }
00653 va_end(ar);
00654 }
00655 else {
00656 argv = 0;
00657 }
00658 return rb_call(recv, mid, n, argv, CALL_FCALL);
00659 }
00660
00668 VALUE
00669 rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
00670 {
00671 return rb_call(recv, mid, argc, argv, CALL_FCALL);
00672 }
00673
00683 VALUE
00684 rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
00685 {
00686 return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
00687 }
00688
00689 VALUE
00690 rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv)
00691 {
00692 PASS_PASSED_BLOCK_TH(GET_THREAD());
00693
00694 return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
00695 }
00696
00697 VALUE
00698 rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE pass_procval)
00699 {
00700 if (!NIL_P(pass_procval)) {
00701 rb_thread_t *th = GET_THREAD();
00702 rb_block_t *block = 0;
00703
00704 rb_proc_t *pass_proc;
00705 GetProcPtr(pass_procval, pass_proc);
00706 block = &pass_proc->block;
00707
00708 th->passed_block = block;
00709 }
00710
00711 return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
00712 }
00713
00714 static VALUE
00715 send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
00716 {
00717 VALUE vid;
00718 VALUE self = RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp)->self;
00719 rb_thread_t *th = GET_THREAD();
00720
00721 if (argc == 0) {
00722 rb_raise(rb_eArgError, "no method name given");
00723 }
00724
00725 vid = *argv++; argc--;
00726 PASS_PASSED_BLOCK_TH(th);
00727
00728 return rb_call0(recv, rb_to_id(vid), argc, argv, scope, self);
00729 }
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749 VALUE
00750 rb_f_send(int argc, VALUE *argv, VALUE recv)
00751 {
00752 return send_internal(argc, argv, recv, CALL_FCALL);
00753 }
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 VALUE
00767 rb_f_public_send(int argc, VALUE *argv, VALUE recv)
00768 {
00769 return send_internal(argc, argv, recv, CALL_PUBLIC);
00770 }
00771
00772
00773
00774 static inline VALUE
00775 rb_yield_0(int argc, const VALUE * argv)
00776 {
00777 return vm_yield(GET_THREAD(), argc, argv);
00778 }
00779
00780 VALUE
00781 rb_yield(VALUE val)
00782 {
00783 if (val == Qundef) {
00784 return rb_yield_0(0, 0);
00785 }
00786 else {
00787 return rb_yield_0(1, &val);
00788 }
00789 }
00790
00791 VALUE
00792 rb_yield_values(int n, ...)
00793 {
00794 if (n == 0) {
00795 return rb_yield_0(0, 0);
00796 }
00797 else {
00798 int i;
00799 VALUE *argv;
00800 va_list args;
00801 argv = ALLOCA_N(VALUE, n);
00802
00803 va_init_list(args, n);
00804 for (i=0; i<n; i++) {
00805 argv[i] = va_arg(args, VALUE);
00806 }
00807 va_end(args);
00808
00809 return rb_yield_0(n, argv);
00810 }
00811 }
00812
00813 VALUE
00814 rb_yield_values2(int argc, const VALUE *argv)
00815 {
00816 return rb_yield_0(argc, argv);
00817 }
00818
00819 VALUE
00820 rb_yield_splat(VALUE values)
00821 {
00822 VALUE tmp = rb_check_array_type(values);
00823 volatile VALUE v;
00824 if (NIL_P(tmp)) {
00825 rb_raise(rb_eArgError, "not an array");
00826 }
00827 v = rb_yield_0(RARRAY_LENINT(tmp), RARRAY_PTR(tmp));
00828 return v;
00829 }
00830
00831 static VALUE
00832 loop_i(void)
00833 {
00834 for (;;) {
00835 rb_yield_0(0, 0);
00836 }
00837 return Qnil;
00838 }
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 static VALUE
00860 rb_f_loop(VALUE self)
00861 {
00862 RETURN_ENUMERATOR(self, 0, 0);
00863 rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
00864 return Qnil;
00865 }
00866
00867 #if VMDEBUG
00868 static const char *
00869 vm_frametype_name(const rb_control_frame_t *cfp);
00870 #endif
00871
00872 VALUE
00873 rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
00874 VALUE (* bl_proc) (ANYARGS), VALUE data2)
00875 {
00876 int state;
00877 volatile VALUE retval = Qnil;
00878 NODE *node = NEW_IFUNC(bl_proc, data2);
00879 rb_thread_t *th = GET_THREAD();
00880 rb_control_frame_t *volatile cfp = th->cfp;
00881
00882 node->nd_aid = rb_frame_this_func();
00883 TH_PUSH_TAG(th);
00884 state = TH_EXEC_TAG();
00885 if (state == 0) {
00886 iter_retry:
00887 {
00888 rb_block_t *blockptr;
00889 if (bl_proc) {
00890 blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp);
00891 blockptr->iseq = (void *)node;
00892 blockptr->proc = 0;
00893 }
00894 else {
00895 blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
00896 }
00897 th->passed_block = blockptr;
00898 }
00899 retval = (*it_proc) (data1);
00900 }
00901 else {
00902 VALUE err = th->errinfo;
00903 if (state == TAG_BREAK) {
00904 VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
00905 VALUE *cdfp = cfp->dfp;
00906
00907 if (cdfp == escape_dfp) {
00908 state = 0;
00909 th->state = 0;
00910 th->errinfo = Qnil;
00911
00912
00913 while (th->cfp != cfp) {
00914 #if VMDEBUG
00915 printf("skipped frame: %s\n", vm_frametype_name(th->cfp));
00916 #endif
00917 if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) {
00918 const rb_method_entry_t *me = th->cfp->me;
00919 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass);
00920 }
00921
00922 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00923 }
00924 }
00925 else{
00926
00927 }
00928 }
00929 else if (state == TAG_RETRY) {
00930 VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
00931 VALUE *cdfp = cfp->dfp;
00932
00933 if (cdfp == escape_dfp) {
00934 state = 0;
00935 th->state = 0;
00936 th->errinfo = Qnil;
00937 th->cfp = cfp;
00938 goto iter_retry;
00939 }
00940 }
00941 }
00942 TH_POP_TAG();
00943
00944 switch (state) {
00945 case 0:
00946 break;
00947 default:
00948 TH_JUMP_TAG(th, state);
00949 }
00950 return retval;
00951 }
00952
00953 struct iter_method_arg {
00954 VALUE obj;
00955 ID mid;
00956 int argc;
00957 VALUE *argv;
00958 };
00959
00960 static VALUE
00961 iterate_method(VALUE obj)
00962 {
00963 const struct iter_method_arg * arg =
00964 (struct iter_method_arg *) obj;
00965
00966 return rb_call(arg->obj, arg->mid, arg->argc, arg->argv, CALL_FCALL);
00967 }
00968
00969 VALUE
00970 rb_block_call(VALUE obj, ID mid, int argc, VALUE * argv,
00971 VALUE (*bl_proc) (ANYARGS), VALUE data2)
00972 {
00973 struct iter_method_arg arg;
00974
00975 arg.obj = obj;
00976 arg.mid = mid;
00977 arg.argc = argc;
00978 arg.argv = argv;
00979 return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
00980 }
00981
00982 VALUE
00983 rb_each(VALUE obj)
00984 {
00985 return rb_call(obj, idEach, 0, 0, CALL_FCALL);
00986 }
00987
00988 static VALUE
00989 eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *volatile file, volatile int line)
00990 {
00991 int state;
00992 VALUE result = Qundef;
00993 VALUE envval;
00994 rb_binding_t *bind = 0;
00995 rb_thread_t *th = GET_THREAD();
00996 rb_env_t *env = NULL;
00997 rb_block_t block;
00998 volatile int parse_in_eval;
00999 volatile int mild_compile_error;
01000
01001 if (file == 0) {
01002 file = rb_sourcefile();
01003 line = rb_sourceline();
01004 }
01005
01006 parse_in_eval = th->parse_in_eval;
01007 mild_compile_error = th->mild_compile_error;
01008 PUSH_TAG();
01009 if ((state = EXEC_TAG()) == 0) {
01010 rb_iseq_t *iseq;
01011 volatile VALUE iseqval;
01012
01013 if (scope != Qnil) {
01014 if (rb_obj_is_kind_of(scope, rb_cBinding)) {
01015 GetBindingPtr(scope, bind);
01016 envval = bind->env;
01017 if (strcmp(file, "(eval)") == 0 && bind->filename != Qnil) {
01018 file = RSTRING_PTR(bind->filename);
01019 line = bind->line_no;
01020 }
01021 }
01022 else {
01023 rb_raise(rb_eTypeError,
01024 "wrong argument type %s (expected Binding)",
01025 rb_obj_classname(scope));
01026 }
01027 GetEnvPtr(envval, env);
01028 th->base_block = &env->block;
01029 }
01030 else {
01031 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
01032
01033 if (cfp != 0) {
01034 block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
01035 th->base_block = █
01036 th->base_block->self = self;
01037 th->base_block->iseq = cfp->iseq;
01038 }
01039 else {
01040 rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
01041 }
01042 }
01043
01044
01045 th->parse_in_eval++;
01046 th->mild_compile_error++;
01047 iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line));
01048 th->mild_compile_error--;
01049 th->parse_in_eval--;
01050
01051 vm_set_eval_stack(th, iseqval, cref);
01052 th->base_block = 0;
01053
01054 if (0) {
01055 VALUE disasm = rb_iseq_disasm(iseqval);
01056 printf("%s\n", StringValuePtr(disasm));
01057 }
01058
01059
01060 GetISeqPtr(iseqval, iseq);
01061 if (bind && iseq->local_table_size > 0) {
01062 bind->env = rb_vm_make_env_object(th, th->cfp);
01063 }
01064
01065
01066 CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
01067 result = vm_exec(th);
01068 }
01069 POP_TAG();
01070 th->mild_compile_error = mild_compile_error;
01071 th->parse_in_eval = parse_in_eval;
01072
01073 if (state) {
01074 if (state == TAG_RAISE) {
01075 VALUE errinfo = th->errinfo;
01076 if (strcmp(file, "(eval)") == 0) {
01077 VALUE mesg, errat, bt2;
01078 ID id_mesg;
01079
01080 CONST_ID(id_mesg, "mesg");
01081 errat = rb_get_backtrace(errinfo);
01082 mesg = rb_attr_get(errinfo, id_mesg);
01083 if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
01084 (bt2 = vm_backtrace(th, -2), RARRAY_LEN(bt2) > 0)) {
01085 if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_LEN(mesg)) {
01086 if (OBJ_FROZEN(mesg)) {
01087 VALUE m = rb_str_cat(rb_str_dup(RARRAY_PTR(errat)[0]), ": ", 2);
01088 rb_ivar_set(errinfo, id_mesg, rb_str_append(m, mesg));
01089 }
01090 else {
01091 rb_str_update(mesg, 0, 0, rb_str_new2(": "));
01092 rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]);
01093 }
01094 }
01095 RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0];
01096 }
01097 }
01098 rb_exc_raise(errinfo);
01099 }
01100 JUMP_TAG(state);
01101 }
01102 return result;
01103 }
01104
01105 static VALUE
01106 eval_string(VALUE self, VALUE src, VALUE scope, const char *file, int line)
01107 {
01108 return eval_string_with_cref(self, src, scope, 0, file, line);
01109 }
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129 VALUE
01130 rb_f_eval(int argc, VALUE *argv, VALUE self)
01131 {
01132 VALUE src, scope, vfile, vline;
01133 const char *file = "(eval)";
01134 int line = 1;
01135
01136 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
01137 if (rb_safe_level() >= 4) {
01138 StringValue(src);
01139 if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
01140 rb_raise(rb_eSecurityError,
01141 "Insecure: can't modify trusted binding");
01142 }
01143 }
01144 else {
01145 SafeStringValue(src);
01146 }
01147 if (argc >= 3) {
01148 StringValue(vfile);
01149 }
01150 if (argc >= 4) {
01151 line = NUM2INT(vline);
01152 }
01153
01154 if (!NIL_P(vfile))
01155 file = RSTRING_PTR(vfile);
01156 return eval_string(self, src, scope, file, line);
01157 }
01158
01159 VALUE
01160 rb_eval_string(const char *str)
01161 {
01162 return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1);
01163 }
01164
01165 VALUE
01166 rb_eval_string_protect(const char *str, int *state)
01167 {
01168 return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state);
01169 }
01170
01171 VALUE
01172 rb_eval_string_wrap(const char *str, int *state)
01173 {
01174 int status;
01175 rb_thread_t *th = GET_THREAD();
01176 VALUE self = th->top_self;
01177 VALUE wrapper = th->top_wrapper;
01178 VALUE val;
01179
01180 th->top_wrapper = rb_module_new();
01181 th->top_self = rb_obj_clone(rb_vm_top_self());
01182 rb_extend_object(th->top_self, th->top_wrapper);
01183
01184 val = rb_eval_string_protect(str, &status);
01185
01186 th->top_self = self;
01187 th->top_wrapper = wrapper;
01188
01189 if (state) {
01190 *state = status;
01191 }
01192 else if (status) {
01193 JUMP_TAG(status);
01194 }
01195 return val;
01196 }
01197
01198 VALUE
01199 rb_eval_cmd(VALUE cmd, VALUE arg, int level)
01200 {
01201 int state;
01202 VALUE val = Qnil;
01203 volatile int safe = rb_safe_level();
01204
01205 if (OBJ_TAINTED(cmd)) {
01206 level = 4;
01207 }
01208
01209 if (TYPE(cmd) != T_STRING) {
01210 PUSH_TAG();
01211 rb_set_safe_level_force(level);
01212 if ((state = EXEC_TAG()) == 0) {
01213 val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LENINT(arg),
01214 RARRAY_PTR(arg));
01215 }
01216 POP_TAG();
01217
01218 rb_set_safe_level_force(safe);
01219
01220 if (state)
01221 JUMP_TAG(state);
01222 return val;
01223 }
01224
01225 PUSH_TAG();
01226 if ((state = EXEC_TAG()) == 0) {
01227 val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0);
01228 }
01229 POP_TAG();
01230
01231 rb_set_safe_level_force(safe);
01232 if (state) JUMP_TAG(state);
01233 return val;
01234 }
01235
01236
01237
01238 static VALUE
01239 yield_under(VALUE under, VALUE self, VALUE values)
01240 {
01241 rb_thread_t *th = GET_THREAD();
01242 rb_block_t block, *blockptr;
01243 NODE *cref;
01244
01245 if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
01246 block = *blockptr;
01247 block.self = self;
01248 th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
01249 }
01250 cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
01251 cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
01252
01253 if (values == Qundef) {
01254 return vm_yield_with_cref(th, 1, &self, cref);
01255 }
01256 else {
01257 return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_PTR(values), cref);
01258 }
01259 }
01260
01261
01262 static VALUE
01263 eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
01264 {
01265 NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL);
01266
01267 if (rb_safe_level() >= 4) {
01268 StringValue(src);
01269 }
01270 else {
01271 SafeStringValue(src);
01272 }
01273
01274 return eval_string_with_cref(self, src, Qnil, cref, file, line);
01275 }
01276
01277 static VALUE
01278 specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
01279 {
01280 if (rb_block_given_p()) {
01281 if (argc > 0) {
01282 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
01283 }
01284 return yield_under(klass, self, Qundef);
01285 }
01286 else {
01287 const char *file = "(eval)";
01288 int line = 1;
01289
01290 if (argc == 0) {
01291 rb_raise(rb_eArgError, "block not supplied");
01292 }
01293 else {
01294 if (rb_safe_level() >= 4) {
01295 StringValue(argv[0]);
01296 }
01297 else {
01298 SafeStringValue(argv[0]);
01299 }
01300 if (argc > 3) {
01301 const char *name = rb_id2name(rb_frame_callee());
01302 rb_raise(rb_eArgError,
01303 "wrong number of arguments: %s(src) or %s{..}",
01304 name, name);
01305 }
01306 if (argc > 2)
01307 line = NUM2INT(argv[2]);
01308 if (argc > 1) {
01309 file = StringValuePtr(argv[1]);
01310 }
01311 }
01312 return eval_under(klass, self, argv[0], file, line);
01313 }
01314 }
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339 VALUE
01340 rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
01341 {
01342 VALUE klass;
01343
01344 if (SPECIAL_CONST_P(self)) {
01345 klass = Qnil;
01346 }
01347 else {
01348 klass = rb_singleton_class(self);
01349 }
01350 return specific_eval(argc, argv, klass, self);
01351 }
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371 VALUE
01372 rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
01373 {
01374 VALUE klass;
01375
01376 if (SPECIAL_CONST_P(self)) {
01377 klass = Qnil;
01378 }
01379 else {
01380 klass = rb_singleton_class(self);
01381 }
01382 return yield_under(klass, self, rb_ary_new4(argc, argv));
01383 }
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409 VALUE
01410 rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
01411 {
01412 return specific_eval(argc, argv, mod, mod);
01413 }
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435 VALUE
01436 rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
01437 {
01438 return yield_under(mod, mod, rb_ary_new4(argc, argv));
01439 }
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453 static VALUE
01454 rb_f_throw(int argc, VALUE *argv)
01455 {
01456 VALUE tag, value;
01457
01458 rb_scan_args(argc, argv, "11", &tag, &value);
01459 rb_throw_obj(tag, value);
01460 return Qnil;
01461 }
01462
01463 void
01464 rb_throw_obj(VALUE tag, VALUE value)
01465 {
01466 rb_thread_t *th = GET_THREAD();
01467 struct rb_vm_tag *tt = th->tag;
01468
01469 while (tt) {
01470 if (tt->tag == tag) {
01471 tt->retval = value;
01472 break;
01473 }
01474 tt = tt->prev;
01475 }
01476 if (!tt) {
01477 VALUE desc = rb_inspect(tag);
01478 RB_GC_GUARD(desc);
01479 rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc));
01480 }
01481 rb_trap_restore_mask();
01482 th->errinfo = NEW_THROW_OBJECT(tag, 0, TAG_THROW);
01483
01484 JUMP_TAG(TAG_THROW);
01485 }
01486
01487 void
01488 rb_throw(const char *tag, VALUE val)
01489 {
01490 rb_throw_obj(ID2SYM(rb_intern(tag)), val);
01491 }
01492
01493 static VALUE
01494 catch_i(VALUE tag, VALUE data)
01495 {
01496 return rb_yield_0(1, &tag);
01497 }
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536 static VALUE
01537 rb_f_catch(int argc, VALUE *argv)
01538 {
01539 VALUE tag;
01540
01541 if (argc == 0) {
01542 tag = rb_obj_alloc(rb_cObject);
01543 }
01544 else {
01545 rb_scan_args(argc, argv, "01", &tag);
01546 }
01547 return rb_catch_obj(tag, catch_i, 0);
01548 }
01549
01550 VALUE
01551 rb_catch(const char *tag, VALUE (*func)(), VALUE data)
01552 {
01553 VALUE vtag = tag ? ID2SYM(rb_intern(tag)) : rb_obj_alloc(rb_cObject);
01554 return rb_catch_obj(vtag, func, data);
01555 }
01556
01557 VALUE
01558 rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
01559 {
01560 int state;
01561 volatile VALUE val = Qnil;
01562 rb_thread_t *th = GET_THREAD();
01563 rb_control_frame_t *saved_cfp = th->cfp;
01564
01565 PUSH_TAG();
01566
01567 th->tag->tag = tag;
01568
01569 if ((state = EXEC_TAG()) == 0) {
01570
01571 val = (*func)(tag, data, 1, &tag, Qnil);
01572 }
01573 else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
01574 th->cfp = saved_cfp;
01575 val = th->tag->retval;
01576 th->errinfo = Qnil;
01577 state = 0;
01578 }
01579 POP_TAG();
01580 if (state)
01581 JUMP_TAG(state);
01582
01583 return val;
01584 }
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616 static VALUE
01617 rb_f_caller(int argc, VALUE *argv)
01618 {
01619 VALUE level;
01620 int lev;
01621
01622 rb_scan_args(argc, argv, "01", &level);
01623
01624 if (NIL_P(level))
01625 lev = 1;
01626 else
01627 lev = NUM2INT(level);
01628 if (lev < 0)
01629 rb_raise(rb_eArgError, "negative level (%d)", lev);
01630
01631 return vm_backtrace(GET_THREAD(), lev);
01632 }
01633
01634 static int
01635 print_backtrace(void *arg, VALUE file, int line, VALUE method)
01636 {
01637 FILE *fp = arg;
01638 const char *filename = NIL_P(file) ? "ruby" : RSTRING_PTR(file);
01639 if (NIL_P(method)) {
01640 fprintf(fp, "\tfrom %s:%d:in unknown method\n",
01641 filename, line);
01642 }
01643 else {
01644 fprintf(fp, "\tfrom %s:%d:in `%s'\n",
01645 filename, line, RSTRING_PTR(method));
01646 }
01647 return FALSE;
01648 }
01649
01650 void
01651 rb_backtrace(void)
01652 {
01653 vm_backtrace_each(GET_THREAD(), -1, NULL, print_backtrace, stderr);
01654 }
01655
01656 VALUE
01657 rb_make_backtrace(void)
01658 {
01659 return vm_backtrace(GET_THREAD(), -1);
01660 }
01661
01662 VALUE
01663 rb_thread_backtrace(VALUE thval)
01664 {
01665 rb_thread_t *th;
01666 GetThreadPtr(thval, th);
01667
01668 switch (th->status) {
01669 case THREAD_RUNNABLE:
01670 case THREAD_STOPPED:
01671 case THREAD_STOPPED_FOREVER:
01672 break;
01673 case THREAD_TO_KILL:
01674 case THREAD_KILLED:
01675 return Qnil;
01676 }
01677
01678 return vm_backtrace(th, 0);
01679 }
01680
01681 int
01682 rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg)
01683 {
01684 return vm_backtrace_each(GET_THREAD(), -1, NULL, iter, arg);
01685 }
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700 static VALUE
01701 rb_f_local_variables(void)
01702 {
01703 VALUE ary = rb_ary_new();
01704 rb_thread_t *th = GET_THREAD();
01705 rb_control_frame_t *cfp =
01706 vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
01707 int i;
01708
01709 while (cfp) {
01710 if (cfp->iseq) {
01711 for (i = 0; i < cfp->iseq->local_table_size; i++) {
01712 ID lid = cfp->iseq->local_table[i];
01713 if (lid) {
01714 const char *vname = rb_id2name(lid);
01715
01716 if (vname) {
01717 rb_ary_push(ary, ID2SYM(lid));
01718 }
01719 }
01720 }
01721 }
01722 if (cfp->lfp != cfp->dfp) {
01723
01724 VALUE *dfp = GC_GUARDED_PTR_REF(cfp->dfp[0]);
01725
01726 if (vm_collect_local_variables_in_heap(th, dfp, ary)) {
01727 break;
01728 }
01729 else {
01730 while (cfp->dfp != dfp) {
01731 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01732 }
01733 }
01734 }
01735 else {
01736 break;
01737 }
01738 }
01739 return ary;
01740 }
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764 VALUE
01765 rb_f_block_given_p(void)
01766 {
01767 rb_thread_t *th = GET_THREAD();
01768 rb_control_frame_t *cfp = th->cfp;
01769 cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
01770
01771 if (cfp != 0 &&
01772 (cfp->lfp[0] & 0x02) == 0 &&
01773 GC_GUARDED_PTR_REF(cfp->lfp[0])) {
01774 return Qtrue;
01775 }
01776 else {
01777 return Qfalse;
01778 }
01779 }
01780
01781 VALUE
01782 rb_current_realfilepath(void)
01783 {
01784 rb_thread_t *th = GET_THREAD();
01785 rb_control_frame_t *cfp = th->cfp;
01786 cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
01787 if (cfp != 0) return cfp->iseq->filepath;
01788 return Qnil;
01789 }
01790
01791 void
01792 Init_vm_eval(void)
01793 {
01794 rb_define_global_function("eval", rb_f_eval, -1);
01795 rb_define_global_function("local_variables", rb_f_local_variables, 0);
01796 rb_define_global_function("iterator?", rb_f_block_given_p, 0);
01797 rb_define_global_function("block_given?", rb_f_block_given_p, 0);
01798
01799 rb_define_global_function("catch", rb_f_catch, -1);
01800 rb_define_global_function("throw", rb_f_throw, -1);
01801
01802 rb_define_global_function("loop", rb_f_loop, 0);
01803
01804 rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
01805 rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
01806 rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
01807
01808 #if 1
01809 rb_add_method(rb_cBasicObject, rb_intern("__send__"),
01810 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
01811 rb_add_method(rb_mKernel, rb_intern("send"),
01812 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
01813 #else
01814 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
01815 rb_define_method(rb_mKernel, "send", rb_f_send, -1);
01816 #endif
01817 rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
01818
01819 rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
01820 rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
01821 rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
01822 rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
01823
01824 rb_define_global_function("caller", rb_f_caller, -1);
01825 }
01826
01827