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