00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "insns.inc"
00013 #include <math.h>
00014 #include "constant.h"
00015 #include "internal.h"
00016
00017
00018
00019 #ifndef INLINE
00020 #define INLINE inline
00021 #endif
00022
00023 static rb_control_frame_t *vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
00024
00025 static inline rb_control_frame_t *
00026 vm_push_frame(rb_thread_t * th, const rb_iseq_t * iseq,
00027 VALUE type, VALUE self, VALUE specval,
00028 const VALUE *pc, VALUE *sp, VALUE *lfp,
00029 int local_size)
00030 {
00031 rb_control_frame_t * const cfp = th->cfp - 1;
00032 int i;
00033
00034 if ((void *)(sp + local_size) >= (void *)cfp) {
00035 rb_exc_raise(sysstack_error);
00036 }
00037 th->cfp = cfp;
00038
00039
00040
00041 for (i=0; i < local_size; i++) {
00042 *sp = Qnil;
00043 sp++;
00044 }
00045
00046
00047 *sp = GC_GUARDED_PTR(specval);
00048
00049 if (lfp == 0) {
00050 lfp = sp;
00051 }
00052
00053
00054
00055 cfp->pc = (VALUE *)pc;
00056 cfp->sp = sp + 1;
00057 cfp->bp = sp + 1;
00058 cfp->iseq = (rb_iseq_t *) iseq;
00059 cfp->flag = type;
00060 cfp->self = self;
00061 cfp->lfp = lfp;
00062 cfp->dfp = sp;
00063 cfp->block_iseq = 0;
00064 cfp->proc = 0;
00065 cfp->me = 0;
00066
00067 #define COLLECT_PROFILE 0
00068 #if COLLECT_PROFILE
00069 cfp->prof_time_self = clock();
00070 cfp->prof_time_chld = 0;
00071 #endif
00072
00073 if (VMDEBUG == 2) {
00074 SDR();
00075 }
00076
00077 return cfp;
00078 }
00079
00080 static inline void
00081 vm_pop_frame(rb_thread_t *th)
00082 {
00083 #if COLLECT_PROFILE
00084 rb_control_frame_t *cfp = th->cfp;
00085
00086 if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
00087 VALUE current_time = clock();
00088 rb_control_frame_t *cfp = th->cfp;
00089 cfp->prof_time_self = current_time - cfp->prof_time_self;
00090 (cfp+1)->prof_time_chld += cfp->prof_time_self;
00091
00092 cfp->iseq->profile.count++;
00093 cfp->iseq->profile.time_cumu = cfp->prof_time_self;
00094 cfp->iseq->profile.time_self = cfp->prof_time_self - cfp->prof_time_chld;
00095 }
00096 else if (0 ) {
00097
00098 }
00099 #endif
00100 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00101
00102 if (VMDEBUG == 2) {
00103 SDR();
00104 }
00105 }
00106
00107
00108
00109 NORETURN(static void argument_error(const rb_iseq_t *iseq, int miss_argc, int correct_argc));
00110 static void
00111 argument_error(const rb_iseq_t *iseq, int miss_argc, int correct_argc)
00112 {
00113 VALUE mesg = rb_sprintf("wrong number of arguments (%d for %d)", miss_argc, correct_argc);
00114 VALUE exc = rb_exc_new3(rb_eArgError, mesg);
00115 VALUE bt = rb_make_backtrace();
00116 VALUE err_line = 0;
00117
00118 if (iseq) {
00119 int line_no = 1;
00120
00121 if (iseq->insn_info_size) {
00122 line_no = iseq->insn_info_table[0].line_no;
00123 }
00124
00125 err_line = rb_sprintf("%s:%d:in `%s'",
00126 RSTRING_PTR(iseq->filename),
00127 line_no, RSTRING_PTR(iseq->name));
00128 rb_funcall(bt, rb_intern("unshift"), 1, err_line);
00129 }
00130
00131 rb_funcall(exc, rb_intern("set_backtrace"), 1, bt);
00132 rb_exc_raise(exc);
00133 }
00134
00135 #define VM_CALLEE_SETUP_ARG(ret, th, iseq, orig_argc, orig_argv, block) \
00136 if (LIKELY((iseq)->arg_simple & 0x01)) { \
00137 \
00138 if ((orig_argc) != (iseq)->argc) { \
00139 argument_error((iseq), (orig_argc), (iseq)->argc); \
00140 } \
00141 (ret) = 0; \
00142 } \
00143 else { \
00144 (ret) = vm_callee_setup_arg_complex((th), (iseq), (orig_argc), (orig_argv), (block)); \
00145 }
00146
00147 static inline int
00148 vm_callee_setup_arg_complex(rb_thread_t *th, const rb_iseq_t * iseq,
00149 int orig_argc, VALUE * orig_argv,
00150 const rb_block_t **block)
00151 {
00152 const int m = iseq->argc;
00153 int argc = orig_argc;
00154 VALUE *argv = orig_argv;
00155 rb_num_t opt_pc = 0;
00156
00157 th->mark_stack_len = argc + iseq->arg_size;
00158
00159
00160 if (argc < (m + iseq->arg_post_len)) {
00161 argument_error(iseq, argc, m + iseq->arg_post_len);
00162 }
00163
00164 argv += m;
00165 argc -= m;
00166
00167
00168 if (iseq->arg_post_len) {
00169 if (!(orig_argc < iseq->arg_post_start)) {
00170 VALUE *new_argv = ALLOCA_N(VALUE, argc);
00171 MEMCPY(new_argv, argv, VALUE, argc);
00172 argv = new_argv;
00173 }
00174
00175 MEMCPY(&orig_argv[iseq->arg_post_start], &argv[argc -= iseq->arg_post_len],
00176 VALUE, iseq->arg_post_len);
00177 }
00178
00179
00180 if (iseq->arg_opts) {
00181 const int opts = iseq->arg_opts - 1 ;
00182
00183 if (iseq->arg_rest == -1 && argc > opts) {
00184 argument_error(iseq, orig_argc, m + opts + iseq->arg_post_len);
00185 }
00186
00187 if (argc > opts) {
00188 argc -= opts;
00189 argv += opts;
00190 opt_pc = iseq->arg_opt_table[opts];
00191 }
00192 else {
00193 int i;
00194 for (i = argc; i<opts; i++) {
00195 orig_argv[i + m] = Qnil;
00196 }
00197 opt_pc = iseq->arg_opt_table[argc];
00198 argc = 0;
00199 }
00200 }
00201
00202
00203 if (iseq->arg_rest != -1) {
00204 orig_argv[iseq->arg_rest] = rb_ary_new4(argc, argv);
00205 argc = 0;
00206 }
00207
00208
00209 if (block && iseq->arg_block != -1) {
00210 VALUE blockval = Qnil;
00211 const rb_block_t *blockptr = *block;
00212
00213 if (argc != 0) {
00214 argument_error(iseq, orig_argc, m + iseq->arg_post_len);
00215 }
00216
00217 if (blockptr) {
00218
00219 if (blockptr->proc == 0) {
00220 rb_proc_t *proc;
00221 blockval = rb_vm_make_proc(th, blockptr, rb_cProc);
00222 GetProcPtr(blockval, proc);
00223 *block = &proc->block;
00224 }
00225 else {
00226 blockval = blockptr->proc;
00227 }
00228 }
00229
00230 orig_argv[iseq->arg_block] = blockval;
00231 }
00232
00233 th->mark_stack_len = 0;
00234 return (int)opt_pc;
00235 }
00236
00237 static inline int
00238 caller_setup_args(const rb_thread_t *th, rb_control_frame_t *cfp, VALUE flag,
00239 int argc, rb_iseq_t *blockiseq, rb_block_t **block)
00240 {
00241 rb_block_t *blockptr = 0;
00242
00243 if (block) {
00244 if (flag & VM_CALL_ARGS_BLOCKARG_BIT) {
00245 rb_proc_t *po;
00246 VALUE proc;
00247
00248 proc = *(--cfp->sp);
00249
00250 if (proc != Qnil) {
00251 if (!rb_obj_is_proc(proc)) {
00252 VALUE b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
00253 if (NIL_P(b) || !rb_obj_is_proc(b)) {
00254 rb_raise(rb_eTypeError,
00255 "wrong argument type %s (expected Proc)",
00256 rb_obj_classname(proc));
00257 }
00258 proc = b;
00259 }
00260 GetProcPtr(proc, po);
00261 blockptr = &po->block;
00262 RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp)->proc = proc;
00263 *block = blockptr;
00264 }
00265 }
00266 else if (blockiseq) {
00267 blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
00268 blockptr->iseq = blockiseq;
00269 blockptr->proc = 0;
00270 *block = blockptr;
00271 }
00272 }
00273
00274
00275 if (flag & VM_CALL_ARGS_SPLAT_BIT) {
00276 VALUE ary = *(cfp->sp - 1);
00277 VALUE *ptr;
00278 int i;
00279 VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a");
00280
00281 if (NIL_P(tmp)) {
00282
00283 }
00284 else {
00285 long len = RARRAY_LEN(tmp);
00286 ptr = RARRAY_PTR(tmp);
00287 cfp->sp -= 1;
00288
00289 CHECK_STACK_OVERFLOW(cfp, len);
00290
00291 for (i = 0; i < len; i++) {
00292 *cfp->sp++ = ptr[i];
00293 }
00294 argc += i-1;
00295 }
00296 }
00297
00298 return argc;
00299 }
00300
00301 static inline VALUE
00302 call_cfunc(VALUE (*func)(), VALUE recv,
00303 int len, int argc, const VALUE *argv)
00304 {
00305
00306
00307 if (len >= 0 && argc != len) {
00308 rb_raise(rb_eArgError, "wrong number of arguments(%d for %d)",
00309 argc, len);
00310 }
00311
00312 switch (len) {
00313 case -2:
00314 return (*func) (recv, rb_ary_new4(argc, argv));
00315 break;
00316 case -1:
00317 return (*func) (argc, argv, recv);
00318 break;
00319 case 0:
00320 return (*func) (recv);
00321 break;
00322 case 1:
00323 return (*func) (recv, argv[0]);
00324 break;
00325 case 2:
00326 return (*func) (recv, argv[0], argv[1]);
00327 break;
00328 case 3:
00329 return (*func) (recv, argv[0], argv[1], argv[2]);
00330 break;
00331 case 4:
00332 return (*func) (recv, argv[0], argv[1], argv[2], argv[3]);
00333 break;
00334 case 5:
00335 return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
00336 break;
00337 case 6:
00338 return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
00339 argv[5]);
00340 break;
00341 case 7:
00342 return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
00343 argv[5], argv[6]);
00344 break;
00345 case 8:
00346 return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
00347 argv[5], argv[6], argv[7]);
00348 break;
00349 case 9:
00350 return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
00351 argv[5], argv[6], argv[7], argv[8]);
00352 break;
00353 case 10:
00354 return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
00355 argv[5], argv[6], argv[7], argv[8], argv[9]);
00356 break;
00357 case 11:
00358 return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
00359 argv[5], argv[6], argv[7], argv[8], argv[9],
00360 argv[10]);
00361 break;
00362 case 12:
00363 return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
00364 argv[5], argv[6], argv[7], argv[8], argv[9],
00365 argv[10], argv[11]);
00366 break;
00367 case 13:
00368 return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
00369 argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
00370 argv[11], argv[12]);
00371 break;
00372 case 14:
00373 return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
00374 argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
00375 argv[11], argv[12], argv[13]);
00376 break;
00377 case 15:
00378 return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4],
00379 argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
00380 argv[11], argv[12], argv[13], argv[14]);
00381 break;
00382 default:
00383 rb_raise(rb_eArgError, "too many arguments(%d)", len);
00384 return Qundef;
00385 }
00386 }
00387
00388 static inline VALUE
00389 vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp,
00390 int num, volatile VALUE recv, const rb_block_t *blockptr,
00391 const rb_method_entry_t *me)
00392 {
00393 volatile VALUE val = 0;
00394 const rb_method_definition_t *def = me->def;
00395 rb_control_frame_t *cfp;
00396
00397 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass);
00398
00399 cfp = vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
00400 recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
00401 cfp->me = me;
00402 reg_cfp->sp -= num + 1;
00403
00404 val = call_cfunc(def->body.cfunc.func, recv, (int)def->body.cfunc.argc, num, reg_cfp->sp + 1);
00405
00406 if (reg_cfp != th->cfp + 1) {
00407 rb_bug("cfp consistency error - send");
00408 }
00409
00410 vm_pop_frame(th);
00411
00412 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, me->called_id, me->klass);
00413
00414 return val;
00415 }
00416
00417 static inline VALUE
00418 vm_call_bmethod(rb_thread_t *th, VALUE recv, int argc, const VALUE *argv,
00419 const rb_block_t *blockptr, const rb_method_entry_t *me)
00420 {
00421 rb_proc_t *proc;
00422 VALUE val;
00423
00424 EXEC_EVENT_HOOK(th, RUBY_EVENT_CALL, recv, me->called_id, me->klass);
00425
00426
00427 th->passed_me = me;
00428 GetProcPtr(me->def->body.proc, proc);
00429 val = rb_vm_invoke_proc(th, proc, recv, argc, argv, blockptr);
00430
00431 EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, recv, me->called_id, me->klass);
00432
00433 return val;
00434 }
00435
00436 static inline void
00437 vm_method_missing_args(rb_thread_t *th, VALUE *argv,
00438 int num, const rb_block_t *blockptr, int opt)
00439 {
00440 rb_control_frame_t * const reg_cfp = th->cfp;
00441 MEMCPY(argv, STACK_ADDR_FROM_TOP(num + 1), VALUE, num + 1);
00442 th->method_missing_reason = opt;
00443 th->passed_block = blockptr;
00444 POPN(num + 1);
00445 }
00446
00447 static inline VALUE
00448 vm_method_missing(rb_thread_t *th, ID id, VALUE recv,
00449 int num, const rb_block_t *blockptr, int opt)
00450 {
00451 VALUE *argv = ALLOCA_N(VALUE, num + 1);
00452 vm_method_missing_args(th, argv, num, blockptr, opt);
00453 argv[0] = ID2SYM(id);
00454 return rb_funcall2(recv, idMethodMissing, num + 1, argv);
00455 }
00456
00457 static inline void
00458 vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
00459 VALUE recv, int argc, const rb_block_t *blockptr, VALUE flag,
00460 const rb_method_entry_t *me)
00461 {
00462 int opt_pc, i;
00463 VALUE *sp, *rsp = cfp->sp - argc;
00464 rb_iseq_t *iseq = me->def->body.iseq;
00465
00466 VM_CALLEE_SETUP_ARG(opt_pc, th, iseq, argc, rsp, &blockptr);
00467
00468
00469 CHECK_STACK_OVERFLOW(cfp, iseq->stack_max);
00470
00471 sp = rsp + iseq->arg_size;
00472
00473 if (LIKELY(!(flag & VM_CALL_TAILCALL_BIT))) {
00474 if (0) printf("local_size: %d, arg_size: %d\n",
00475 iseq->local_size, iseq->arg_size);
00476
00477
00478 for (i = 0; i < iseq->local_size - iseq->arg_size; i++) {
00479 *sp++ = Qnil;
00480 }
00481
00482 vm_push_frame(th, iseq,
00483 VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
00484 iseq->iseq_encoded + opt_pc, sp, 0, 0);
00485
00486 cfp->sp = rsp - 1 ;
00487 }
00488 else {
00489 VALUE *p_rsp;
00490 th->cfp++;
00491 p_rsp = th->cfp->sp;
00492
00493
00494 for (i=0; i < (sp - rsp); i++) {
00495 p_rsp[i] = rsp[i];
00496 }
00497
00498 sp -= rsp - p_rsp;
00499
00500
00501 for (i = 0; i < iseq->local_size - iseq->arg_size; i++) {
00502 *sp++ = Qnil;
00503 }
00504
00505 vm_push_frame(th, iseq,
00506 VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
00507 iseq->iseq_encoded + opt_pc, sp, 0, 0);
00508 }
00509 }
00510
00511 static inline VALUE
00512 vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
00513 int num, const rb_block_t *blockptr, VALUE flag,
00514 ID id, const rb_method_entry_t *me, VALUE recv)
00515 {
00516 VALUE val;
00517
00518 start_method_dispatch:
00519
00520 if (me != 0) {
00521 if ((me->flag == 0)) {
00522 normal_method_dispatch:
00523 switch (me->def->type) {
00524 case VM_METHOD_TYPE_ISEQ:{
00525 vm_setup_method(th, cfp, recv, num, blockptr, flag, me);
00526 return Qundef;
00527 }
00528 case VM_METHOD_TYPE_NOTIMPLEMENTED:
00529 case VM_METHOD_TYPE_CFUNC:{
00530 val = vm_call_cfunc(th, cfp, num, recv, blockptr, me);
00531 break;
00532 }
00533 case VM_METHOD_TYPE_ATTRSET:{
00534 if (num != 1) {
00535 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", num);
00536 }
00537 val = rb_ivar_set(recv, me->def->body.attr.id, *(cfp->sp - 1));
00538 cfp->sp -= 2;
00539 break;
00540 }
00541 case VM_METHOD_TYPE_IVAR:{
00542 if (num != 0) {
00543 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", num);
00544 }
00545 val = rb_attr_get(recv, me->def->body.attr.id);
00546 cfp->sp -= 1;
00547 break;
00548 }
00549 case VM_METHOD_TYPE_MISSING:{
00550 VALUE *argv = ALLOCA_N(VALUE, num+1);
00551 argv[0] = ID2SYM(me->def->original_id);
00552 MEMCPY(argv+1, cfp->sp - num, VALUE, num);
00553 cfp->sp += - num - 1;
00554 th->passed_block = blockptr;
00555 val = rb_funcall2(recv, rb_intern("method_missing"), num+1, argv);
00556 break;
00557 }
00558 case VM_METHOD_TYPE_BMETHOD:{
00559 VALUE *argv = ALLOCA_N(VALUE, num);
00560 MEMCPY(argv, cfp->sp - num, VALUE, num);
00561 cfp->sp += - num - 1;
00562 val = vm_call_bmethod(th, recv, num, argv, blockptr, me);
00563 break;
00564 }
00565 case VM_METHOD_TYPE_ZSUPER:{
00566 VALUE klass = RCLASS_SUPER(me->klass);
00567 me = rb_method_entry(klass, id);
00568
00569 if (me != 0) {
00570 goto normal_method_dispatch;
00571 }
00572 else {
00573 goto start_method_dispatch;
00574 }
00575 }
00576 case VM_METHOD_TYPE_OPTIMIZED:{
00577 switch (me->def->body.optimize_type) {
00578 case OPTIMIZED_METHOD_TYPE_SEND: {
00579 rb_control_frame_t *reg_cfp = cfp;
00580 rb_num_t i = num - 1;
00581 VALUE sym;
00582
00583 if (num == 0) {
00584 rb_raise(rb_eArgError, "no method name given");
00585 }
00586
00587 sym = TOPN(i);
00588 id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym);
00589
00590 if (i > 0) {
00591 MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i);
00592 }
00593 me = rb_method_entry(CLASS_OF(recv), id);
00594 num -= 1;
00595 DEC_SP(1);
00596 flag |= VM_CALL_FCALL_BIT | VM_CALL_OPT_SEND_BIT;
00597
00598 goto start_method_dispatch;
00599 }
00600 case OPTIMIZED_METHOD_TYPE_CALL: {
00601 rb_proc_t *proc;
00602 int argc = num;
00603 VALUE *argv = ALLOCA_N(VALUE, num);
00604 GetProcPtr(recv, proc);
00605 MEMCPY(argv, cfp->sp - num, VALUE, num);
00606 cfp->sp -= num + 1;
00607
00608 val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr);
00609 break;
00610 }
00611 default:
00612 rb_bug("eval_invoke_method: unsupported optimized method type (%d)",
00613 me->def->body.optimize_type);
00614 }
00615 break;
00616 }
00617 default:{
00618 rb_bug("eval_invoke_method: unsupported method type (%d)", me->def->type);
00619 break;
00620 }
00621 }
00622 }
00623 else {
00624 int noex_safe;
00625
00626 if (!(flag & VM_CALL_FCALL_BIT) &&
00627 (me->flag & NOEX_MASK) & NOEX_PRIVATE) {
00628 int stat = NOEX_PRIVATE;
00629
00630 if (flag & VM_CALL_VCALL_BIT) {
00631 stat |= NOEX_VCALL;
00632 }
00633 val = vm_method_missing(th, id, recv, num, blockptr, stat);
00634 }
00635 else if (!(flag & VM_CALL_OPT_SEND_BIT) && (me->flag & NOEX_MASK) & NOEX_PROTECTED) {
00636 VALUE defined_class = me->klass;
00637
00638 if (RB_TYPE_P(defined_class, T_ICLASS)) {
00639 defined_class = RBASIC(defined_class)->klass;
00640 }
00641
00642 if (!rb_obj_is_kind_of(cfp->self, defined_class)) {
00643 val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED);
00644 }
00645 else {
00646 goto normal_method_dispatch;
00647 }
00648 }
00649 else if ((noex_safe = NOEX_SAFE(me->flag)) > th->safe_level &&
00650 (noex_safe > 2)) {
00651 rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(id));
00652 }
00653 else {
00654 goto normal_method_dispatch;
00655 }
00656 }
00657 }
00658 else {
00659
00660 int stat = 0;
00661 if (flag & VM_CALL_VCALL_BIT) {
00662 stat |= NOEX_VCALL;
00663 }
00664 if (flag & VM_CALL_SUPER_BIT) {
00665 stat |= NOEX_SUPER;
00666 }
00667 if (id == idMethodMissing) {
00668 VALUE *argv = ALLOCA_N(VALUE, num);
00669 vm_method_missing_args(th, argv, num - 1, 0, stat);
00670 rb_raise_method_missing(th, num, argv, recv, stat);
00671 }
00672 else {
00673 val = vm_method_missing(th, id, recv, num, blockptr, stat);
00674 }
00675 }
00676
00677 RUBY_VM_CHECK_INTS();
00678 return val;
00679 }
00680
00681
00682
00683 static inline int
00684 block_proc_is_lambda(const VALUE procval)
00685 {
00686 rb_proc_t *proc;
00687
00688 if (procval) {
00689 GetProcPtr(procval, proc);
00690 return proc->is_lambda;
00691 }
00692 else {
00693 return 0;
00694 }
00695 }
00696
00697 static inline VALUE
00698 vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block,
00699 VALUE self, int argc, const VALUE *argv,
00700 const rb_block_t *blockargptr)
00701 {
00702 NODE *ifunc = (NODE *) block->iseq;
00703 VALUE val, arg, blockarg;
00704 int lambda = block_proc_is_lambda(block->proc);
00705
00706 if (lambda) {
00707 arg = rb_ary_new4(argc, argv);
00708 }
00709 else if (argc == 0) {
00710 arg = Qnil;
00711 }
00712 else {
00713 arg = argv[0];
00714 }
00715
00716 if (blockargptr) {
00717 if (blockargptr->proc) {
00718 blockarg = blockargptr->proc;
00719 }
00720 else {
00721 blockarg = rb_vm_make_proc(th, blockargptr, rb_cProc);
00722 }
00723 }
00724 else {
00725 blockarg = Qnil;
00726 }
00727
00728 vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC,
00729 self, (VALUE)block->dfp,
00730 0, th->cfp->sp, block->lfp, 1);
00731
00732 if (blockargptr) {
00733 th->cfp->lfp[0] = GC_GUARDED_PTR((VALUE)blockargptr);
00734 }
00735 val = (*ifunc->nd_cfnc) (arg, ifunc->nd_tval, argc, argv, blockarg);
00736
00737 th->cfp++;
00738 return val;
00739 }
00740
00741
00742
00743
00744
00745
00746 static inline int
00747 vm_yield_setup_block_args_complex(rb_thread_t *th, const rb_iseq_t *iseq,
00748 int argc, VALUE *argv)
00749 {
00750 rb_num_t opt_pc = 0;
00751 int i;
00752 const int m = iseq->argc;
00753 const int r = iseq->arg_rest;
00754 int len = iseq->arg_post_len;
00755 int start = iseq->arg_post_start;
00756 int rsize = argc > m ? argc - m : 0;
00757 int psize = rsize > len ? len : rsize;
00758 int osize = 0;
00759 VALUE ary;
00760
00761
00762 rsize -= psize;
00763
00764 if (iseq->arg_opts) {
00765 const int opts = iseq->arg_opts - 1;
00766 if (rsize > opts) {
00767 osize = opts;
00768 opt_pc = iseq->arg_opt_table[opts];
00769 }
00770 else {
00771 osize = rsize;
00772 opt_pc = iseq->arg_opt_table[rsize];
00773 }
00774 }
00775 rsize -= osize;
00776
00777 if (0) {
00778 printf(" argc: %d\n", argc);
00779 printf(" len: %d\n", len);
00780 printf("start: %d\n", start);
00781 printf("rsize: %d\n", rsize);
00782 }
00783
00784 if (r == -1) {
00785
00786 MEMMOVE(&argv[start], &argv[m+osize], VALUE, psize);
00787 }
00788 else {
00789 ary = rb_ary_new4(rsize, &argv[r]);
00790
00791
00792 MEMMOVE(&argv[start], &argv[m+rsize+osize], VALUE, psize);
00793 argv[r] = ary;
00794 }
00795
00796 for (i=psize; i<len; i++) {
00797 argv[start + i] = Qnil;
00798 }
00799
00800 return (int)opt_pc;
00801 }
00802
00803 static inline int
00804 vm_yield_setup_block_args(rb_thread_t *th, const rb_iseq_t * iseq,
00805 int orig_argc, VALUE *argv,
00806 const rb_block_t *blockptr)
00807 {
00808 int i;
00809 int argc = orig_argc;
00810 const int m = iseq->argc;
00811 VALUE ary, arg0;
00812 int opt_pc = 0;
00813
00814 th->mark_stack_len = argc;
00815
00816
00817
00818
00819
00820
00821 arg0 = argv[0];
00822 if (!(iseq->arg_simple & 0x02) &&
00823 (m + iseq->arg_post_len) > 0 &&
00824 argc == 1 && !NIL_P(ary = rb_check_array_type(arg0))) {
00825 th->mark_stack_len = argc = RARRAY_LENINT(ary);
00826
00827 CHECK_STACK_OVERFLOW(th->cfp, argc);
00828
00829 MEMCPY(argv, RARRAY_PTR(ary), VALUE, argc);
00830 }
00831 else {
00832 argv[0] = arg0;
00833 }
00834
00835 for (i=argc; i<m; i++) {
00836 argv[i] = Qnil;
00837 }
00838
00839 if (iseq->arg_rest == -1 && iseq->arg_opts == 0) {
00840 const int arg_size = iseq->arg_size;
00841 if (arg_size < argc) {
00842
00843
00844
00845
00846 th->mark_stack_len = argc = arg_size;
00847 }
00848 }
00849 else {
00850 int r = iseq->arg_rest;
00851
00852 if (iseq->arg_post_len ||
00853 iseq->arg_opts) {
00854 opt_pc = vm_yield_setup_block_args_complex(th, iseq, argc, argv);
00855 }
00856 else {
00857 if (argc < r) {
00858
00859
00860
00861 for (i=argc; i<r; i++) {
00862 argv[i] = Qnil;
00863 }
00864 argv[r] = rb_ary_new();
00865 }
00866 else {
00867 argv[r] = rb_ary_new4(argc-r, &argv[r]);
00868 }
00869 }
00870
00871 th->mark_stack_len = iseq->arg_size;
00872 }
00873
00874
00875 if (iseq->arg_block != -1) {
00876 VALUE procval = Qnil;
00877
00878 if (blockptr) {
00879 if (blockptr->proc == 0) {
00880 procval = rb_vm_make_proc(th, blockptr, rb_cProc);
00881 }
00882 else {
00883 procval = blockptr->proc;
00884 }
00885 }
00886
00887 argv[iseq->arg_block] = procval;
00888 }
00889
00890 th->mark_stack_len = 0;
00891 return opt_pc;
00892 }
00893
00894 static inline int
00895 vm_yield_setup_args(rb_thread_t * const th, const rb_iseq_t *iseq,
00896 int argc, VALUE *argv,
00897 const rb_block_t *blockptr, int lambda)
00898 {
00899 if (0) {
00900 printf(" argc: %d\n", argc);
00901 printf("iseq argc: %d\n", iseq->argc);
00902 printf("iseq opts: %d\n", iseq->arg_opts);
00903 printf("iseq rest: %d\n", iseq->arg_rest);
00904 printf("iseq post: %d\n", iseq->arg_post_len);
00905 printf("iseq blck: %d\n", iseq->arg_block);
00906 printf("iseq smpl: %d\n", iseq->arg_simple);
00907 printf(" lambda: %s\n", lambda ? "true" : "false");
00908 }
00909
00910 if (lambda) {
00911
00912 int opt_pc;
00913 VM_CALLEE_SETUP_ARG(opt_pc, th, iseq, argc, argv, &blockptr);
00914 return opt_pc;
00915 }
00916 else {
00917 return vm_yield_setup_block_args(th, iseq, argc, argv, blockptr);
00918 }
00919 }
00920
00921 static VALUE
00922 vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_num_t flag)
00923 {
00924 const rb_block_t *block = GET_BLOCK_PTR();
00925 rb_iseq_t *iseq;
00926 int argc = (int)num;
00927 VALUE type = GET_ISEQ()->local_iseq->type;
00928
00929 if ((type != ISEQ_TYPE_METHOD && type != ISEQ_TYPE_CLASS) || block == 0) {
00930 rb_vm_localjump_error("no block given (yield)", Qnil, 0);
00931 }
00932 iseq = block->iseq;
00933
00934 argc = caller_setup_args(th, GET_CFP(), flag, argc, 0, 0);
00935
00936 if (BUILTIN_TYPE(iseq) != T_NODE) {
00937 int opt_pc;
00938 const int arg_size = iseq->arg_size;
00939 VALUE * const rsp = GET_SP() - argc;
00940 SET_SP(rsp);
00941
00942 CHECK_STACK_OVERFLOW(GET_CFP(), iseq->stack_max);
00943 opt_pc = vm_yield_setup_args(th, iseq, argc, rsp, 0,
00944 block_proc_is_lambda(block->proc));
00945
00946 vm_push_frame(th, iseq,
00947 VM_FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp,
00948 iseq->iseq_encoded + opt_pc, rsp + arg_size, block->lfp,
00949 iseq->local_size - arg_size);
00950
00951 return Qundef;
00952 }
00953 else {
00954 VALUE val = vm_yield_with_cfunc(th, block, block->self, argc, STACK_ADDR_FROM_TOP(argc), 0);
00955 POPN(argc);
00956 return val;
00957 }
00958 }
00959
00960
00961
00962 static inline NODE *
00963 lfp_svar_place(rb_thread_t *th, VALUE *lfp)
00964 {
00965 VALUE *svar;
00966
00967 if (lfp && th->local_lfp != lfp) {
00968 svar = &lfp[-1];
00969 }
00970 else {
00971 svar = &th->local_svar;
00972 }
00973 if (NIL_P(*svar)) {
00974 *svar = (VALUE)NEW_IF(Qnil, Qnil, Qnil);
00975 }
00976 return (NODE *)*svar;
00977 }
00978
00979 static VALUE
00980 lfp_svar_get(rb_thread_t *th, VALUE *lfp, rb_num_t key)
00981 {
00982 NODE *svar = lfp_svar_place(th, lfp);
00983
00984 switch (key) {
00985 case 0:
00986 return svar->u1.value;
00987 case 1:
00988 return svar->u2.value;
00989 default: {
00990 const VALUE ary = svar->u3.value;
00991
00992 if (NIL_P(ary)) {
00993 return Qnil;
00994 }
00995 else {
00996 return rb_ary_entry(ary, key - DEFAULT_SPECIAL_VAR_COUNT);
00997 }
00998 }
00999 }
01000 }
01001
01002 static void
01003 lfp_svar_set(rb_thread_t *th, VALUE *lfp, rb_num_t key, VALUE val)
01004 {
01005 NODE *svar = lfp_svar_place(th, lfp);
01006
01007 switch (key) {
01008 case 0:
01009 svar->u1.value = val;
01010 return;
01011 case 1:
01012 svar->u2.value = val;
01013 return;
01014 default: {
01015 VALUE ary = svar->u3.value;
01016
01017 if (NIL_P(ary)) {
01018 svar->u3.value = ary = rb_ary_new();
01019 }
01020 rb_ary_store(ary, key - DEFAULT_SPECIAL_VAR_COUNT, val);
01021 }
01022 }
01023 }
01024
01025 static inline VALUE
01026 vm_getspecial(rb_thread_t *th, VALUE *lfp, rb_num_t key, rb_num_t type)
01027 {
01028 VALUE val;
01029
01030 if (type == 0) {
01031 val = lfp_svar_get(th, lfp, key);
01032 }
01033 else {
01034 VALUE backref = lfp_svar_get(th, lfp, 1);
01035
01036 if (type & 0x01) {
01037 switch (type >> 1) {
01038 case '&':
01039 val = rb_reg_last_match(backref);
01040 break;
01041 case '`':
01042 val = rb_reg_match_pre(backref);
01043 break;
01044 case '\'':
01045 val = rb_reg_match_post(backref);
01046 break;
01047 case '+':
01048 val = rb_reg_match_last(backref);
01049 break;
01050 default:
01051 rb_bug("unexpected back-ref");
01052 }
01053 }
01054 else {
01055 val = rb_reg_nth_match((int)(type >> 1), backref);
01056 }
01057 }
01058 return val;
01059 }
01060
01061 static NODE *
01062 vm_get_cref0(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
01063 {
01064 while (1) {
01065 if (lfp == dfp) {
01066 if (!RUBY_VM_NORMAL_ISEQ_P(iseq)) return NULL;
01067 return iseq->cref_stack;
01068 }
01069 else if (dfp[-1] != Qnil) {
01070 return (NODE *)dfp[-1];
01071 }
01072 dfp = GET_PREV_DFP(dfp);
01073 }
01074 }
01075
01076 static NODE *
01077 vm_get_cref(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
01078 {
01079 NODE *cref = vm_get_cref0(iseq, lfp, dfp);
01080
01081 if (cref == 0) {
01082 rb_bug("vm_get_cref: unreachable");
01083 }
01084 return cref;
01085 }
01086
01087 static NODE *
01088 vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
01089 {
01090 rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
01091 NODE *cref = NEW_BLOCK(klass);
01092 cref->nd_visi = noex;
01093
01094 if (blockptr) {
01095 cref->nd_next = vm_get_cref0(blockptr->iseq, blockptr->lfp, blockptr->dfp);
01096 }
01097 else if (cfp) {
01098 cref->nd_next = vm_get_cref0(cfp->iseq, cfp->lfp, cfp->dfp);
01099 }
01100
01101 return cref;
01102 }
01103
01104 static inline VALUE
01105 vm_get_cbase(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
01106 {
01107 NODE *cref = vm_get_cref(iseq, lfp, dfp);
01108 VALUE klass = Qundef;
01109
01110 while (cref) {
01111 if ((klass = cref->nd_clss) != 0) {
01112 break;
01113 }
01114 cref = cref->nd_next;
01115 }
01116
01117 return klass;
01118 }
01119
01120 static inline VALUE
01121 vm_get_const_base(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
01122 {
01123 NODE *cref = vm_get_cref(iseq, lfp, dfp);
01124 VALUE klass = Qundef;
01125
01126 while (cref) {
01127 if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
01128 (klass = cref->nd_clss) != 0) {
01129 break;
01130 }
01131 cref = cref->nd_next;
01132 }
01133
01134 return klass;
01135 }
01136
01137 static inline void
01138 vm_check_if_namespace(VALUE klass)
01139 {
01140 VALUE str;
01141 switch (TYPE(klass)) {
01142 case T_CLASS:
01143 case T_MODULE:
01144 break;
01145 default:
01146 str = rb_inspect(klass);
01147 rb_raise(rb_eTypeError, "%s is not a class/module",
01148 StringValuePtr(str));
01149 }
01150 }
01151
01152 static inline VALUE
01153 vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
01154 VALUE orig_klass, ID id, int is_defined)
01155 {
01156 VALUE val;
01157
01158 if (orig_klass == Qnil) {
01159
01160 const NODE *root_cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
01161 const NODE *cref;
01162 VALUE klass = orig_klass;
01163
01164 while (root_cref && root_cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) {
01165 root_cref = root_cref->nd_next;
01166 }
01167 cref = root_cref;
01168 while (cref && cref->nd_next) {
01169 if (cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) {
01170 klass = Qnil;
01171 }
01172 else {
01173 klass = cref->nd_clss;
01174 }
01175 cref = cref->nd_next;
01176
01177 if (!NIL_P(klass)) {
01178 VALUE am = 0;
01179 st_data_t data;
01180 search_continue:
01181 if (RCLASS_CONST_TBL(klass) &&
01182 st_lookup(RCLASS_CONST_TBL(klass), id, &data)) {
01183 val = ((rb_const_entry_t*)data)->value;
01184 if (val == Qundef) {
01185 if (am == klass) break;
01186 am = klass;
01187 if (is_defined) return 1;
01188 rb_autoload_load(klass, id);
01189 goto search_continue;
01190 }
01191 else {
01192 if (is_defined) {
01193 return 1;
01194 }
01195 else {
01196 return val;
01197 }
01198 }
01199 }
01200 }
01201 }
01202
01203
01204 if (root_cref && !NIL_P(root_cref->nd_clss)) {
01205 klass = root_cref->nd_clss;
01206 }
01207 else {
01208 klass = CLASS_OF(th->cfp->self);
01209 }
01210
01211 if (is_defined) {
01212 return rb_const_defined(klass, id);
01213 }
01214 else {
01215 return rb_const_get(klass, id);
01216 }
01217 }
01218 else {
01219 vm_check_if_namespace(orig_klass);
01220 if (is_defined) {
01221 return rb_public_const_defined_from(orig_klass, id);
01222 }
01223 else {
01224 return rb_public_const_get_from(orig_klass, id);
01225 }
01226 }
01227 }
01228
01229 static inline VALUE
01230 vm_get_cvar_base(NODE *cref)
01231 {
01232 VALUE klass;
01233
01234 while (cref && cref->nd_next &&
01235 (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON) ||
01236 (cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL))) {
01237 cref = cref->nd_next;
01238
01239 if (!cref->nd_next) {
01240 rb_warn("class variable access from toplevel");
01241 }
01242 }
01243
01244 klass = cref->nd_clss;
01245
01246 if (NIL_P(klass)) {
01247 rb_raise(rb_eTypeError, "no class variables available");
01248 }
01249 return klass;
01250 }
01251
01252 static VALUE
01253 vm_search_const_defined_class(const VALUE cbase, ID id)
01254 {
01255 if (rb_const_defined_at(cbase, id)) return cbase;
01256 if (cbase == rb_cObject) {
01257 VALUE tmp = RCLASS_SUPER(cbase);
01258 while (tmp) {
01259 if (rb_const_defined_at(tmp, id)) return tmp;
01260 tmp = RCLASS_SUPER(tmp);
01261 }
01262 }
01263 return 0;
01264 }
01265
01266 #ifndef USE_IC_FOR_IVAR
01267 #define USE_IC_FOR_IVAR 1
01268 #endif
01269
01270 static VALUE
01271 vm_getivar(VALUE obj, ID id, IC ic)
01272 {
01273 #if USE_IC_FOR_IVAR
01274 if (TYPE(obj) == T_OBJECT) {
01275 VALUE val = Qundef;
01276 VALUE klass = RBASIC(obj)->klass;
01277
01278 if (LIKELY(ic->ic_class == klass &&
01279 ic->ic_vmstat == GET_VM_STATE_VERSION())) {
01280 long index = ic->ic_value.index;
01281 long len = ROBJECT_NUMIV(obj);
01282 VALUE *ptr = ROBJECT_IVPTR(obj);
01283
01284 if (index < len) {
01285 val = ptr[index];
01286 }
01287 }
01288 else {
01289 st_data_t index;
01290 long len = ROBJECT_NUMIV(obj);
01291 VALUE *ptr = ROBJECT_IVPTR(obj);
01292 struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
01293
01294 if (iv_index_tbl) {
01295 if (st_lookup(iv_index_tbl, id, &index)) {
01296 if ((long)index < len) {
01297 val = ptr[index];
01298 }
01299 ic->ic_class = klass;
01300 ic->ic_value.index = index;
01301 ic->ic_vmstat = GET_VM_STATE_VERSION();
01302 }
01303 }
01304 }
01305 if (UNLIKELY(val == Qundef)) {
01306 rb_warning("instance variable %s not initialized", rb_id2name(id));
01307 val = Qnil;
01308 }
01309 return val;
01310 }
01311 else {
01312 return rb_ivar_get(obj, id);
01313 }
01314 #else
01315 return rb_ivar_get(obj, id);
01316 #endif
01317 }
01318
01319 static void
01320 vm_setivar(VALUE obj, ID id, VALUE val, IC ic)
01321 {
01322 #if USE_IC_FOR_IVAR
01323 if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) {
01324 rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
01325 }
01326
01327 rb_check_frozen(obj);
01328
01329 if (TYPE(obj) == T_OBJECT) {
01330 VALUE klass = RBASIC(obj)->klass;
01331 st_data_t index;
01332
01333 if (LIKELY(ic->ic_class == klass &&
01334 ic->ic_vmstat == GET_VM_STATE_VERSION())) {
01335 long index = ic->ic_value.index;
01336 long len = ROBJECT_NUMIV(obj);
01337 VALUE *ptr = ROBJECT_IVPTR(obj);
01338
01339 if (index < len) {
01340 ptr[index] = val;
01341 return;
01342 }
01343 }
01344 else {
01345 struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
01346
01347 if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
01348 ic->ic_class = klass;
01349 ic->ic_value.index = index;
01350 ic->ic_vmstat = GET_VM_STATE_VERSION();
01351 }
01352
01353 }
01354 }
01355 rb_ivar_set(obj, id, val);
01356 #else
01357 rb_ivar_set(obj, id, val);
01358 #endif
01359 }
01360
01361 static inline const rb_method_entry_t *
01362 vm_method_search(VALUE id, VALUE klass, IC ic)
01363 {
01364 rb_method_entry_t *me;
01365 #if OPT_INLINE_METHOD_CACHE
01366 if (LIKELY(klass == ic->ic_class &&
01367 GET_VM_STATE_VERSION() == ic->ic_vmstat)) {
01368 me = ic->ic_value.method;
01369 }
01370 else {
01371 me = rb_method_entry(klass, id);
01372 ic->ic_class = klass;
01373 ic->ic_value.method = me;
01374 ic->ic_vmstat = GET_VM_STATE_VERSION();
01375 }
01376 #else
01377 me = rb_method_entry(klass, id);
01378 #endif
01379 return me;
01380 }
01381
01382 static inline VALUE
01383 vm_search_normal_superclass(VALUE klass, VALUE recv)
01384 {
01385 if (BUILTIN_TYPE(klass) == T_CLASS) {
01386 return RCLASS_SUPER(klass);
01387 }
01388 else if (BUILTIN_TYPE(klass) == T_MODULE) {
01389 VALUE k = CLASS_OF(recv);
01390 while (k) {
01391 if (BUILTIN_TYPE(k) == T_ICLASS && RBASIC(k)->klass == klass) {
01392 return RCLASS_SUPER(k);
01393 }
01394 k = RCLASS_SUPER(k);
01395 }
01396 return rb_cObject;
01397 }
01398 else {
01399 rb_bug("vm_search_normal_superclass: should not be reach here");
01400 }
01401 }
01402
01403 static void
01404 vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *iseq,
01405 VALUE recv, VALUE sigval,
01406 ID *idp, VALUE *klassp)
01407 {
01408 ID id;
01409 VALUE klass;
01410
01411 while (iseq && !iseq->klass) {
01412 iseq = iseq->parent_iseq;
01413 }
01414
01415 if (iseq == 0) {
01416 rb_raise(rb_eNoMethodError, "super called outside of method");
01417 }
01418
01419 id = iseq->defined_method_id;
01420
01421 if (iseq != iseq->local_iseq) {
01422
01423 rb_control_frame_t *lcfp = GET_CFP();
01424
01425 if (!sigval) {
01426
01427 rb_raise(rb_eRuntimeError, "implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly.");
01428 }
01429
01430 while (lcfp->iseq != iseq) {
01431 rb_thread_t *th = GET_THREAD();
01432 VALUE *tdfp = GET_PREV_DFP(lcfp->dfp);
01433 while (1) {
01434 lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp);
01435 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, lcfp)) {
01436 rb_raise(rb_eNoMethodError,
01437 "super called outside of method");
01438 }
01439 if (lcfp->dfp == tdfp) {
01440 break;
01441 }
01442 }
01443 }
01444
01445
01446 if (!lcfp->me) {
01447 rb_raise(rb_eNoMethodError, "super called outside of method");
01448 }
01449
01450 id = lcfp->me->def->original_id;
01451 klass = vm_search_normal_superclass(lcfp->me->klass, recv);
01452 }
01453 else {
01454 klass = vm_search_normal_superclass(iseq->klass, recv);
01455 }
01456
01457 *idp = id;
01458 *klassp = klass;
01459 }
01460
01461 static VALUE
01462 vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
01463 rb_num_t throw_state, VALUE throwobj)
01464 {
01465 int state = (int)(throw_state & 0xff);
01466 int flag = (int)(throw_state & 0x8000);
01467 rb_num_t level = throw_state >> 16;
01468
01469 if (state != 0) {
01470 VALUE *pt = 0;
01471 if (flag != 0) {
01472 pt = (void *) 1;
01473 }
01474 else {
01475 if (state == TAG_BREAK) {
01476 rb_control_frame_t *cfp = GET_CFP();
01477 VALUE *dfp = GET_DFP();
01478 int is_orphan = 1;
01479 rb_iseq_t *base_iseq = GET_ISEQ();
01480
01481 search_parent:
01482 if (cfp->iseq->type != ISEQ_TYPE_BLOCK) {
01483 if (cfp->iseq->type == ISEQ_TYPE_CLASS) {
01484 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01485 dfp = cfp->dfp;
01486 goto search_parent;
01487 }
01488 dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp);
01489 base_iseq = base_iseq->parent_iseq;
01490
01491 while ((VALUE *) cfp < th->stack + th->stack_size) {
01492 if (cfp->dfp == dfp) {
01493 goto search_parent;
01494 }
01495 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01496 }
01497 rb_bug("VM (throw): can't find break base.");
01498 }
01499
01500 if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
01501
01502 is_orphan = 0;
01503 pt = cfp->dfp;
01504 state = TAG_RETURN;
01505 }
01506 else {
01507 dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp);
01508
01509 while ((VALUE *)cfp < th->stack + th->stack_size) {
01510 if (cfp->dfp == dfp) {
01511 VALUE epc = cfp->pc - cfp->iseq->iseq_encoded;
01512 rb_iseq_t *iseq = cfp->iseq;
01513 int i;
01514
01515 for (i=0; i<iseq->catch_table_size; i++) {
01516 struct iseq_catch_table_entry *entry = &iseq->catch_table[i];
01517
01518 if (entry->type == CATCH_TYPE_BREAK &&
01519 entry->start < epc && entry->end >= epc) {
01520 if (entry->cont == epc) {
01521 goto found;
01522 }
01523 else {
01524 break;
01525 }
01526 }
01527 }
01528 break;
01529
01530 found:
01531 pt = dfp;
01532 is_orphan = 0;
01533 break;
01534 }
01535 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01536 }
01537 }
01538
01539 if (is_orphan) {
01540 rb_vm_localjump_error("break from proc-closure", throwobj, TAG_BREAK);
01541 }
01542 }
01543 else if (state == TAG_RETRY) {
01544 rb_num_t i;
01545 pt = GC_GUARDED_PTR_REF((VALUE *) * GET_DFP());
01546 for (i = 0; i < level; i++) {
01547 pt = GC_GUARDED_PTR_REF((VALUE *) * pt);
01548 }
01549 }
01550 else if (state == TAG_RETURN) {
01551 rb_control_frame_t *cfp = GET_CFP();
01552 VALUE *dfp = GET_DFP();
01553 VALUE *lfp = GET_LFP();
01554 int in_class_frame = 0;
01555
01556
01557 while ((VALUE *) cfp < th->stack + th->stack_size) {
01558 if (!lfp) {
01559 lfp = cfp->lfp;
01560 }
01561 if (cfp->dfp == lfp && cfp->iseq->type == ISEQ_TYPE_CLASS) {
01562 in_class_frame = 1;
01563 lfp = 0;
01564 }
01565
01566 if (cfp->lfp == lfp) {
01567 if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
01568 VALUE *tdfp = dfp;
01569
01570 if (in_class_frame) {
01571
01572 dfp = cfp->dfp;
01573 goto valid_return;
01574 }
01575
01576 while (lfp != tdfp) {
01577 if (cfp->dfp == tdfp) {
01578
01579 dfp = cfp->dfp;
01580 goto valid_return;
01581 }
01582 tdfp = GC_GUARDED_PTR_REF((VALUE *)*tdfp);
01583 }
01584 }
01585 }
01586
01587 if (cfp->dfp == lfp && cfp->iseq->type == ISEQ_TYPE_METHOD) {
01588 dfp = lfp;
01589 goto valid_return;
01590 }
01591
01592 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01593 }
01594
01595 rb_vm_localjump_error("unexpected return", throwobj, TAG_RETURN);
01596
01597 valid_return:
01598 pt = dfp;
01599 }
01600 else {
01601 rb_bug("isns(throw): unsupport throw type");
01602 }
01603 }
01604 th->state = state;
01605 return (VALUE)NEW_THROW_OBJECT(throwobj, (VALUE) pt, state);
01606 }
01607 else {
01608
01609 VALUE err = throwobj;
01610
01611 if (FIXNUM_P(err)) {
01612 th->state = FIX2INT(err);
01613 }
01614 else if (SYMBOL_P(err)) {
01615 th->state = TAG_THROW;
01616 }
01617 else if (BUILTIN_TYPE(err) == T_NODE) {
01618 th->state = GET_THROWOBJ_STATE(err);
01619 }
01620 else {
01621 th->state = TAG_RAISE;
01622
01623 }
01624 return err;
01625 }
01626 }
01627
01628 static inline void
01629 vm_expandarray(rb_control_frame_t *cfp, VALUE ary, rb_num_t num, int flag)
01630 {
01631 int is_splat = flag & 0x01;
01632 rb_num_t space_size = num + is_splat;
01633 VALUE *base = cfp->sp, *ptr;
01634 volatile VALUE tmp_ary;
01635 rb_num_t len;
01636
01637 if (TYPE(ary) != T_ARRAY) {
01638 ary = rb_ary_to_ary(ary);
01639 }
01640
01641 cfp->sp += space_size;
01642
01643 tmp_ary = ary;
01644 ptr = RARRAY_PTR(ary);
01645 len = (rb_num_t)RARRAY_LEN(ary);
01646
01647 if (flag & 0x02) {
01648
01649 rb_num_t i = 0, j;
01650
01651 if (len < num) {
01652 for (i=0; i<num-len; i++) {
01653 *base++ = Qnil;
01654 }
01655 }
01656 for (j=0; i<num; i++, j++) {
01657 VALUE v = ptr[len - j - 1];
01658 *base++ = v;
01659 }
01660 if (is_splat) {
01661 *base = rb_ary_new4(len - j, ptr);
01662 }
01663 }
01664 else {
01665
01666 rb_num_t i;
01667 VALUE *bptr = &base[space_size - 1];
01668
01669 for (i=0; i<num; i++) {
01670 if (len <= i) {
01671 for (; i<num; i++) {
01672 *bptr-- = Qnil;
01673 }
01674 break;
01675 }
01676 *bptr-- = ptr[i];
01677 }
01678 if (is_splat) {
01679 if (num > len) {
01680 *bptr = rb_ary_new();
01681 }
01682 else {
01683 *bptr = rb_ary_new4(len - num, ptr + num);
01684 }
01685 }
01686 }
01687 }
01688
01689 static inline int
01690 check_cfunc(const rb_method_entry_t *me, VALUE (*func)())
01691 {
01692 if (me && me->def->type == VM_METHOD_TYPE_CFUNC &&
01693 me->def->body.cfunc.func == func) {
01694 return 1;
01695 }
01696 else {
01697 return 0;
01698 }
01699 }
01700
01701 static
01702 #ifndef NO_BIG_INLINE
01703 inline
01704 #endif
01705 VALUE
01706 opt_eq_func(VALUE recv, VALUE obj, IC ic)
01707 {
01708 if (FIXNUM_2_P(recv, obj) &&
01709 BASIC_OP_UNREDEFINED_P(BOP_EQ)) {
01710 return (recv == obj) ? Qtrue : Qfalse;
01711 }
01712 else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
01713 if (HEAP_CLASS_OF(recv) == rb_cFloat &&
01714 HEAP_CLASS_OF(obj) == rb_cFloat &&
01715 BASIC_OP_UNREDEFINED_P(BOP_EQ)) {
01716 double a = RFLOAT_VALUE(recv);
01717 double b = RFLOAT_VALUE(obj);
01718
01719 if (isnan(a) || isnan(b)) {
01720 return Qfalse;
01721 }
01722 return (a == b) ? Qtrue : Qfalse;
01723 }
01724 else if (HEAP_CLASS_OF(recv) == rb_cString &&
01725 HEAP_CLASS_OF(obj) == rb_cString &&
01726 BASIC_OP_UNREDEFINED_P(BOP_EQ)) {
01727 return rb_str_equal(recv, obj);
01728 }
01729 }
01730
01731 {
01732 const rb_method_entry_t *me = vm_method_search(idEq, CLASS_OF(recv), ic);
01733
01734 if (check_cfunc(me, rb_obj_equal)) {
01735 return recv == obj ? Qtrue : Qfalse;
01736 }
01737 }
01738
01739 return Qundef;
01740 }
01741
01742