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