00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "eval_intern.h"
00015 #include "iseq.h"
00016 #include "gc.h"
00017 #include "ruby/vm.h"
00018 #include "ruby/encoding.h"
00019 #include "internal.h"
00020 #include "vm_core.h"
00021 #include "probes_helper.h"
00022
00023 NORETURN(void rb_raise_jump(VALUE));
00024
00025 NODE *rb_vm_get_cref(const rb_iseq_t *, const VALUE *);
00026
00027 VALUE rb_eLocalJumpError;
00028 VALUE rb_eSysStackError;
00029
00030 #define exception_error GET_VM()->special_exceptions[ruby_error_reenter]
00031
00032 #include "eval_error.c"
00033 #include "eval_jump.c"
00034
00035 #define CLASS_OR_MODULE_P(obj) \
00036 (!SPECIAL_CONST_P(obj) && \
00037 (BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE))
00038
00039
00040
00041
00042
00043 int
00044 ruby_setup(void)
00045 {
00046 static int initialized = 0;
00047 int state;
00048
00049 if (initialized)
00050 return 0;
00051 initialized = 1;
00052
00053 ruby_init_stack((void *)&state);
00054 Init_BareVM();
00055 Init_heap();
00056
00057 PUSH_TAG();
00058 if ((state = EXEC_TAG()) == 0) {
00059 rb_call_inits();
00060 ruby_prog_init();
00061 GET_VM()->running = 1;
00062 }
00063 POP_TAG();
00064
00065 return state;
00066 }
00067
00068
00069
00070
00071
00072 void
00073 ruby_init(void)
00074 {
00075 int state = ruby_setup();
00076 if (state) {
00077 error_print();
00078 exit(EXIT_FAILURE);
00079 }
00080 }
00081
00092 void *
00093 ruby_options(int argc, char **argv)
00094 {
00095 int state;
00096 void *volatile iseq = 0;
00097
00098 ruby_init_stack((void *)&iseq);
00099 PUSH_TAG();
00100 if ((state = EXEC_TAG()) == 0) {
00101 SAVE_ROOT_JMPBUF(GET_THREAD(), iseq = ruby_process_options(argc, argv));
00102 }
00103 else {
00104 rb_clear_trace_func();
00105 state = error_handle(state);
00106 iseq = (void *)INT2FIX(state);
00107 }
00108 POP_TAG();
00109 return iseq;
00110 }
00111
00112 static void
00113 ruby_finalize_0(void)
00114 {
00115 PUSH_TAG();
00116 if (EXEC_TAG() == 0) {
00117 rb_trap_exit();
00118 }
00119 POP_TAG();
00120 rb_exec_end_proc();
00121 rb_clear_trace_func();
00122 }
00123
00124 static void
00125 ruby_finalize_1(void)
00126 {
00127 ruby_sig_finalize();
00128 GET_THREAD()->errinfo = Qnil;
00129 rb_gc_call_finalizer_at_exit();
00130 }
00131
00139 void
00140 ruby_finalize(void)
00141 {
00142 ruby_finalize_0();
00143 ruby_finalize_1();
00144 }
00145
00156 int
00157 ruby_cleanup(volatile int ex)
00158 {
00159 int state;
00160 volatile VALUE errs[2];
00161 rb_thread_t *th = GET_THREAD();
00162 int nerr;
00163
00164 rb_threadptr_interrupt(th);
00165 rb_threadptr_check_signal(th);
00166 PUSH_TAG();
00167 if ((state = EXEC_TAG()) == 0) {
00168 SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(th); });
00169 }
00170 POP_TAG();
00171
00172 errs[1] = th->errinfo;
00173 th->safe_level = 0;
00174 ruby_init_stack(&errs[STACK_UPPER(errs, 0, 1)]);
00175
00176 PUSH_TAG();
00177 if ((state = EXEC_TAG()) == 0) {
00178 SAVE_ROOT_JMPBUF(th, ruby_finalize_0());
00179 }
00180 POP_TAG();
00181
00182
00183 th->status = THREAD_KILLED;
00184
00185 errs[0] = th->errinfo;
00186 PUSH_TAG();
00187 if ((state = EXEC_TAG()) == 0) {
00188 SAVE_ROOT_JMPBUF(th, rb_thread_terminate_all());
00189 }
00190 else if (ex == 0) {
00191 ex = state;
00192 }
00193 th->errinfo = errs[1];
00194 ex = error_handle(ex);
00195
00196 #if EXIT_SUCCESS != 0 || EXIT_FAILURE != 1
00197 switch (ex) {
00198 #if EXIT_SUCCESS != 0
00199 case 0: ex = EXIT_SUCCESS; break;
00200 #endif
00201 #if EXIT_FAILURE != 1
00202 case 1: ex = EXIT_FAILURE; break;
00203 #endif
00204 }
00205 #endif
00206
00207 state = 0;
00208 for (nerr = 0; nerr < numberof(errs); ++nerr) {
00209 VALUE err = errs[nerr];
00210
00211 if (!RTEST(err)) continue;
00212
00213
00214 if (RB_TYPE_P(err, T_NODE)) continue;
00215
00216 if (rb_obj_is_kind_of(err, rb_eSystemExit)) {
00217 ex = sysexit_status(err);
00218 break;
00219 }
00220 else if (rb_obj_is_kind_of(err, rb_eSignal)) {
00221 VALUE sig = rb_iv_get(err, "signo");
00222 state = NUM2INT(sig);
00223 break;
00224 }
00225 else if (ex == EXIT_SUCCESS) {
00226 ex = EXIT_FAILURE;
00227 }
00228 }
00229
00230 ruby_finalize_1();
00231
00232
00233 rb_threadptr_unlock_all_locking_mutexes(GET_THREAD());
00234 POP_TAG();
00235 rb_thread_stop_timer_thread(1);
00236 ruby_vm_destruct(GET_VM());
00237 if (state) ruby_default_signal(state);
00238
00239 return ex;
00240 }
00241
00242 static int
00243 ruby_exec_internal(void *n)
00244 {
00245 volatile int state;
00246 VALUE iseq = (VALUE)n;
00247 rb_thread_t *th = GET_THREAD();
00248
00249 if (!n) return 0;
00250
00251 PUSH_TAG();
00252 if ((state = EXEC_TAG()) == 0) {
00253 SAVE_ROOT_JMPBUF(th, {
00254 th->base_block = 0;
00255 rb_iseq_eval_main(iseq);
00256 });
00257 }
00258 POP_TAG();
00259 return state;
00260 }
00261
00263 void
00264 ruby_stop(int ex)
00265 {
00266 exit(ruby_cleanup(ex));
00267 }
00268
00281 int
00282 ruby_executable_node(void *n, int *status)
00283 {
00284 VALUE v = (VALUE)n;
00285 int s;
00286
00287 switch (v) {
00288 case Qtrue: s = EXIT_SUCCESS; break;
00289 case Qfalse: s = EXIT_FAILURE; break;
00290 default:
00291 if (!FIXNUM_P(v)) return TRUE;
00292 s = FIX2INT(v);
00293 }
00294 if (status) *status = s;
00295 return FALSE;
00296 }
00297
00302 int
00303 ruby_run_node(void *n)
00304 {
00305 int status;
00306 if (!ruby_executable_node(n, &status)) {
00307 ruby_cleanup(0);
00308 return status;
00309 }
00310 return ruby_cleanup(ruby_exec_node(n));
00311 }
00312
00314 int
00315 ruby_exec_node(void *n)
00316 {
00317 ruby_init_stack((void *)&n);
00318 return ruby_exec_internal(n);
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 static VALUE
00337 rb_mod_nesting(void)
00338 {
00339 VALUE ary = rb_ary_new();
00340 const NODE *cref = rb_vm_cref();
00341
00342 while (cref && cref->nd_next) {
00343 VALUE klass = cref->nd_clss;
00344 if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
00345 !NIL_P(klass)) {
00346 rb_ary_push(ary, klass);
00347 }
00348 cref = cref->nd_next;
00349 }
00350 return ary;
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 static VALUE
00376 rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
00377 {
00378 const NODE *cref = rb_vm_cref();
00379 VALUE klass;
00380 VALUE cbase = 0;
00381 void *data = 0;
00382
00383 if (argc > 0 || mod != rb_cModule) {
00384 return rb_mod_constants(argc, argv, mod);
00385 }
00386
00387 while (cref) {
00388 klass = cref->nd_clss;
00389 if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
00390 !NIL_P(klass)) {
00391 data = rb_mod_const_at(cref->nd_clss, data);
00392 if (!cbase) {
00393 cbase = klass;
00394 }
00395 }
00396 cref = cref->nd_next;
00397 }
00398
00399 if (cbase) {
00400 data = rb_mod_const_of(cbase, data);
00401 }
00402 return rb_const_list(data);
00403 }
00404
00405 void
00406 rb_frozen_class_p(VALUE klass)
00407 {
00408 if (SPECIAL_CONST_P(klass)) {
00409 noclass:
00410 Check_Type(klass, T_CLASS);
00411 }
00412 if (OBJ_FROZEN(klass)) {
00413 const char *desc;
00414
00415 if (FL_TEST(klass, FL_SINGLETON))
00416 desc = "object";
00417 else {
00418 switch (BUILTIN_TYPE(klass)) {
00419 case T_MODULE:
00420 case T_ICLASS:
00421 desc = "module";
00422 break;
00423 case T_CLASS:
00424 desc = "class";
00425 break;
00426 default:
00427 goto noclass;
00428 }
00429 }
00430 rb_error_frozen(desc);
00431 }
00432 }
00433
00434 NORETURN(static void rb_longjmp(int, volatile VALUE));
00435 static VALUE get_errinfo(void);
00436 static VALUE get_thread_errinfo(rb_thread_t *th);
00437
00438 static VALUE
00439 exc_setup_cause(VALUE exc, VALUE cause)
00440 {
00441 ID id_cause;
00442 CONST_ID(id_cause, "cause");
00443
00444 #if SUPPORT_JOKE
00445 if (NIL_P(cause)) {
00446 ID id_true_cause;
00447 CONST_ID(id_true_cause, "true_cause");
00448
00449 cause = rb_attr_get(rb_eFatal, id_true_cause);
00450 if (NIL_P(cause)) {
00451 cause = rb_exc_new_cstr(rb_eFatal, "because using such Ruby");
00452 rb_ivar_set(cause, id_cause, INT2FIX(42));
00453 OBJ_FREEZE(cause);
00454 rb_ivar_set(rb_eFatal, id_true_cause, cause);
00455 }
00456 }
00457 #endif
00458 if (!NIL_P(cause) && cause != exc) {
00459 rb_ivar_set(exc, id_cause, cause);
00460 }
00461 return exc;
00462 }
00463
00464 static void
00465 setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg)
00466 {
00467 VALUE at;
00468 VALUE e;
00469 const char *file;
00470 volatile int line = 0;
00471
00472 if (NIL_P(mesg)) {
00473 mesg = th->errinfo;
00474 if (INTERNAL_EXCEPTION_P(mesg)) JUMP_TAG(TAG_FATAL);
00475 }
00476 if (NIL_P(mesg)) {
00477 mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
00478 }
00479 exc_setup_cause(mesg, get_thread_errinfo(th));
00480
00481 file = rb_sourcefile();
00482 if (file) line = rb_sourceline();
00483 if (file && !NIL_P(mesg)) {
00484 if (mesg == sysstack_error) {
00485 at = rb_enc_sprintf(rb_usascii_encoding(), "%s:%d", file, line);
00486 at = rb_ary_new3(1, at);
00487 rb_iv_set(mesg, "bt", at);
00488 }
00489 else {
00490 at = get_backtrace(mesg);
00491 if (NIL_P(at)) {
00492 at = rb_vm_backtrace_object();
00493 if (OBJ_FROZEN(mesg)) {
00494 mesg = rb_obj_dup(mesg);
00495 }
00496 rb_iv_set(mesg, "bt_locations", at);
00497 set_backtrace(mesg, at);
00498 }
00499 }
00500 }
00501
00502 if (!NIL_P(mesg)) {
00503 th->errinfo = mesg;
00504 }
00505
00506 if (RTEST(ruby_debug) && !NIL_P(e = th->errinfo) &&
00507 !rb_obj_is_kind_of(e, rb_eSystemExit)) {
00508 int status;
00509
00510 mesg = e;
00511 PUSH_TAG();
00512 if ((status = EXEC_TAG()) == 0) {
00513 th->errinfo = Qnil;
00514 e = rb_obj_as_string(mesg);
00515 th->errinfo = mesg;
00516 if (file && line) {
00517 warn_printf("Exception `%s' at %s:%d - %"PRIsVALUE"\n",
00518 rb_obj_classname(th->errinfo), file, line, e);
00519 }
00520 else if (file) {
00521 warn_printf("Exception `%s' at %s - %"PRIsVALUE"\n",
00522 rb_obj_classname(th->errinfo), file, e);
00523 }
00524 else {
00525 warn_printf("Exception `%s' - %"PRIsVALUE"\n",
00526 rb_obj_classname(th->errinfo), e);
00527 }
00528 }
00529 POP_TAG();
00530 if (status == TAG_FATAL && th->errinfo == exception_error) {
00531 th->errinfo = mesg;
00532 }
00533 else if (status) {
00534 rb_threadptr_reset_raised(th);
00535 JUMP_TAG(status);
00536 }
00537 }
00538
00539 if (rb_threadptr_set_raised(th)) {
00540 th->errinfo = exception_error;
00541 rb_threadptr_reset_raised(th);
00542 JUMP_TAG(TAG_FATAL);
00543 }
00544
00545 if (tag != TAG_FATAL) {
00546 if (RUBY_DTRACE_RAISE_ENABLED()) {
00547 RUBY_DTRACE_RAISE(rb_obj_classname(th->errinfo),
00548 rb_sourcefile(),
00549 rb_sourceline());
00550 }
00551 EXEC_EVENT_HOOK(th, RUBY_EVENT_RAISE, th->cfp->self, 0, 0, mesg);
00552 }
00553 }
00554
00555 static void
00556 rb_longjmp(int tag, volatile VALUE mesg)
00557 {
00558 rb_thread_t *th = GET_THREAD();
00559 setup_exception(th, tag, mesg);
00560 rb_thread_raised_clear(th);
00561 JUMP_TAG(tag);
00562 }
00563
00564 static VALUE make_exception(int argc, VALUE *argv, int isstr);
00565
00566 void
00567 rb_exc_raise(VALUE mesg)
00568 {
00569 if (!NIL_P(mesg)) {
00570 mesg = make_exception(1, &mesg, FALSE);
00571 }
00572 rb_longjmp(TAG_RAISE, mesg);
00573 }
00574
00575 void
00576 rb_exc_fatal(VALUE mesg)
00577 {
00578 if (!NIL_P(mesg)) {
00579 mesg = make_exception(1, &mesg, FALSE);
00580 }
00581 rb_longjmp(TAG_FATAL, mesg);
00582 }
00583
00584 void
00585 rb_interrupt(void)
00586 {
00587 rb_raise(rb_eInterrupt, "%s", "");
00588 }
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 static VALUE
00615 rb_f_raise(int argc, VALUE *argv)
00616 {
00617 VALUE err;
00618 if (argc == 0) {
00619 err = get_errinfo();
00620 if (!NIL_P(err)) {
00621 argc = 1;
00622 argv = &err;
00623 }
00624 }
00625 rb_raise_jump(rb_make_exception(argc, argv));
00626
00627 UNREACHABLE;
00628 }
00629
00630 static VALUE
00631 make_exception(int argc, VALUE *argv, int isstr)
00632 {
00633 VALUE mesg, exc;
00634 ID exception;
00635 int n;
00636
00637 mesg = Qnil;
00638 switch (argc) {
00639 case 0:
00640 break;
00641 case 1:
00642 exc = argv[0];
00643 if (NIL_P(exc))
00644 break;
00645 if (isstr) {
00646 mesg = rb_check_string_type(exc);
00647 if (!NIL_P(mesg)) {
00648 mesg = rb_exc_new3(rb_eRuntimeError, mesg);
00649 break;
00650 }
00651 }
00652 n = 0;
00653 goto exception_call;
00654
00655 case 2:
00656 case 3:
00657 exc = argv[0];
00658 n = 1;
00659 exception_call:
00660 if (exc == sysstack_error) return exc;
00661 CONST_ID(exception, "exception");
00662 mesg = rb_check_funcall(exc, exception, n, argv+1);
00663 if (mesg == Qundef) {
00664 rb_raise(rb_eTypeError, "exception class/object expected");
00665 }
00666 break;
00667 default:
00668 rb_check_arity(argc, 0, 3);
00669 break;
00670 }
00671 if (argc > 0) {
00672 if (!rb_obj_is_kind_of(mesg, rb_eException))
00673 rb_raise(rb_eTypeError, "exception object expected");
00674 if (argc > 2)
00675 set_backtrace(mesg, argv[2]);
00676 }
00677
00678 return mesg;
00679 }
00680
00681 VALUE
00682 rb_make_exception(int argc, VALUE *argv)
00683 {
00684 return make_exception(argc, argv, TRUE);
00685 }
00686
00687 void
00688 rb_raise_jump(VALUE mesg)
00689 {
00690 rb_thread_t *th = GET_THREAD();
00691 rb_control_frame_t *cfp = th->cfp;
00692 VALUE klass = cfp->me->klass;
00693 VALUE self = cfp->self;
00694 ID mid = cfp->me->called_id;
00695
00696 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00697 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, self, mid, klass, Qnil);
00698
00699 setup_exception(th, TAG_RAISE, mesg);
00700
00701 rb_thread_raised_clear(th);
00702 JUMP_TAG(TAG_RAISE);
00703 }
00704
00705 void
00706 rb_jump_tag(int tag)
00707 {
00708 JUMP_TAG(tag);
00709 }
00710
00711 int
00712 rb_block_given_p(void)
00713 {
00714 rb_thread_t *th = GET_THREAD();
00715
00716 if (rb_vm_control_frame_block_ptr(th->cfp)) {
00717 return TRUE;
00718 }
00719 else {
00720 return FALSE;
00721 }
00722 }
00723
00724 int
00725 rb_iterator_p(void)
00726 {
00727 return rb_block_given_p();
00728 }
00729
00730 VALUE rb_eThreadError;
00731
00732 void
00733 rb_need_block(void)
00734 {
00735 if (!rb_block_given_p()) {
00736 rb_vm_localjump_error("no block given", Qnil, 0);
00737 }
00738 }
00739
00740 VALUE
00741 rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1,
00742 VALUE (* r_proc) (ANYARGS), VALUE data2, ...)
00743 {
00744 int state;
00745 rb_thread_t *th = GET_THREAD();
00746 rb_control_frame_t *cfp = th->cfp;
00747 volatile VALUE result = Qfalse;
00748 volatile VALUE e_info = th->errinfo;
00749 va_list args;
00750
00751 TH_PUSH_TAG(th);
00752 if ((state = TH_EXEC_TAG()) == 0) {
00753 retry_entry:
00754 result = (*b_proc) (data1);
00755 }
00756 else if (result) {
00757
00758 if (state == TAG_RETRY) {
00759 state = 0;
00760 th->errinfo = Qnil;
00761 result = Qfalse;
00762 goto retry_entry;
00763 }
00764 }
00765 else {
00766 rb_vm_rewind_cfp(th, cfp);
00767
00768 if (state == TAG_RAISE) {
00769 int handle = FALSE;
00770 VALUE eclass;
00771
00772 va_init_list(args, data2);
00773 while ((eclass = va_arg(args, VALUE)) != 0) {
00774 if (rb_obj_is_kind_of(th->errinfo, eclass)) {
00775 handle = TRUE;
00776 break;
00777 }
00778 }
00779 va_end(args);
00780
00781 if (handle) {
00782 result = Qnil;
00783 state = 0;
00784 if (r_proc) {
00785 result = (*r_proc) (data2, th->errinfo);
00786 }
00787 th->errinfo = e_info;
00788 }
00789 }
00790 }
00791 TH_POP_TAG();
00792 if (state)
00793 JUMP_TAG(state);
00794
00795 return result;
00796 }
00797
00798 VALUE
00799 rb_rescue(VALUE (* b_proc)(ANYARGS), VALUE data1,
00800 VALUE (* r_proc)(ANYARGS), VALUE data2)
00801 {
00802 return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError,
00803 (VALUE)0);
00804 }
00805
00806 VALUE
00807 rb_protect(VALUE (* proc) (VALUE), VALUE data, int * state)
00808 {
00809 volatile VALUE result = Qnil;
00810 volatile int status;
00811 rb_thread_t *th = GET_THREAD();
00812 rb_control_frame_t *cfp = th->cfp;
00813 struct rb_vm_protect_tag protect_tag;
00814 rb_jmpbuf_t org_jmpbuf;
00815
00816 protect_tag.prev = th->protect_tag;
00817
00818 TH_PUSH_TAG(th);
00819 th->protect_tag = &protect_tag;
00820 MEMCPY(&org_jmpbuf, &(th)->root_jmpbuf, rb_jmpbuf_t, 1);
00821 if ((status = TH_EXEC_TAG()) == 0) {
00822 SAVE_ROOT_JMPBUF(th, result = (*proc) (data));
00823 }
00824 else {
00825 rb_vm_rewind_cfp(th, cfp);
00826 }
00827 MEMCPY(&(th)->root_jmpbuf, &org_jmpbuf, rb_jmpbuf_t, 1);
00828 th->protect_tag = protect_tag.prev;
00829 TH_POP_TAG();
00830
00831 if (state) {
00832 *state = status;
00833 }
00834
00835 return result;
00836 }
00837
00838 VALUE
00839 rb_ensure(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*e_proc)(ANYARGS), VALUE data2)
00840 {
00841 int state;
00842 volatile VALUE result = Qnil;
00843 volatile VALUE errinfo;
00844 rb_thread_t *const th = GET_THREAD();
00845 rb_ensure_list_t ensure_list;
00846 ensure_list.entry.marker = 0;
00847 ensure_list.entry.e_proc = e_proc;
00848 ensure_list.entry.data2 = data2;
00849 ensure_list.next = th->ensure_list;
00850 th->ensure_list = &ensure_list;
00851 PUSH_TAG();
00852 if ((state = EXEC_TAG()) == 0) {
00853 result = (*b_proc) (data1);
00854 }
00855 POP_TAG();
00856
00857
00858 errinfo = th->errinfo;
00859 th->ensure_list=ensure_list.next;
00860 (*ensure_list.entry.e_proc)(ensure_list.entry.data2);
00861 th->errinfo = errinfo;
00862 if (state)
00863 JUMP_TAG(state);
00864 return result;
00865 }
00866
00867 static const rb_method_entry_t *
00868 method_entry_of_iseq(rb_control_frame_t *cfp, rb_iseq_t *iseq)
00869 {
00870 rb_thread_t *th = GET_THREAD();
00871 rb_control_frame_t *cfp_limit;
00872
00873 cfp_limit = (rb_control_frame_t *)(th->stack + th->stack_size);
00874 while (cfp_limit > cfp) {
00875 if (cfp->iseq == iseq)
00876 return cfp->me;
00877 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
00878 }
00879 return 0;
00880 }
00881
00882 static ID
00883 frame_func_id(rb_control_frame_t *cfp)
00884 {
00885 const rb_method_entry_t *me_local;
00886 rb_iseq_t *iseq = cfp->iseq;
00887 if (cfp->me) {
00888 return cfp->me->def->original_id;
00889 }
00890 while (iseq) {
00891 if (RUBY_VM_IFUNC_P(iseq)) {
00892 NODE *ifunc = (NODE *)iseq;
00893 if (ifunc->nd_aid) return ifunc->nd_aid;
00894 return idIFUNC;
00895 }
00896 me_local = method_entry_of_iseq(cfp, iseq);
00897 if (me_local) {
00898 cfp->me = me_local;
00899 return me_local->def->original_id;
00900 }
00901 if (iseq->defined_method_id) {
00902 return iseq->defined_method_id;
00903 }
00904 if (iseq->local_iseq == iseq) {
00905 break;
00906 }
00907 iseq = iseq->parent_iseq;
00908 }
00909 return 0;
00910 }
00911
00912 static ID
00913 frame_called_id(rb_control_frame_t *cfp)
00914 {
00915 const rb_method_entry_t *me_local;
00916 rb_iseq_t *iseq = cfp->iseq;
00917 if (cfp->me) {
00918 return cfp->me->called_id;
00919 }
00920 while (iseq) {
00921 if (RUBY_VM_IFUNC_P(iseq)) {
00922 NODE *ifunc = (NODE *)iseq;
00923 if (ifunc->nd_aid) return ifunc->nd_aid;
00924 return idIFUNC;
00925 }
00926 me_local = method_entry_of_iseq(cfp, iseq);
00927 if (me_local) {
00928 cfp->me = me_local;
00929 return me_local->called_id;
00930 }
00931 if (iseq->defined_method_id) {
00932 return iseq->defined_method_id;
00933 }
00934 if (iseq->local_iseq == iseq) {
00935 break;
00936 }
00937 iseq = iseq->parent_iseq;
00938 }
00939 return 0;
00940 }
00941
00942 ID
00943 rb_frame_this_func(void)
00944 {
00945 return frame_func_id(GET_THREAD()->cfp);
00946 }
00947
00948 ID
00949 rb_frame_callee(void)
00950 {
00951 return frame_called_id(GET_THREAD()->cfp);
00952 }
00953
00954 static rb_control_frame_t *
00955 previous_frame(rb_thread_t *th)
00956 {
00957 rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00958
00959 if ((void *)(th->stack + th->stack_size) == (void *)(prev_cfp)) {
00960 return 0;
00961 }
00962 return prev_cfp;
00963 }
00964
00965 static ID
00966 prev_frame_callee(void)
00967 {
00968 rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());
00969 if (!prev_cfp) return 0;
00970 return frame_called_id(prev_cfp);
00971 }
00972
00973 static ID
00974 prev_frame_func(void)
00975 {
00976 rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());
00977 if (!prev_cfp) return 0;
00978 return frame_func_id(prev_cfp);
00979 }
00980
00981 ID
00982 rb_frame_last_func(void)
00983 {
00984 rb_thread_t *th = GET_THREAD();
00985 rb_control_frame_t *cfp = th->cfp;
00986 ID mid;
00987
00988 while (!(mid = frame_func_id(cfp)) &&
00989 (cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp),
00990 !RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)));
00991 return mid;
00992 }
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006 static VALUE
01007 rb_mod_append_features(VALUE module, VALUE include)
01008 {
01009 if (!CLASS_OR_MODULE_P(include)) {
01010 Check_Type(include, T_CLASS);
01011 }
01012 rb_include_module(include, module);
01013
01014 return module;
01015 }
01016
01017
01018
01019
01020
01021
01022
01023
01024 static VALUE
01025 rb_mod_include(int argc, VALUE *argv, VALUE module)
01026 {
01027 int i;
01028 ID id_append_features, id_included;
01029
01030 CONST_ID(id_append_features, "append_features");
01031 CONST_ID(id_included, "included");
01032
01033 for (i = 0; i < argc; i++)
01034 Check_Type(argv[i], T_MODULE);
01035 while (argc--) {
01036 rb_funcall(argv[argc], id_append_features, 1, module);
01037 rb_funcall(argv[argc], id_included, 1, module);
01038 }
01039 return module;
01040 }
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054 static VALUE
01055 rb_mod_prepend_features(VALUE module, VALUE prepend)
01056 {
01057 if (!CLASS_OR_MODULE_P(prepend)) {
01058 Check_Type(prepend, T_CLASS);
01059 }
01060 rb_prepend_module(prepend, module);
01061
01062 return module;
01063 }
01064
01065
01066
01067
01068
01069
01070
01071
01072 static VALUE
01073 rb_mod_prepend(int argc, VALUE *argv, VALUE module)
01074 {
01075 int i;
01076 ID id_prepend_features, id_prepended;
01077
01078 CONST_ID(id_prepend_features, "prepend_features");
01079 CONST_ID(id_prepended, "prepended");
01080 for (i = 0; i < argc; i++)
01081 Check_Type(argv[i], T_MODULE);
01082 while (argc--) {
01083 rb_funcall(argv[argc], id_prepend_features, 1, module);
01084 rb_funcall(argv[argc], id_prepended, 1, module);
01085 }
01086 return module;
01087 }
01088
01089 static VALUE
01090 hidden_identity_hash_new()
01091 {
01092 VALUE hash = rb_hash_new();
01093
01094 rb_funcall(hash, rb_intern("compare_by_identity"), 0);
01095 RBASIC_CLEAR_CLASS(hash);
01096 return hash;
01097 }
01098
01099 void
01100 rb_using_refinement(NODE *cref, VALUE klass, VALUE module)
01101 {
01102 VALUE iclass, c, superclass = klass;
01103
01104 Check_Type(klass, T_CLASS);
01105 Check_Type(module, T_MODULE);
01106 if (NIL_P(cref->nd_refinements)) {
01107 RB_OBJ_WRITE(cref, &cref->nd_refinements, hidden_identity_hash_new());
01108 }
01109 else {
01110 if (cref->flags & NODE_FL_CREF_OMOD_SHARED) {
01111 RB_OBJ_WRITE(cref, &cref->nd_refinements, rb_hash_dup(cref->nd_refinements));
01112 cref->flags &= ~NODE_FL_CREF_OMOD_SHARED;
01113 }
01114 if (!NIL_P(c = rb_hash_lookup(cref->nd_refinements, klass))) {
01115 superclass = c;
01116 while (c && RB_TYPE_P(c, T_ICLASS)) {
01117 if (RBASIC(c)->klass == module) {
01118
01119 return;
01120 }
01121 c = RCLASS_SUPER(c);
01122 }
01123 }
01124 }
01125 FL_SET(module, RMODULE_IS_OVERLAID);
01126 c = iclass = rb_include_class_new(module, superclass);
01127 RCLASS_REFINED_CLASS(c) = klass;
01128
01129 RCLASS_M_TBL_WRAPPER(OBJ_WB_UNPROTECT(c)) =
01130 RCLASS_M_TBL_WRAPPER(OBJ_WB_UNPROTECT(module));
01131
01132 module = RCLASS_SUPER(module);
01133 while (module && module != klass) {
01134 FL_SET(module, RMODULE_IS_OVERLAID);
01135 c = RCLASS_SET_SUPER(c, rb_include_class_new(module, RCLASS_SUPER(c)));
01136 RCLASS_REFINED_CLASS(c) = klass;
01137 module = RCLASS_SUPER(module);
01138 }
01139 rb_hash_aset(cref->nd_refinements, klass, iclass);
01140 }
01141
01142 static int
01143 using_refinement(VALUE klass, VALUE module, VALUE arg)
01144 {
01145 NODE *cref = (NODE *) arg;
01146
01147 rb_using_refinement(cref, klass, module);
01148 return ST_CONTINUE;
01149 }
01150
01151 static void
01152 using_module_recursive(NODE *cref, VALUE klass)
01153 {
01154 ID id_refinements;
01155 VALUE super, module, refinements;
01156
01157 super = RCLASS_SUPER(klass);
01158 if (super) {
01159 using_module_recursive(cref, super);
01160 }
01161 switch (BUILTIN_TYPE(klass)) {
01162 case T_MODULE:
01163 module = klass;
01164 break;
01165
01166 case T_ICLASS:
01167 module = RBASIC(klass)->klass;
01168 break;
01169
01170 default:
01171 rb_raise(rb_eTypeError, "wrong argument type %s (expected Module)",
01172 rb_obj_classname(klass));
01173 break;
01174 }
01175 CONST_ID(id_refinements, "__refinements__");
01176 refinements = rb_attr_get(module, id_refinements);
01177 if (NIL_P(refinements)) return;
01178 rb_hash_foreach(refinements, using_refinement, (VALUE) cref);
01179 }
01180
01181 void
01182 rb_using_module(NODE *cref, VALUE module)
01183 {
01184 Check_Type(module, T_MODULE);
01185 using_module_recursive(cref, module);
01186 rb_clear_method_cache_by_class(rb_cObject);
01187 }
01188
01189 VALUE
01190 rb_refinement_module_get_refined_class(VALUE module)
01191 {
01192 ID id_refined_class;
01193
01194 CONST_ID(id_refined_class, "__refined_class__");
01195 return rb_attr_get(module, id_refined_class);
01196 }
01197
01198 static void
01199 add_activated_refinement(VALUE activated_refinements,
01200 VALUE klass, VALUE refinement)
01201 {
01202 VALUE iclass, c, superclass = klass;
01203
01204 if (!NIL_P(c = rb_hash_lookup(activated_refinements, klass))) {
01205 superclass = c;
01206 while (c && RB_TYPE_P(c, T_ICLASS)) {
01207 if (RBASIC(c)->klass == refinement) {
01208
01209 return;
01210 }
01211 c = RCLASS_SUPER(c);
01212 }
01213 }
01214 FL_SET(refinement, RMODULE_IS_OVERLAID);
01215 c = iclass = rb_include_class_new(refinement, superclass);
01216 RCLASS_REFINED_CLASS(c) = klass;
01217 refinement = RCLASS_SUPER(refinement);
01218 while (refinement) {
01219 FL_SET(refinement, RMODULE_IS_OVERLAID);
01220 c = RCLASS_SET_SUPER(c, rb_include_class_new(refinement, RCLASS_SUPER(c)));
01221 RCLASS_REFINED_CLASS(c) = klass;
01222 refinement = RCLASS_SUPER(refinement);
01223 }
01224 rb_hash_aset(activated_refinements, klass, iclass);
01225 }
01226
01227 VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements);
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238 static VALUE
01239 rb_mod_refine(VALUE module, VALUE klass)
01240 {
01241 VALUE refinement;
01242 ID id_refinements, id_activated_refinements,
01243 id_refined_class, id_defined_at;
01244 VALUE refinements, activated_refinements;
01245 rb_thread_t *th = GET_THREAD();
01246 rb_block_t *block = rb_vm_control_frame_block_ptr(th->cfp);
01247
01248 if (!block) {
01249 rb_raise(rb_eArgError, "no block given");
01250 }
01251 if (block->proc) {
01252 rb_raise(rb_eArgError,
01253 "can't pass a Proc as a block to Module#refine");
01254 }
01255 Check_Type(klass, T_CLASS);
01256 CONST_ID(id_refinements, "__refinements__");
01257 refinements = rb_attr_get(module, id_refinements);
01258 if (NIL_P(refinements)) {
01259 refinements = hidden_identity_hash_new();
01260 rb_ivar_set(module, id_refinements, refinements);
01261 }
01262 CONST_ID(id_activated_refinements, "__activated_refinements__");
01263 activated_refinements = rb_attr_get(module, id_activated_refinements);
01264 if (NIL_P(activated_refinements)) {
01265 activated_refinements = hidden_identity_hash_new();
01266 rb_ivar_set(module, id_activated_refinements,
01267 activated_refinements);
01268 }
01269 refinement = rb_hash_lookup(refinements, klass);
01270 if (NIL_P(refinement)) {
01271 refinement = rb_module_new();
01272 RCLASS_SET_SUPER(refinement, klass);
01273 FL_SET(refinement, RMODULE_IS_REFINEMENT);
01274 CONST_ID(id_refined_class, "__refined_class__");
01275 rb_ivar_set(refinement, id_refined_class, klass);
01276 CONST_ID(id_defined_at, "__defined_at__");
01277 rb_ivar_set(refinement, id_defined_at, module);
01278 rb_hash_aset(refinements, klass, refinement);
01279 add_activated_refinement(activated_refinements, klass, refinement);
01280 }
01281 rb_yield_refine_block(refinement, activated_refinements);
01282 return refinement;
01283 }
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293 static VALUE
01294 mod_using(VALUE self, VALUE module)
01295 {
01296 NODE *cref = rb_vm_cref();
01297 rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());
01298
01299 if (prev_frame_func()) {
01300 rb_raise(rb_eRuntimeError,
01301 "Module#using is not permitted in methods");
01302 }
01303 if (prev_cfp && prev_cfp->self != self) {
01304 rb_raise(rb_eRuntimeError, "Module#using is not called on self");
01305 }
01306 rb_using_module(cref, module);
01307 return self;
01308 }
01309
01310 void
01311 rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
01312 {
01313 PASS_PASSED_BLOCK();
01314 rb_funcall2(obj, idInitialize, argc, argv);
01315 }
01316
01317 void
01318 rb_extend_object(VALUE obj, VALUE module)
01319 {
01320 rb_include_module(rb_singleton_class(obj), module);
01321 }
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350 static VALUE
01351 rb_mod_extend_object(VALUE mod, VALUE obj)
01352 {
01353 rb_extend_object(obj, mod);
01354 return obj;
01355 }
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382 static VALUE
01383 rb_obj_extend(int argc, VALUE *argv, VALUE obj)
01384 {
01385 int i;
01386 ID id_extend_object, id_extended;
01387
01388 CONST_ID(id_extend_object, "extend_object");
01389 CONST_ID(id_extended, "extended");
01390
01391 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
01392 for (i = 0; i < argc; i++)
01393 Check_Type(argv[i], T_MODULE);
01394 while (argc--) {
01395 rb_funcall(argv[argc], id_extend_object, 1, obj);
01396 rb_funcall(argv[argc], id_extended, 1, obj);
01397 }
01398 return obj;
01399 }
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410 static VALUE
01411 top_include(int argc, VALUE *argv, VALUE self)
01412 {
01413 rb_thread_t *th = GET_THREAD();
01414
01415 if (th->top_wrapper) {
01416 rb_warning("main.include in the wrapped load is effective only in wrapper module");
01417 return rb_mod_include(argc, argv, th->top_wrapper);
01418 }
01419 return rb_mod_include(argc, argv, rb_cObject);
01420 }
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430 static VALUE
01431 top_using(VALUE self, VALUE module)
01432 {
01433 NODE *cref = rb_vm_cref();
01434 rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());
01435
01436 if (cref->nd_next || (prev_cfp && prev_cfp->me)) {
01437 rb_raise(rb_eRuntimeError,
01438 "main.using is permitted only at toplevel");
01439 }
01440 rb_using_module(cref, module);
01441 return self;
01442 }
01443
01444 static VALUE *
01445 errinfo_place(rb_thread_t *th)
01446 {
01447 rb_control_frame_t *cfp = th->cfp;
01448 rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
01449
01450 while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
01451 if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
01452 if (cfp->iseq->type == ISEQ_TYPE_RESCUE) {
01453 return &cfp->ep[-2];
01454 }
01455 else if (cfp->iseq->type == ISEQ_TYPE_ENSURE &&
01456 !RB_TYPE_P(cfp->ep[-2], T_NODE) &&
01457 !FIXNUM_P(cfp->ep[-2])) {
01458 return &cfp->ep[-2];
01459 }
01460 }
01461 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01462 }
01463 return 0;
01464 }
01465
01466 static VALUE
01467 get_thread_errinfo(rb_thread_t *th)
01468 {
01469 VALUE *ptr = errinfo_place(th);
01470 if (ptr) {
01471 return *ptr;
01472 }
01473 else {
01474 return th->errinfo;
01475 }
01476 }
01477
01478 static VALUE
01479 get_errinfo(void)
01480 {
01481 return get_thread_errinfo(GET_THREAD());
01482 }
01483
01484 static VALUE
01485 errinfo_getter(ID id)
01486 {
01487 return get_errinfo();
01488 }
01489
01490 #if 0
01491 static void
01492 errinfo_setter(VALUE val, ID id, VALUE *var)
01493 {
01494 if (!NIL_P(val) && !rb_obj_is_kind_of(val, rb_eException)) {
01495 rb_raise(rb_eTypeError, "assigning non-exception to $!");
01496 }
01497 else {
01498 VALUE *ptr = errinfo_place(GET_THREAD());
01499 if (ptr) {
01500 *ptr = val;
01501 }
01502 else {
01503 rb_raise(rb_eRuntimeError, "errinfo_setter: not in rescue clause.");
01504 }
01505 }
01506 }
01507 #endif
01508
01509 VALUE
01510 rb_errinfo(void)
01511 {
01512 rb_thread_t *th = GET_THREAD();
01513 return th->errinfo;
01514 }
01515
01516 void
01517 rb_set_errinfo(VALUE err)
01518 {
01519 if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) {
01520 rb_raise(rb_eTypeError, "assigning non-exception to $!");
01521 }
01522 GET_THREAD()->errinfo = err;
01523 }
01524
01525 VALUE
01526 rb_rubylevel_errinfo(void)
01527 {
01528 return get_errinfo();
01529 }
01530
01531 static VALUE
01532 errat_getter(ID id)
01533 {
01534 VALUE err = get_errinfo();
01535 if (!NIL_P(err)) {
01536 return get_backtrace(err);
01537 }
01538 else {
01539 return Qnil;
01540 }
01541 }
01542
01543 static void
01544 errat_setter(VALUE val, ID id, VALUE *var)
01545 {
01546 VALUE err = get_errinfo();
01547 if (NIL_P(err)) {
01548 rb_raise(rb_eArgError, "$! not set");
01549 }
01550 set_backtrace(err, val);
01551 }
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563 static VALUE
01564 rb_f_method_name(void)
01565 {
01566 ID fname = prev_frame_func();
01567
01568 if (fname) {
01569 return ID2SYM(fname);
01570 }
01571 else {
01572 return Qnil;
01573 }
01574 }
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585 static VALUE
01586 rb_f_callee_name(void)
01587 {
01588 ID fname = prev_frame_callee();
01589
01590 if (fname) {
01591 return ID2SYM(fname);
01592 }
01593 else {
01594 return Qnil;
01595 }
01596 }
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608 static VALUE
01609 f_current_dirname(void)
01610 {
01611 VALUE base = rb_current_realfilepath();
01612 if (NIL_P(base)) {
01613 return Qnil;
01614 }
01615 base = rb_file_dirname(base);
01616 return base;
01617 }
01618
01619 void
01620 Init_eval(void)
01621 {
01622 rb_define_virtual_variable("$@", errat_getter, errat_setter);
01623 rb_define_virtual_variable("$!", errinfo_getter, 0);
01624
01625 rb_define_global_function("raise", rb_f_raise, -1);
01626 rb_define_global_function("fail", rb_f_raise, -1);
01627
01628 rb_define_global_function("global_variables", rb_f_global_variables, 0);
01629
01630 rb_define_global_function("__method__", rb_f_method_name, 0);
01631 rb_define_global_function("__callee__", rb_f_callee_name, 0);
01632 rb_define_global_function("__dir__", f_current_dirname, 0);
01633
01634 rb_define_method(rb_cModule, "include", rb_mod_include, -1);
01635 rb_define_method(rb_cModule, "prepend", rb_mod_prepend, -1);
01636
01637 rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
01638 rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
01639 rb_define_private_method(rb_cModule, "prepend_features", rb_mod_prepend_features, 1);
01640 rb_define_private_method(rb_cModule, "refine", rb_mod_refine, 1);
01641 rb_define_private_method(rb_cModule, "using", mod_using, 1);
01642 rb_undef_method(rb_cClass, "refine");
01643
01644 rb_undef_method(rb_cClass, "module_function");
01645
01646 Init_vm_eval();
01647 Init_eval_method();
01648
01649 rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
01650 rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
01651
01652 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
01653 "include", top_include, -1);
01654 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
01655 "using", top_using, 1);
01656
01657 rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
01658
01659 rb_define_global_function("trace_var", rb_f_trace_var, -1);
01660 rb_define_global_function("untrace_var", rb_f_untrace_var, -1);
01661
01662 exception_error = rb_exc_new3(rb_eFatal,
01663 rb_obj_freeze(rb_str_new2("exception reentered")));
01664 OBJ_TAINT(exception_error);
01665 OBJ_FREEZE(exception_error);
01666 }
01667