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 printf("%s\n", RSTRING_PTR(rb_iseq_disasm(iseqval)));
01018 }
01019
01020
01021 GetISeqPtr(iseqval, iseq);
01022 if (bind && iseq->local_table_size > 0) {
01023 bind->env = rb_vm_make_env_object(th, th->cfp);
01024 }
01025
01026
01027 CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
01028 result = vm_exec(th);
01029 }
01030 POP_TAG();
01031 th->mild_compile_error = mild_compile_error;
01032 th->parse_in_eval = parse_in_eval;
01033
01034 if (state) {
01035 if (state == TAG_RAISE) {
01036 VALUE errinfo = th->errinfo;
01037 if (strcmp(file, "(eval)") == 0) {
01038 VALUE mesg, errat, bt2;
01039 extern VALUE rb_get_backtrace(VALUE info);
01040 ID id_mesg;
01041
01042 CONST_ID(id_mesg, "mesg");
01043 errat = rb_get_backtrace(errinfo);
01044 mesg = rb_attr_get(errinfo, id_mesg);
01045 if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
01046 (bt2 = vm_backtrace(th, -2), RARRAY_LEN(bt2) > 0)) {
01047 if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_LEN(mesg)) {
01048 if (OBJ_FROZEN(mesg)) {
01049 VALUE m = rb_str_cat(rb_str_dup(RARRAY_PTR(errat)[0]), ": ", 2);
01050 rb_ivar_set(errinfo, id_mesg, rb_str_append(m, mesg));
01051 }
01052 else {
01053 rb_str_update(mesg, 0, 0, rb_str_new2(": "));
01054 rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]);
01055 }
01056 }
01057 RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0];
01058 }
01059 }
01060 rb_exc_raise(errinfo);
01061 }
01062 JUMP_TAG(state);
01063 }
01064 return result;
01065 }
01066
01067 static VALUE
01068 eval_string(VALUE self, VALUE src, VALUE scope, const char *file, int line)
01069 {
01070 return eval_string_with_cref(self, src, scope, 0, file, line);
01071 }
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091 VALUE
01092 rb_f_eval(int argc, VALUE *argv, VALUE self)
01093 {
01094 VALUE src, scope, vfile, vline;
01095 const char *file = "(eval)";
01096 int line = 1;
01097
01098 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
01099 if (rb_safe_level() >= 4) {
01100 StringValue(src);
01101 if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
01102 rb_raise(rb_eSecurityError,
01103 "Insecure: can't modify trusted binding");
01104 }
01105 }
01106 else {
01107 SafeStringValue(src);
01108 }
01109 if (argc >= 3) {
01110 StringValue(vfile);
01111 }
01112 if (argc >= 4) {
01113 line = NUM2INT(vline);
01114 }
01115
01116 if (!NIL_P(vfile))
01117 file = RSTRING_PTR(vfile);
01118 return eval_string(self, src, scope, file, line);
01119 }
01120
01121 VALUE
01122 rb_eval_string(const char *str)
01123 {
01124 return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1);
01125 }
01126
01127 VALUE
01128 rb_eval_string_protect(const char *str, int *state)
01129 {
01130 return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state);
01131 }
01132
01133 VALUE
01134 rb_eval_string_wrap(const char *str, int *state)
01135 {
01136 int status;
01137 rb_thread_t *th = GET_THREAD();
01138 VALUE self = th->top_self;
01139 VALUE wrapper = th->top_wrapper;
01140 VALUE val;
01141
01142 th->top_wrapper = rb_module_new();
01143 th->top_self = rb_obj_clone(rb_vm_top_self());
01144 rb_extend_object(th->top_self, th->top_wrapper);
01145
01146 val = rb_eval_string_protect(str, &status);
01147
01148 th->top_self = self;
01149 th->top_wrapper = wrapper;
01150
01151 if (state) {
01152 *state = status;
01153 }
01154 else if (status) {
01155 JUMP_TAG(status);
01156 }
01157 return val;
01158 }
01159
01160 VALUE
01161 rb_eval_cmd(VALUE cmd, VALUE arg, int level)
01162 {
01163 int state;
01164 VALUE val = Qnil;
01165 volatile int safe = rb_safe_level();
01166
01167 if (OBJ_TAINTED(cmd)) {
01168 level = 4;
01169 }
01170
01171 if (TYPE(cmd) != T_STRING) {
01172 PUSH_TAG();
01173 rb_set_safe_level_force(level);
01174 if ((state = EXEC_TAG()) == 0) {
01175 val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LENINT(arg),
01176 RARRAY_PTR(arg));
01177 }
01178 POP_TAG();
01179
01180 rb_set_safe_level_force(safe);
01181
01182 if (state)
01183 JUMP_TAG(state);
01184 return val;
01185 }
01186
01187 PUSH_TAG();
01188 if ((state = EXEC_TAG()) == 0) {
01189 val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0);
01190 }
01191 POP_TAG();
01192
01193 rb_set_safe_level_force(safe);
01194 if (state) rb_vm_jump_tag_but_local_jump(state, val);
01195 return val;
01196 }
01197
01198
01199
01200 static VALUE
01201 yield_under(VALUE under, VALUE self, VALUE values)
01202 {
01203 rb_thread_t *th = GET_THREAD();
01204 rb_block_t block, *blockptr;
01205 NODE *cref;
01206
01207 if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
01208 block = *blockptr;
01209 block.self = self;
01210 th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
01211 }
01212 cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
01213 cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
01214
01215 if (values == Qundef) {
01216 return vm_yield_with_cref(th, 1, &self, cref);
01217 }
01218 else {
01219 return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_PTR(values), cref);
01220 }
01221 }
01222
01223
01224 static VALUE
01225 eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
01226 {
01227 NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL);
01228
01229 if (rb_safe_level() >= 4) {
01230 StringValue(src);
01231 }
01232 else {
01233 SafeStringValue(src);
01234 }
01235
01236 return eval_string_with_cref(self, src, Qnil, cref, file, line);
01237 }
01238
01239 static VALUE
01240 specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
01241 {
01242 if (rb_block_given_p()) {
01243 if (argc > 0) {
01244 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
01245 }
01246 return yield_under(klass, self, Qundef);
01247 }
01248 else {
01249 const char *file = "(eval)";
01250 int line = 1;
01251
01252 if (argc == 0) {
01253 rb_raise(rb_eArgError, "block not supplied");
01254 }
01255 else {
01256 if (rb_safe_level() >= 4) {
01257 StringValue(argv[0]);
01258 }
01259 else {
01260 SafeStringValue(argv[0]);
01261 }
01262 if (argc > 3) {
01263 const char *name = rb_id2name(rb_frame_callee());
01264 rb_raise(rb_eArgError,
01265 "wrong number of arguments: %s(src) or %s{..}",
01266 name, name);
01267 }
01268 if (argc > 2)
01269 line = NUM2INT(argv[2]);
01270 if (argc > 1) {
01271 file = StringValuePtr(argv[1]);
01272 }
01273 }
01274 return eval_under(klass, self, argv[0], file, line);
01275 }
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 VALUE
01302 rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
01303 {
01304 VALUE klass;
01305
01306 if (SPECIAL_CONST_P(self)) {
01307 klass = Qnil;
01308 }
01309 else {
01310 klass = rb_singleton_class(self);
01311 }
01312 return specific_eval(argc, argv, klass, self);
01313 }
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333 VALUE
01334 rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
01335 {
01336 VALUE klass;
01337
01338 if (SPECIAL_CONST_P(self)) {
01339 klass = Qnil;
01340 }
01341 else {
01342 klass = rb_singleton_class(self);
01343 }
01344 return yield_under(klass, self, rb_ary_new4(argc, argv));
01345 }
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 VALUE
01372 rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
01373 {
01374 return specific_eval(argc, argv, mod, mod);
01375 }
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397 VALUE
01398 rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
01399 {
01400 return yield_under(mod, mod, rb_ary_new4(argc, argv));
01401 }
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415 static VALUE
01416 rb_f_throw(int argc, VALUE *argv)
01417 {
01418 VALUE tag, value;
01419
01420 rb_scan_args(argc, argv, "11", &tag, &value);
01421 rb_throw_obj(tag, value);
01422 return Qnil;
01423 }
01424
01425 void
01426 rb_throw_obj(VALUE tag, VALUE value)
01427 {
01428 rb_thread_t *th = GET_THREAD();
01429 struct rb_vm_tag *tt = th->tag;
01430
01431 while (tt) {
01432 if (tt->tag == tag) {
01433 tt->retval = value;
01434 break;
01435 }
01436 tt = tt->prev;
01437 }
01438 if (!tt) {
01439 VALUE desc = rb_inspect(tag);
01440 rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc));
01441 }
01442 rb_trap_restore_mask();
01443 th->errinfo = NEW_THROW_OBJECT(tag, 0, TAG_THROW);
01444
01445 JUMP_TAG(TAG_THROW);
01446 }
01447
01448 void
01449 rb_throw(const char *tag, VALUE val)
01450 {
01451 rb_throw_obj(ID2SYM(rb_intern(tag)), val);
01452 }
01453
01454 static VALUE
01455 catch_i(VALUE tag, VALUE data)
01456 {
01457 return rb_yield_0(1, &tag);
01458 }
01459
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 static VALUE
01498 rb_f_catch(int argc, VALUE *argv)
01499 {
01500 VALUE tag;
01501
01502 if (argc == 0) {
01503 tag = rb_obj_alloc(rb_cObject);
01504 }
01505 else {
01506 rb_scan_args(argc, argv, "01", &tag);
01507 }
01508 return rb_catch_obj(tag, catch_i, 0);
01509 }
01510
01511 VALUE
01512 rb_catch(const char *tag, VALUE (*func)(), VALUE data)
01513 {
01514 VALUE vtag = tag ? ID2SYM(rb_intern(tag)) : rb_obj_alloc(rb_cObject);
01515 return rb_catch_obj(vtag, func, data);
01516 }
01517
01518 VALUE
01519 rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
01520 {
01521 int state;
01522 volatile VALUE val = Qnil;
01523 rb_thread_t *th = GET_THREAD();
01524 rb_control_frame_t *saved_cfp = th->cfp;
01525
01526 PUSH_TAG();
01527
01528 th->tag->tag = tag;
01529
01530 if ((state = EXEC_TAG()) == 0) {
01531
01532 val = (*func)(tag, data, 1, &tag, Qnil);
01533 }
01534 else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
01535 th->cfp = saved_cfp;
01536 val = th->tag->retval;
01537 th->errinfo = Qnil;
01538 state = 0;
01539 }
01540 POP_TAG();
01541 if (state)
01542 JUMP_TAG(state);
01543
01544 return val;
01545 }
01546
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 static VALUE
01578 rb_f_caller(int argc, VALUE *argv)
01579 {
01580 VALUE level;
01581 int lev;
01582
01583 rb_scan_args(argc, argv, "01", &level);
01584
01585 if (NIL_P(level))
01586 lev = 1;
01587 else
01588 lev = NUM2INT(level);
01589 if (lev < 0)
01590 rb_raise(rb_eArgError, "negative level (%d)", lev);
01591
01592 return vm_backtrace(GET_THREAD(), lev);
01593 }
01594
01595 static int
01596 print_backtrace(void *arg, VALUE file, int line, VALUE method)
01597 {
01598 FILE *fp = arg;
01599 const char *filename = NIL_P(file) ? "ruby" : RSTRING_PTR(file);
01600 if (NIL_P(method)) {
01601 fprintf(fp, "\tfrom %s:%d:in unknown method\n",
01602 filename, line);
01603 }
01604 else {
01605 fprintf(fp, "\tfrom %s:%d:in `%s'\n",
01606 filename, line, RSTRING_PTR(method));
01607 }
01608 return FALSE;
01609 }
01610
01611 void
01612 rb_backtrace(void)
01613 {
01614 vm_backtrace_each(GET_THREAD(), -1, NULL, print_backtrace, stderr);
01615 }
01616
01617 VALUE
01618 rb_make_backtrace(void)
01619 {
01620 return vm_backtrace(GET_THREAD(), -1);
01621 }
01622
01623 VALUE
01624 rb_thread_backtrace(VALUE thval)
01625 {
01626 rb_thread_t *th;
01627 GetThreadPtr(thval, th);
01628
01629 switch (th->status) {
01630 case THREAD_RUNNABLE:
01631 case THREAD_STOPPED:
01632 case THREAD_STOPPED_FOREVER:
01633 break;
01634 case THREAD_TO_KILL:
01635 case THREAD_KILLED:
01636 return Qnil;
01637 }
01638
01639 return vm_backtrace(th, 0);
01640 }
01641
01642 int
01643 rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg)
01644 {
01645 return vm_backtrace_each(GET_THREAD(), -1, NULL, iter, arg);
01646 }
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661 static VALUE
01662 rb_f_local_variables(void)
01663 {
01664 VALUE ary = rb_ary_new();
01665 rb_thread_t *th = GET_THREAD();
01666 rb_control_frame_t *cfp =
01667 vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
01668 int i;
01669
01670 while (cfp) {
01671 if (cfp->iseq) {
01672 for (i = 0; i < cfp->iseq->local_table_size; i++) {
01673 ID lid = cfp->iseq->local_table[i];
01674 if (lid) {
01675 const char *vname = rb_id2name(lid);
01676
01677 if (vname) {
01678 rb_ary_push(ary, ID2SYM(lid));
01679 }
01680 }
01681 }
01682 }
01683 if (cfp->lfp != cfp->dfp) {
01684
01685 VALUE *dfp = GC_GUARDED_PTR_REF(cfp->dfp[0]);
01686
01687 if (vm_collect_local_variables_in_heap(th, dfp, ary)) {
01688 break;
01689 }
01690 else {
01691 while (cfp->dfp != dfp) {
01692 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01693 }
01694 }
01695 }
01696 else {
01697 break;
01698 }
01699 }
01700 return ary;
01701 }
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725 VALUE
01726 rb_f_block_given_p(void)
01727 {
01728 rb_thread_t *th = GET_THREAD();
01729 rb_control_frame_t *cfp = th->cfp;
01730 cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
01731
01732 if (cfp != 0 &&
01733 (cfp->lfp[0] & 0x02) == 0 &&
01734 GC_GUARDED_PTR_REF(cfp->lfp[0])) {
01735 return Qtrue;
01736 }
01737 else {
01738 return Qfalse;
01739 }
01740 }
01741
01742 VALUE
01743 rb_current_realfilepath(void)
01744 {
01745 rb_thread_t *th = GET_THREAD();
01746 rb_control_frame_t *cfp = th->cfp;
01747 cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
01748 if (cfp != 0) return cfp->iseq->filepath;
01749 return Qnil;
01750 }
01751
01752 void
01753 Init_vm_eval(void)
01754 {
01755 rb_define_global_function("eval", rb_f_eval, -1);
01756 rb_define_global_function("local_variables", rb_f_local_variables, 0);
01757 rb_define_global_function("iterator?", rb_f_block_given_p, 0);
01758 rb_define_global_function("block_given?", rb_f_block_given_p, 0);
01759
01760 rb_define_global_function("catch", rb_f_catch, -1);
01761 rb_define_global_function("throw", rb_f_throw, -1);
01762
01763 rb_define_global_function("loop", rb_f_loop, 0);
01764
01765 rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
01766 rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
01767 rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
01768
01769 #if 1
01770 rb_add_method(rb_cBasicObject, rb_intern("__send__"),
01771 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
01772 rb_add_method(rb_mKernel, rb_intern("send"),
01773 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, 0);
01774 #else
01775 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
01776 rb_define_method(rb_mKernel, "send", rb_f_send, -1);
01777 #endif
01778 rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
01779
01780 rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
01781 rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
01782 rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
01783 rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
01784
01785 rb_define_global_function("caller", rb_f_caller, -1);
01786 }
01787
01788