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 static VALUE
00698 send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
00699 {
00700 VALUE vid;
00701 VALUE self = RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp)->self;
00702 rb_thread_t *th = GET_THREAD();
00703
00704 if (argc == 0) {
00705 rb_raise(rb_eArgError, "no method name given");
00706 }
00707
00708 vid = *argv++; argc--;
00709 PASS_PASSED_BLOCK_TH(th);
00710
00711 return rb_call0(recv, rb_to_id(vid), argc, argv, scope, self);
00712 }
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 VALUE
00733 rb_f_send(int argc, VALUE *argv, VALUE recv)
00734 {
00735 return send_internal(argc, argv, recv, CALL_FCALL);
00736 }
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749 VALUE
00750 rb_f_public_send(int argc, VALUE *argv, VALUE recv)
00751 {
00752 return send_internal(argc, argv, recv, CALL_PUBLIC);
00753 }
00754
00755
00756
00757 static inline VALUE
00758 rb_yield_0(int argc, const VALUE * argv)
00759 {
00760 return vm_yield(GET_THREAD(), argc, argv);
00761 }
00762
00763 VALUE
00764 rb_yield(VALUE val)
00765 {
00766 if (val == Qundef) {
00767 return rb_yield_0(0, 0);
00768 }
00769 else {
00770 return rb_yield_0(1, &val);
00771 }
00772 }
00773
00774 VALUE
00775 rb_yield_values(int n, ...)
00776 {
00777 if (n == 0) {
00778 return rb_yield_0(0, 0);
00779 }
00780 else {
00781 int i;
00782 VALUE *argv;
00783 va_list args;
00784 argv = ALLOCA_N(VALUE, n);
00785
00786 va_init_list(args, n);
00787 for (i=0; i<n; i++) {
00788 argv[i] = va_arg(args, VALUE);
00789 }
00790 va_end(args);
00791
00792 return rb_yield_0(n, argv);
00793 }
00794 }
00795
00796 VALUE
00797 rb_yield_values2(int argc, const VALUE *argv)
00798 {
00799 return rb_yield_0(argc, argv);
00800 }
00801
00802 VALUE
00803 rb_yield_splat(VALUE values)
00804 {
00805 VALUE tmp = rb_check_array_type(values);
00806 volatile VALUE v;
00807 if (NIL_P(tmp)) {
00808 rb_raise(rb_eArgError, "not an array");
00809 }
00810 v = rb_yield_0(RARRAY_LENINT(tmp), RARRAY_PTR(tmp));
00811 return v;
00812 }
00813
00814 static VALUE
00815 loop_i(void)
00816 {
00817 for (;;) {
00818 rb_yield_0(0, 0);
00819 }
00820 return Qnil;
00821 }
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842 static VALUE
00843 rb_f_loop(VALUE self)
00844 {
00845 RETURN_ENUMERATOR(self, 0, 0);
00846 rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
00847 return Qnil;
00848 }
00849
00850 #if VMDEBUG
00851 static const char *
00852 vm_frametype_name(const rb_control_frame_t *cfp);
00853 #endif
00854
00855 VALUE
00856 rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
00857 VALUE (* bl_proc) (ANYARGS), VALUE data2)
00858 {
00859 int state;
00860 volatile VALUE retval = Qnil;
00861 NODE *node = NEW_IFUNC(bl_proc, data2);
00862 rb_thread_t *th = GET_THREAD();
00863 rb_control_frame_t *volatile cfp = th->cfp;
00864
00865 node->nd_aid = rb_frame_this_func();
00866 TH_PUSH_TAG(th);
00867 state = TH_EXEC_TAG();
00868 if (state == 0) {
00869 iter_retry:
00870 {
00871 rb_block_t *blockptr;
00872 if (bl_proc) {
00873 blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp);
00874 blockptr->iseq = (void *)node;
00875 blockptr->proc = 0;
00876 }
00877 else {
00878 blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
00879 }
00880 th->passed_block = blockptr;
00881 }
00882 retval = (*it_proc) (data1);
00883 }
00884 else {
00885 VALUE err = th->errinfo;
00886 if (state == TAG_BREAK) {
00887 VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
00888 VALUE *cdfp = cfp->dfp;
00889
00890 if (cdfp == escape_dfp) {
00891 state = 0;
00892 th->state = 0;
00893 th->errinfo = Qnil;
00894
00895
00896 while (th->cfp != cfp) {
00897 #if VMDEBUG
00898 printf("skipped frame: %s\n", vm_frametype_name(th->cfp));
00899 #endif
00900 if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) {
00901 const rb_method_entry_t *me = th->cfp->me;
00902 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass);
00903 }
00904
00905 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00906 }
00907 }
00908 else{
00909
00910 }
00911 }
00912 else if (state == TAG_RETRY) {
00913 VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
00914 VALUE *cdfp = cfp->dfp;
00915
00916 if (cdfp == escape_dfp) {
00917 state = 0;
00918 th->state = 0;
00919 th->errinfo = Qnil;
00920 th->cfp = cfp;
00921 goto iter_retry;
00922 }
00923 }
00924 }
00925 TH_POP_TAG();
00926
00927 switch (state) {
00928 case 0:
00929 break;
00930 default:
00931 TH_JUMP_TAG(th, state);
00932 }
00933 return retval;
00934 }
00935
00936 struct iter_method_arg {
00937 VALUE obj;
00938 ID mid;
00939 int argc;
00940 VALUE *argv;
00941 };
00942
00943 static VALUE
00944 iterate_method(VALUE obj)
00945 {
00946 const struct iter_method_arg * arg =
00947 (struct iter_method_arg *) obj;
00948
00949 return rb_call(arg->obj, arg->mid, arg->argc, arg->argv, CALL_FCALL);
00950 }
00951
00952 VALUE
00953 rb_block_call(VALUE obj, ID mid, int argc, VALUE * argv,
00954 VALUE (*bl_proc) (ANYARGS), VALUE data2)
00955 {
00956 struct iter_method_arg arg;
00957
00958 arg.obj = obj;
00959 arg.mid = mid;
00960 arg.argc = argc;
00961 arg.argv = argv;
00962 return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
00963 }
00964
00965 VALUE
00966 rb_each(VALUE obj)
00967 {
00968 return rb_call(obj, idEach, 0, 0, CALL_FCALL);
00969 }
00970
00971 static VALUE
00972 eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *volatile file, volatile int line)
00973 {
00974 int state;
00975 VALUE result = Qundef;
00976 VALUE envval;
00977 rb_binding_t *bind = 0;
00978 rb_thread_t *th = GET_THREAD();
00979 rb_env_t *env = NULL;
00980 rb_block_t block;
00981 volatile int parse_in_eval;
00982 volatile int mild_compile_error;
00983
00984 if (file == 0) {
00985 file = rb_sourcefile();
00986 line = rb_sourceline();
00987 }
00988
00989 parse_in_eval = th->parse_in_eval;
00990 mild_compile_error = th->mild_compile_error;
00991 PUSH_TAG();
00992 if ((state = EXEC_TAG()) == 0) {
00993 rb_iseq_t *iseq;
00994 volatile VALUE iseqval;
00995
00996 if (scope != Qnil) {
00997 if (rb_obj_is_kind_of(scope, rb_cBinding)) {
00998 GetBindingPtr(scope, bind);
00999 envval = bind->env;
01000 if (strcmp(file, "(eval)") == 0 && bind->filename != Qnil) {
01001 file = RSTRING_PTR(bind->filename);
01002 line = bind->line_no;
01003 }
01004 }
01005 else {
01006 rb_raise(rb_eTypeError,
01007 "wrong argument type %s (expected Binding)",
01008 rb_obj_classname(scope));
01009 }
01010 GetEnvPtr(envval, env);
01011 th->base_block = &env->block;
01012 }
01013 else {
01014 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
01015
01016 if (cfp != 0) {
01017 block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
01018 th->base_block = █
01019 th->base_block->self = self;
01020 th->base_block->iseq = cfp->iseq;
01021 }
01022 else {
01023 rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
01024 }
01025 }
01026
01027
01028 th->parse_in_eval++;
01029 th->mild_compile_error++;
01030 iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line));
01031 th->mild_compile_error--;
01032 th->parse_in_eval--;
01033
01034 vm_set_eval_stack(th, iseqval, cref);
01035 th->base_block = 0;
01036
01037 if (0) {
01038 VALUE disasm = rb_iseq_disasm(iseqval);
01039 printf("%s\n", StringValuePtr(disasm));
01040 }
01041
01042
01043 GetISeqPtr(iseqval, iseq);
01044 if (bind && iseq->local_table_size > 0) {
01045 bind->env = rb_vm_make_env_object(th, th->cfp);
01046 }
01047
01048
01049 CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
01050 result = vm_exec(th);
01051 }
01052 POP_TAG();
01053 th->mild_compile_error = mild_compile_error;
01054 th->parse_in_eval = parse_in_eval;
01055
01056 if (state) {
01057 if (state == TAG_RAISE) {
01058 VALUE errinfo = th->errinfo;
01059 if (strcmp(file, "(eval)") == 0) {
01060 VALUE mesg, errat, bt2;
01061 ID id_mesg;
01062
01063 CONST_ID(id_mesg, "mesg");
01064 errat = rb_get_backtrace(errinfo);
01065 mesg = rb_attr_get(errinfo, id_mesg);
01066 if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
01067 (bt2 = vm_backtrace(th, -2), RARRAY_LEN(bt2) > 0)) {
01068 if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_LEN(mesg)) {
01069 if (OBJ_FROZEN(mesg)) {
01070 VALUE m = rb_str_cat(rb_str_dup(RARRAY_PTR(errat)[0]), ": ", 2);
01071 rb_ivar_set(errinfo, id_mesg, rb_str_append(m, mesg));
01072 }
01073 else {
01074 rb_str_update(mesg, 0, 0, rb_str_new2(": "));
01075 rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]);
01076 }
01077 }
01078 RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0];
01079 }
01080 }
01081 rb_exc_raise(errinfo);
01082 }
01083 JUMP_TAG(state);
01084 }
01085 return result;
01086 }
01087
01088 static VALUE
01089 eval_string(VALUE self, VALUE src, VALUE scope, const char *file, int line)
01090 {
01091 return eval_string_with_cref(self, src, scope, 0, file, line);
01092 }
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112 VALUE
01113 rb_f_eval(int argc, VALUE *argv, VALUE self)
01114 {
01115 VALUE src, scope, vfile, vline;
01116 const char *file = "(eval)";
01117 int line = 1;
01118
01119 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
01120 if (rb_safe_level() >= 4) {
01121 StringValue(src);
01122 if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
01123 rb_raise(rb_eSecurityError,
01124 "Insecure: can't modify trusted binding");
01125 }
01126 }
01127 else {
01128 SafeStringValue(src);
01129 }
01130 if (argc >= 3) {
01131 StringValue(vfile);
01132 }
01133 if (argc >= 4) {
01134 line = NUM2INT(vline);
01135 }
01136
01137 if (!NIL_P(vfile))
01138 file = RSTRING_PTR(vfile);
01139 return eval_string(self, src, scope, file, line);
01140 }
01141
01142 VALUE
01143 rb_eval_string(const char *str)
01144 {
01145 return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1);
01146 }
01147
01148 VALUE
01149 rb_eval_string_protect(const char *str, int *state)
01150 {
01151 return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state);
01152 }
01153
01154 VALUE
01155 rb_eval_string_wrap(const char *str, int *state)
01156 {
01157 int status;
01158 rb_thread_t *th = GET_THREAD();
01159 VALUE self = th->top_self;
01160 VALUE wrapper = th->top_wrapper;
01161 VALUE val;
01162
01163 th->top_wrapper = rb_module_new();
01164 th->top_self = rb_obj_clone(rb_vm_top_self());
01165 rb_extend_object(th->top_self, th->top_wrapper);
01166
01167 val = rb_eval_string_protect(str, &status);
01168
01169 th->top_self = self;
01170 th->top_wrapper = wrapper;
01171
01172 if (state) {
01173 *state = status;
01174 }
01175 else if (status) {
01176 JUMP_TAG(status);
01177 }
01178 return val;
01179 }
01180
01181 VALUE
01182 rb_eval_cmd(VALUE cmd, VALUE arg, int level)
01183 {
01184 int state;
01185 VALUE val = Qnil;
01186 volatile int safe = rb_safe_level();
01187
01188 if (OBJ_TAINTED(cmd)) {
01189 level = 4;
01190 }
01191
01192 if (TYPE(cmd) != T_STRING) {
01193 PUSH_TAG();
01194 rb_set_safe_level_force(level);
01195 if ((state = EXEC_TAG()) == 0) {
01196 val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LENINT(arg),
01197 RARRAY_PTR(arg));
01198 }
01199 POP_TAG();
01200
01201 rb_set_safe_level_force(safe);
01202
01203 if (state)
01204 JUMP_TAG(state);
01205 return val;
01206 }
01207
01208 PUSH_TAG();
01209 if ((state = EXEC_TAG()) == 0) {
01210 val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0);
01211 }
01212 POP_TAG();
01213
01214 rb_set_safe_level_force(safe);
01215 if (state) rb_vm_jump_tag_but_local_jump(state, val);
01216 return val;
01217 }
01218
01219
01220
01221 static VALUE
01222 yield_under(VALUE under, VALUE self, VALUE values)
01223 {
01224 rb_thread_t *th = GET_THREAD();
01225 rb_block_t block, *blockptr;
01226 NODE *cref;
01227
01228 if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
01229 block = *blockptr;
01230 block.self = self;
01231 th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
01232 }
01233 cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
01234 cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
01235
01236 if (values == Qundef) {
01237 return vm_yield_with_cref(th, 1, &self, cref);
01238 }
01239 else {
01240 return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_PTR(values), cref);
01241 }
01242 }
01243
01244
01245 static VALUE
01246 eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
01247 {
01248 NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL);
01249
01250 if (rb_safe_level() >= 4) {
01251 StringValue(src);
01252 }
01253 else {
01254 SafeStringValue(src);
01255 }
01256
01257 return eval_string_with_cref(self, src, Qnil, cref, file, line);
01258 }
01259
01260 static VALUE
01261 specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
01262 {
01263 if (rb_block_given_p()) {
01264 if (argc > 0) {
01265 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
01266 }
01267 return yield_under(klass, self, Qundef);
01268 }
01269 else {
01270 const char *file = "(eval)";
01271 int line = 1;
01272
01273 if (argc == 0) {
01274 rb_raise(rb_eArgError, "block not supplied");
01275 }
01276 else {
01277 if (rb_safe_level() >= 4) {
01278 StringValue(argv[0]);
01279 }
01280 else {
01281 SafeStringValue(argv[0]);
01282 }
01283 if (argc > 3) {
01284 const char *name = rb_id2name(rb_frame_callee());
01285 rb_raise(rb_eArgError,
01286 "wrong number of arguments: %s(src) or %s{..}",
01287 name, name);
01288 }
01289 if (argc > 2)
01290 line = NUM2INT(argv[2]);
01291 if (argc > 1) {
01292 file = StringValuePtr(argv[1]);
01293 }
01294 }
01295 return eval_under(klass, self, argv[0], file, line);
01296 }
01297 }
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322 VALUE
01323 rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
01324 {
01325 VALUE klass;
01326
01327 if (SPECIAL_CONST_P(self)) {
01328 klass = Qnil;
01329 }
01330 else {
01331 klass = rb_singleton_class(self);
01332 }
01333 return specific_eval(argc, argv, klass, self);
01334 }
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354 VALUE
01355 rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
01356 {
01357 VALUE klass;
01358
01359 if (SPECIAL_CONST_P(self)) {
01360 klass = Qnil;
01361 }
01362 else {
01363 klass = rb_singleton_class(self);
01364 }
01365 return yield_under(klass, self, rb_ary_new4(argc, argv));
01366 }
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392 VALUE
01393 rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
01394 {
01395 return specific_eval(argc, argv, mod, mod);
01396 }
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418 VALUE
01419 rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
01420 {
01421 return yield_under(mod, mod, rb_ary_new4(argc, argv));
01422 }
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436 static VALUE
01437 rb_f_throw(int argc, VALUE *argv)
01438 {
01439 VALUE tag, value;
01440
01441 rb_scan_args(argc, argv, "11", &tag, &value);
01442 rb_throw_obj(tag, value);
01443 return Qnil;
01444 }
01445
01446 void
01447 rb_throw_obj(VALUE tag, VALUE value)
01448 {
01449 rb_thread_t *th = GET_THREAD();
01450 struct rb_vm_tag *tt = th->tag;
01451
01452 while (tt) {
01453 if (tt->tag == tag) {
01454 tt->retval = value;
01455 break;
01456 }
01457 tt = tt->prev;
01458 }
01459 if (!tt) {
01460 VALUE desc = rb_inspect(tag);
01461 RB_GC_GUARD(desc);
01462 rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc));
01463 }
01464 rb_trap_restore_mask();
01465 th->errinfo = NEW_THROW_OBJECT(tag, 0, TAG_THROW);
01466
01467 JUMP_TAG(TAG_THROW);
01468 }
01469
01470 void
01471 rb_throw(const char *tag, VALUE val)
01472 {
01473 rb_throw_obj(ID2SYM(rb_intern(tag)), val);
01474 }
01475
01476 static VALUE
01477 catch_i(VALUE tag, VALUE data)
01478 {
01479 return rb_yield_0(1, &tag);
01480 }
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519 static VALUE
01520 rb_f_catch(int argc, VALUE *argv)
01521 {
01522 VALUE tag;
01523
01524 if (argc == 0) {
01525 tag = rb_obj_alloc(rb_cObject);
01526 }
01527 else {
01528 rb_scan_args(argc, argv, "01", &tag);
01529 }
01530 return rb_catch_obj(tag, catch_i, 0);
01531 }
01532
01533 VALUE
01534 rb_catch(const char *tag, VALUE (*func)(), VALUE data)
01535 {
01536 VALUE vtag = tag ? ID2SYM(rb_intern(tag)) : rb_obj_alloc(rb_cObject);
01537 return rb_catch_obj(vtag, func, data);
01538 }
01539
01540 VALUE
01541 rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
01542 {
01543 int state;
01544 volatile VALUE val = Qnil;
01545 rb_thread_t *th = GET_THREAD();
01546 rb_control_frame_t *saved_cfp = th->cfp;
01547
01548 PUSH_TAG();
01549
01550 th->tag->tag = tag;
01551
01552 if ((state = EXEC_TAG()) == 0) {
01553
01554 val = (*func)(tag, data, 1, &tag, Qnil);
01555 }
01556 else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
01557 th->cfp = saved_cfp;
01558 val = th->tag->retval;
01559 th->errinfo = Qnil;
01560 state = 0;
01561 }
01562 POP_TAG();
01563 if (state)
01564 JUMP_TAG(state);
01565
01566 return val;
01567 }
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599 static VALUE
01600 rb_f_caller(int argc, VALUE *argv)
01601 {
01602 VALUE level;
01603 int lev;
01604
01605 rb_scan_args(argc, argv, "01", &level);
01606
01607 if (NIL_P(level))
01608 lev = 1;
01609 else
01610 lev = NUM2INT(level);
01611 if (lev < 0)
01612 rb_raise(rb_eArgError, "negative level (%d)", lev);
01613
01614 return vm_backtrace(GET_THREAD(), lev);
01615 }
01616
01617 static int
01618 print_backtrace(void *arg, VALUE file, int line, VALUE method)
01619 {
01620 FILE *fp = arg;
01621 const char *filename = NIL_P(file) ? "ruby" : RSTRING_PTR(file);
01622 if (NIL_P(method)) {
01623 fprintf(fp, "\tfrom %s:%d:in unknown method\n",
01624 filename, line);
01625 }
01626 else {
01627 fprintf(fp, "\tfrom %s:%d:in `%s'\n",
01628 filename, line, RSTRING_PTR(method));
01629 }
01630 return FALSE;
01631 }
01632
01633 void
01634 rb_backtrace(void)
01635 {
01636 vm_backtrace_each(GET_THREAD(), -1, NULL, print_backtrace, stderr);
01637 }
01638
01639 VALUE
01640 rb_make_backtrace(void)
01641 {
01642 return vm_backtrace(GET_THREAD(), -1);
01643 }
01644
01645 VALUE
01646 rb_thread_backtrace(VALUE thval)
01647 {
01648 rb_thread_t *th;
01649 GetThreadPtr(thval, th);
01650
01651 switch (th->status) {
01652 case THREAD_RUNNABLE:
01653 case THREAD_STOPPED:
01654 case THREAD_STOPPED_FOREVER:
01655 break;
01656 case THREAD_TO_KILL:
01657 case THREAD_KILLED:
01658 return Qnil;
01659 }
01660
01661 return vm_backtrace(th, 0);
01662 }
01663
01664 int
01665 rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg)
01666 {
01667 return vm_backtrace_each(GET_THREAD(), -1, NULL, iter, arg);
01668 }
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683 static VALUE
01684 rb_f_local_variables(void)
01685 {
01686 VALUE ary = rb_ary_new();
01687 rb_thread_t *th = GET_THREAD();
01688 rb_control_frame_t *cfp =
01689 vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
01690 int i;
01691
01692 while (cfp) {
01693 if (cfp->iseq) {
01694 for (i = 0; i < cfp->iseq->local_table_size; i++) {
01695 ID lid = cfp->iseq->local_table[i];
01696 if (lid) {
01697 const char *vname = rb_id2name(lid);
01698
01699 if (vname) {
01700 rb_ary_push(ary, ID2SYM(lid));
01701 }
01702 }
01703 }
01704 }
01705 if (cfp->lfp != cfp->dfp) {
01706
01707 VALUE *dfp = GC_GUARDED_PTR_REF(cfp->dfp[0]);
01708
01709 if (vm_collect_local_variables_in_heap(th, dfp, ary)) {
01710 break;
01711 }
01712 else {
01713 while (cfp->dfp != dfp) {
01714 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01715 }
01716 }
01717 }
01718 else {
01719 break;
01720 }
01721 }
01722 return ary;
01723 }
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747 VALUE
01748 rb_f_block_given_p(void)
01749 {
01750 rb_thread_t *th = GET_THREAD();
01751 rb_control_frame_t *cfp = th->cfp;
01752 cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
01753
01754 if (cfp != 0 &&
01755 (cfp->lfp[0] & 0x02) == 0 &&
01756 GC_GUARDED_PTR_REF(cfp->lfp[0])) {
01757 return Qtrue;
01758 }
01759 else {
01760 return Qfalse;
01761 }
01762 }
01763
01764 VALUE
01765 rb_current_realfilepath(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 if (cfp != 0) return cfp->iseq->filepath;
01771 return Qnil;
01772 }
01773
01774 void
01775 Init_vm_eval(void)
01776 {
01777 rb_define_global_function("eval", rb_f_eval, -1);
01778 rb_define_global_function("local_variables", rb_f_local_variables, 0);
01779 rb_define_global_function("iterator?", rb_f_block_given_p, 0);
01780 rb_define_global_function("block_given?", rb_f_block_given_p, 0);
01781
01782 rb_define_global_function("catch", rb_f_catch, -1);
01783 rb_define_global_function("throw", rb_f_throw, -1);
01784
01785 rb_define_global_function("loop", rb_f_loop, 0);
01786
01787 rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
01788 rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
01789 rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
01790
01791 #if 1
01792 rb_add_method(rb_cBasicObject, rb_intern("__send__"),
01793 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
01794 rb_add_method(rb_mKernel, rb_intern("send"),
01795 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
01796 #else
01797 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
01798 rb_define_method(rb_mKernel, "send", rb_f_send, -1);
01799 #endif
01800 rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
01801
01802 rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
01803 rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
01804 rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
01805 rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
01806
01807 rb_define_global_function("caller", rb_f_caller, -1);
01808 }
01809
01810