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