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