Ruby 1.9.3p327(2012-11-10revision37606)
|
00001 /********************************************************************** 00002 00003 vm_insnhelper.c - instruction helper functions. 00004 00005 $Author: kosaki $ 00006 00007 Copyright (C) 2007 Koichi Sasada 00008 00009 **********************************************************************/ 00010 00011 /* finish iseq array */ 00012 #include "insns.inc" 00013 #include <math.h> 00014 #include "constant.h" 00015 #include "internal.h" 00016 00017 /* control stack frame */ 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 /* setup vm value stack */ 00039 00040 /* nil initialize */ 00041 for (i=0; i < local_size; i++) { 00042 *sp = Qnil; 00043 sp++; 00044 } 00045 00046 /* set special val */ 00047 *sp = GC_GUARDED_PTR(specval); 00048 00049 if (lfp == 0) { 00050 lfp = sp; 00051 } 00052 00053 /* setup vm control frame stack */ 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 /* c method? */) { 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 /* method dispatch */ 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 /* simple check */ \ 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 /* mandatory */ 00160 if (argc < (m + iseq->arg_post_len)) { /* check with post arg */ 00161 argument_error(iseq, argc, m + iseq->arg_post_len); 00162 } 00163 00164 argv += m; 00165 argc -= m; 00166 00167 /* post arguments */ 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 /* opt arguments */ 00180 if (iseq->arg_opts) { 00181 const int opts = iseq->arg_opts - 1 /* no opt */; 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]; /* no opt */ 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 /* rest arguments */ 00203 if (iseq->arg_rest != -1) { 00204 orig_argv[iseq->arg_rest] = rb_ary_new4(argc, argv); 00205 argc = 0; 00206 } 00207 00208 /* block arguments */ 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 /* make Proc object */ 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; /* Proc or nil */ 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 /* expand top of stack? */ 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 /* do nothing */ 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 /* printf("len: %d, argc: %d\n", len, argc); */ 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; /* not reached */ 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 #ifdef __llvm__ 00410 #define RB_LLVM_GUARD(v) RB_GC_GUARD(v) 00411 RB_LLVM_GUARD(reg_cfp); 00412 #endif 00413 00414 vm_pop_frame(th); 00415 00416 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, me->called_id, me->klass); 00417 00418 return val; 00419 } 00420 00421 static inline VALUE 00422 vm_call_bmethod(rb_thread_t *th, VALUE recv, int argc, const VALUE *argv, 00423 const rb_block_t *blockptr, const rb_method_entry_t *me) 00424 { 00425 rb_proc_t *proc; 00426 VALUE val; 00427 00428 EXEC_EVENT_HOOK(th, RUBY_EVENT_CALL, recv, me->called_id, me->klass); 00429 00430 /* control block frame */ 00431 th->passed_me = me; 00432 GetProcPtr(me->def->body.proc, proc); 00433 val = rb_vm_invoke_proc(th, proc, recv, argc, argv, blockptr); 00434 00435 EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, recv, me->called_id, me->klass); 00436 00437 return val; 00438 } 00439 00440 static inline void 00441 vm_method_missing_args(rb_thread_t *th, VALUE *argv, 00442 int num, const rb_block_t *blockptr, int opt) 00443 { 00444 rb_control_frame_t * const reg_cfp = th->cfp; 00445 MEMCPY(argv, STACK_ADDR_FROM_TOP(num + 1), VALUE, num + 1); 00446 th->method_missing_reason = opt; 00447 th->passed_block = blockptr; 00448 POPN(num + 1); 00449 } 00450 00451 static inline VALUE 00452 vm_method_missing(rb_thread_t *th, ID id, VALUE recv, 00453 int num, const rb_block_t *blockptr, int opt) 00454 { 00455 VALUE *argv = ALLOCA_N(VALUE, num + 1); 00456 vm_method_missing_args(th, argv, num, blockptr, opt); 00457 argv[0] = ID2SYM(id); 00458 return rb_funcall2(recv, idMethodMissing, num + 1, argv); 00459 } 00460 00461 static inline void 00462 vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp, 00463 VALUE recv, int argc, const rb_block_t *blockptr, VALUE flag, 00464 const rb_method_entry_t *me) 00465 { 00466 int opt_pc, i; 00467 VALUE *sp, *rsp = cfp->sp - argc; 00468 rb_iseq_t *iseq = me->def->body.iseq; 00469 00470 VM_CALLEE_SETUP_ARG(opt_pc, th, iseq, argc, rsp, &blockptr); 00471 00472 /* stack overflow check */ 00473 CHECK_STACK_OVERFLOW(cfp, iseq->stack_max); 00474 00475 sp = rsp + iseq->arg_size; 00476 00477 if (LIKELY(!(flag & VM_CALL_TAILCALL_BIT))) { 00478 if (0) printf("local_size: %d, arg_size: %d\n", 00479 iseq->local_size, iseq->arg_size); 00480 00481 /* clear local variables */ 00482 for (i = 0; i < iseq->local_size - iseq->arg_size; i++) { 00483 *sp++ = Qnil; 00484 } 00485 00486 vm_push_frame(th, iseq, 00487 VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr, 00488 iseq->iseq_encoded + opt_pc, sp, 0, 0); 00489 00490 cfp->sp = rsp - 1 /* recv */; 00491 } 00492 else { 00493 VALUE *p_rsp; 00494 th->cfp++; /* pop cf */ 00495 p_rsp = th->cfp->sp; 00496 00497 /* copy arguments */ 00498 for (i=0; i < (sp - rsp); i++) { 00499 p_rsp[i] = rsp[i]; 00500 } 00501 00502 sp -= rsp - p_rsp; 00503 00504 /* clear local variables */ 00505 for (i = 0; i < iseq->local_size - iseq->arg_size; i++) { 00506 *sp++ = Qnil; 00507 } 00508 00509 vm_push_frame(th, iseq, 00510 VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr, 00511 iseq->iseq_encoded + opt_pc, sp, 0, 0); 00512 } 00513 } 00514 00515 static inline VALUE 00516 vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, 00517 int num, const rb_block_t *blockptr, VALUE flag, 00518 ID id, const rb_method_entry_t *me, VALUE recv) 00519 { 00520 VALUE val; 00521 00522 start_method_dispatch: 00523 00524 if (me != 0) { 00525 if ((me->flag == 0)) { 00526 normal_method_dispatch: 00527 switch (me->def->type) { 00528 case VM_METHOD_TYPE_ISEQ:{ 00529 vm_setup_method(th, cfp, recv, num, blockptr, flag, me); 00530 return Qundef; 00531 } 00532 case VM_METHOD_TYPE_NOTIMPLEMENTED: 00533 case VM_METHOD_TYPE_CFUNC:{ 00534 val = vm_call_cfunc(th, cfp, num, recv, blockptr, me); 00535 break; 00536 } 00537 case VM_METHOD_TYPE_ATTRSET:{ 00538 if (num != 1) { 00539 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", num); 00540 } 00541 val = rb_ivar_set(recv, me->def->body.attr.id, *(cfp->sp - 1)); 00542 cfp->sp -= 2; 00543 break; 00544 } 00545 case VM_METHOD_TYPE_IVAR:{ 00546 if (num != 0) { 00547 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", num); 00548 } 00549 val = rb_attr_get(recv, me->def->body.attr.id); 00550 cfp->sp -= 1; 00551 break; 00552 } 00553 case VM_METHOD_TYPE_MISSING:{ 00554 VALUE *argv = ALLOCA_N(VALUE, num+1); 00555 argv[0] = ID2SYM(me->def->original_id); 00556 MEMCPY(argv+1, cfp->sp - num, VALUE, num); 00557 cfp->sp += - num - 1; 00558 th->passed_block = blockptr; 00559 val = rb_funcall2(recv, rb_intern("method_missing"), num+1, argv); 00560 break; 00561 } 00562 case VM_METHOD_TYPE_BMETHOD:{ 00563 VALUE *argv = ALLOCA_N(VALUE, num); 00564 MEMCPY(argv, cfp->sp - num, VALUE, num); 00565 cfp->sp += - num - 1; 00566 val = vm_call_bmethod(th, recv, num, argv, blockptr, me); 00567 break; 00568 } 00569 case VM_METHOD_TYPE_ZSUPER:{ 00570 VALUE klass = RCLASS_SUPER(me->klass); 00571 me = rb_method_entry(klass, id); 00572 00573 if (me != 0) { 00574 goto normal_method_dispatch; 00575 } 00576 else { 00577 goto start_method_dispatch; 00578 } 00579 } 00580 case VM_METHOD_TYPE_OPTIMIZED:{ 00581 switch (me->def->body.optimize_type) { 00582 case OPTIMIZED_METHOD_TYPE_SEND: { 00583 rb_control_frame_t *reg_cfp = cfp; 00584 rb_num_t i = num - 1; 00585 VALUE sym; 00586 00587 if (num == 0) { 00588 rb_raise(rb_eArgError, "no method name given"); 00589 } 00590 00591 sym = TOPN(i); 00592 id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym); 00593 /* shift arguments */ 00594 if (i > 0) { 00595 MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i); 00596 } 00597 me = rb_method_entry(CLASS_OF(recv), id); 00598 num -= 1; 00599 DEC_SP(1); 00600 flag |= VM_CALL_FCALL_BIT | VM_CALL_OPT_SEND_BIT; 00601 00602 goto start_method_dispatch; 00603 } 00604 case OPTIMIZED_METHOD_TYPE_CALL: { 00605 rb_proc_t *proc; 00606 int argc = num; 00607 VALUE *argv = ALLOCA_N(VALUE, num); 00608 GetProcPtr(recv, proc); 00609 MEMCPY(argv, cfp->sp - num, VALUE, num); 00610 cfp->sp -= num + 1; 00611 00612 val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr); 00613 break; 00614 } 00615 default: 00616 rb_bug("eval_invoke_method: unsupported optimized method type (%d)", 00617 me->def->body.optimize_type); 00618 } 00619 break; 00620 } 00621 default:{ 00622 rb_bug("eval_invoke_method: unsupported method type (%d)", me->def->type); 00623 break; 00624 } 00625 } 00626 } 00627 else { 00628 int noex_safe; 00629 00630 if (!(flag & VM_CALL_FCALL_BIT) && 00631 (me->flag & NOEX_MASK) & NOEX_PRIVATE) { 00632 int stat = NOEX_PRIVATE; 00633 00634 if (flag & VM_CALL_VCALL_BIT) { 00635 stat |= NOEX_VCALL; 00636 } 00637 val = vm_method_missing(th, id, recv, num, blockptr, stat); 00638 } 00639 else if (!(flag & VM_CALL_OPT_SEND_BIT) && (me->flag & NOEX_MASK) & NOEX_PROTECTED) { 00640 VALUE defined_class = me->klass; 00641 00642 if (RB_TYPE_P(defined_class, T_ICLASS)) { 00643 defined_class = RBASIC(defined_class)->klass; 00644 } 00645 00646 if (!rb_obj_is_kind_of(cfp->self, defined_class)) { 00647 val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED); 00648 } 00649 else { 00650 goto normal_method_dispatch; 00651 } 00652 } 00653 else if ((noex_safe = NOEX_SAFE(me->flag)) > th->safe_level && 00654 (noex_safe > 2)) { 00655 rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(id)); 00656 } 00657 else { 00658 goto normal_method_dispatch; 00659 } 00660 } 00661 } 00662 else { 00663 /* method missing */ 00664 int stat = 0; 00665 if (flag & VM_CALL_VCALL_BIT) { 00666 stat |= NOEX_VCALL; 00667 } 00668 if (flag & VM_CALL_SUPER_BIT) { 00669 stat |= NOEX_SUPER; 00670 } 00671 if (id == idMethodMissing) { 00672 VALUE *argv = ALLOCA_N(VALUE, num); 00673 vm_method_missing_args(th, argv, num - 1, 0, stat); 00674 rb_raise_method_missing(th, num, argv, recv, stat); 00675 } 00676 else { 00677 val = vm_method_missing(th, id, recv, num, blockptr, stat); 00678 } 00679 } 00680 00681 RUBY_VM_CHECK_INTS(); 00682 return val; 00683 } 00684 00685 /* yield */ 00686 00687 static inline int 00688 block_proc_is_lambda(const VALUE procval) 00689 { 00690 rb_proc_t *proc; 00691 00692 if (procval) { 00693 GetProcPtr(procval, proc); 00694 return proc->is_lambda; 00695 } 00696 else { 00697 return 0; 00698 } 00699 } 00700 00701 static inline VALUE 00702 vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block, 00703 VALUE self, int argc, const VALUE *argv, 00704 const rb_block_t *blockargptr) 00705 { 00706 NODE *ifunc = (NODE *) block->iseq; 00707 VALUE val, arg, blockarg; 00708 int lambda = block_proc_is_lambda(block->proc); 00709 00710 if (lambda) { 00711 arg = rb_ary_new4(argc, argv); 00712 } 00713 else if (argc == 0) { 00714 arg = Qnil; 00715 } 00716 else { 00717 arg = argv[0]; 00718 } 00719 00720 if (blockargptr) { 00721 if (blockargptr->proc) { 00722 blockarg = blockargptr->proc; 00723 } 00724 else { 00725 blockarg = rb_vm_make_proc(th, blockargptr, rb_cProc); 00726 } 00727 } 00728 else { 00729 blockarg = Qnil; 00730 } 00731 00732 vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC, 00733 self, (VALUE)block->dfp, 00734 0, th->cfp->sp, block->lfp, 1); 00735 00736 if (blockargptr) { 00737 th->cfp->lfp[0] = GC_GUARDED_PTR((VALUE)blockargptr); 00738 } 00739 val = (*ifunc->nd_cfnc) (arg, ifunc->nd_tval, argc, argv, blockarg); 00740 00741 th->cfp++; 00742 return val; 00743 } 00744 00745 00746 /*-- 00747 * @brief on supplied all of optional, rest and post parameters. 00748 * @pre iseq is block style (not lambda style) 00749 */ 00750 static inline int 00751 vm_yield_setup_block_args_complex(rb_thread_t *th, const rb_iseq_t *iseq, 00752 int argc, VALUE *argv) 00753 { 00754 rb_num_t opt_pc = 0; 00755 int i; 00756 const int m = iseq->argc; 00757 const int r = iseq->arg_rest; 00758 int len = iseq->arg_post_len; 00759 int start = iseq->arg_post_start; 00760 int rsize = argc > m ? argc - m : 0; /* # of arguments which did not consumed yet */ 00761 int psize = rsize > len ? len : rsize; /* # of post arguments */ 00762 int osize = 0; /* # of opt arguments */ 00763 VALUE ary; 00764 00765 /* reserves arguments for post parameters */ 00766 rsize -= psize; 00767 00768 if (iseq->arg_opts) { 00769 const int opts = iseq->arg_opts - 1; 00770 if (rsize > opts) { 00771 osize = opts; 00772 opt_pc = iseq->arg_opt_table[opts]; 00773 } 00774 else { 00775 osize = rsize; 00776 opt_pc = iseq->arg_opt_table[rsize]; 00777 } 00778 } 00779 rsize -= osize; 00780 00781 if (0) { 00782 printf(" argc: %d\n", argc); 00783 printf(" len: %d\n", len); 00784 printf("start: %d\n", start); 00785 printf("rsize: %d\n", rsize); 00786 } 00787 00788 if (r == -1) { 00789 /* copy post argument */ 00790 MEMMOVE(&argv[start], &argv[m+osize], VALUE, psize); 00791 } 00792 else { 00793 ary = rb_ary_new4(rsize, &argv[r]); 00794 00795 /* copy post argument */ 00796 MEMMOVE(&argv[start], &argv[m+rsize+osize], VALUE, psize); 00797 argv[r] = ary; 00798 } 00799 00800 for (i=psize; i<len; i++) { 00801 argv[start + i] = Qnil; 00802 } 00803 00804 return (int)opt_pc; 00805 } 00806 00807 static inline int 00808 vm_yield_setup_block_args(rb_thread_t *th, const rb_iseq_t * iseq, 00809 int orig_argc, VALUE *argv, 00810 const rb_block_t *blockptr) 00811 { 00812 int i; 00813 int argc = orig_argc; 00814 const int m = iseq->argc; 00815 VALUE ary, arg0; 00816 int opt_pc = 0; 00817 00818 th->mark_stack_len = argc; 00819 00820 /* 00821 * yield [1, 2] 00822 * => {|a|} => a = [1, 2] 00823 * => {|a, b|} => a, b = [1, 2] 00824 */ 00825 arg0 = argv[0]; 00826 if (!(iseq->arg_simple & 0x02) && /* exclude {|a|} */ 00827 (m + iseq->arg_post_len) > 0 && /* this process is meaningful */ 00828 argc == 1 && !NIL_P(ary = rb_check_array_type(arg0))) { /* rhs is only an array */ 00829 th->mark_stack_len = argc = RARRAY_LENINT(ary); 00830 00831 CHECK_STACK_OVERFLOW(th->cfp, argc); 00832 00833 MEMCPY(argv, RARRAY_PTR(ary), VALUE, argc); 00834 } 00835 else { 00836 argv[0] = arg0; 00837 } 00838 00839 for (i=argc; i<m; i++) { 00840 argv[i] = Qnil; 00841 } 00842 00843 if (iseq->arg_rest == -1 && iseq->arg_opts == 0) { 00844 const int arg_size = iseq->arg_size; 00845 if (arg_size < argc) { 00846 /* 00847 * yield 1, 2 00848 * => {|a|} # truncate 00849 */ 00850 th->mark_stack_len = argc = arg_size; 00851 } 00852 } 00853 else { 00854 int r = iseq->arg_rest; 00855 00856 if (iseq->arg_post_len || 00857 iseq->arg_opts) { /* TODO: implement simple version for (iseq->arg_post_len==0 && iseq->arg_opts > 0) */ 00858 opt_pc = vm_yield_setup_block_args_complex(th, iseq, argc, argv); 00859 } 00860 else { 00861 if (argc < r) { 00862 /* yield 1 00863 * => {|a, b, *r|} 00864 */ 00865 for (i=argc; i<r; i++) { 00866 argv[i] = Qnil; 00867 } 00868 argv[r] = rb_ary_new(); 00869 } 00870 else { 00871 argv[r] = rb_ary_new4(argc-r, &argv[r]); 00872 } 00873 } 00874 00875 th->mark_stack_len = iseq->arg_size; 00876 } 00877 00878 /* {|&b|} */ 00879 if (iseq->arg_block != -1) { 00880 VALUE procval = Qnil; 00881 00882 if (blockptr) { 00883 if (blockptr->proc == 0) { 00884 procval = rb_vm_make_proc(th, blockptr, rb_cProc); 00885 } 00886 else { 00887 procval = blockptr->proc; 00888 } 00889 } 00890 00891 argv[iseq->arg_block] = procval; 00892 } 00893 00894 th->mark_stack_len = 0; 00895 return opt_pc; 00896 } 00897 00898 static inline int 00899 vm_yield_setup_args(rb_thread_t * const th, const rb_iseq_t *iseq, 00900 int argc, VALUE *argv, 00901 const rb_block_t *blockptr, int lambda) 00902 { 00903 if (0) { /* for debug */ 00904 printf(" argc: %d\n", argc); 00905 printf("iseq argc: %d\n", iseq->argc); 00906 printf("iseq opts: %d\n", iseq->arg_opts); 00907 printf("iseq rest: %d\n", iseq->arg_rest); 00908 printf("iseq post: %d\n", iseq->arg_post_len); 00909 printf("iseq blck: %d\n", iseq->arg_block); 00910 printf("iseq smpl: %d\n", iseq->arg_simple); 00911 printf(" lambda: %s\n", lambda ? "true" : "false"); 00912 } 00913 00914 if (lambda) { 00915 /* call as method */ 00916 int opt_pc; 00917 VM_CALLEE_SETUP_ARG(opt_pc, th, iseq, argc, argv, &blockptr); 00918 return opt_pc; 00919 } 00920 else { 00921 return vm_yield_setup_block_args(th, iseq, argc, argv, blockptr); 00922 } 00923 } 00924 00925 static VALUE 00926 vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_num_t flag) 00927 { 00928 const rb_block_t *block = GET_BLOCK_PTR(); 00929 rb_iseq_t *iseq; 00930 int argc = (int)num; 00931 VALUE type = GET_ISEQ()->local_iseq->type; 00932 00933 if ((type != ISEQ_TYPE_METHOD && type != ISEQ_TYPE_CLASS) || block == 0) { 00934 rb_vm_localjump_error("no block given (yield)", Qnil, 0); 00935 } 00936 iseq = block->iseq; 00937 00938 argc = caller_setup_args(th, GET_CFP(), flag, argc, 0, 0); 00939 00940 if (BUILTIN_TYPE(iseq) != T_NODE) { 00941 int opt_pc; 00942 const int arg_size = iseq->arg_size; 00943 VALUE * const rsp = GET_SP() - argc; 00944 SET_SP(rsp); 00945 00946 CHECK_STACK_OVERFLOW(GET_CFP(), iseq->stack_max); 00947 opt_pc = vm_yield_setup_args(th, iseq, argc, rsp, 0, 00948 block_proc_is_lambda(block->proc)); 00949 00950 vm_push_frame(th, iseq, 00951 VM_FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp, 00952 iseq->iseq_encoded + opt_pc, rsp + arg_size, block->lfp, 00953 iseq->local_size - arg_size); 00954 00955 return Qundef; 00956 } 00957 else { 00958 VALUE val = vm_yield_with_cfunc(th, block, block->self, argc, STACK_ADDR_FROM_TOP(argc), 0); 00959 POPN(argc); /* TODO: should put before C/yield? */ 00960 return val; 00961 } 00962 } 00963 00964 /* svar */ 00965 00966 static inline NODE * 00967 lfp_svar_place(rb_thread_t *th, VALUE *lfp) 00968 { 00969 VALUE *svar; 00970 00971 if (lfp && th->local_lfp != lfp) { 00972 svar = &lfp[-1]; 00973 } 00974 else { 00975 svar = &th->local_svar; 00976 } 00977 if (NIL_P(*svar)) { 00978 *svar = (VALUE)NEW_IF(Qnil, Qnil, Qnil); 00979 } 00980 return (NODE *)*svar; 00981 } 00982 00983 static VALUE 00984 lfp_svar_get(rb_thread_t *th, VALUE *lfp, VALUE key) 00985 { 00986 NODE *svar = lfp_svar_place(th, lfp); 00987 00988 switch (key) { 00989 case 0: 00990 return svar->u1.value; 00991 case 1: 00992 return svar->u2.value; 00993 default: { 00994 const VALUE hash = svar->u3.value; 00995 00996 if (hash == Qnil) { 00997 return Qnil; 00998 } 00999 else { 01000 return rb_hash_lookup(hash, key); 01001 } 01002 } 01003 } 01004 } 01005 01006 static void 01007 lfp_svar_set(rb_thread_t *th, VALUE *lfp, VALUE key, VALUE val) 01008 { 01009 NODE *svar = lfp_svar_place(th, lfp); 01010 01011 switch (key) { 01012 case 0: 01013 svar->u1.value = val; 01014 return; 01015 case 1: 01016 svar->u2.value = val; 01017 return; 01018 default: { 01019 VALUE hash = svar->u3.value; 01020 01021 if (hash == Qnil) { 01022 svar->u3.value = hash = rb_hash_new(); 01023 } 01024 rb_hash_aset(hash, key, val); 01025 } 01026 } 01027 } 01028 01029 static inline VALUE 01030 vm_getspecial(rb_thread_t *th, VALUE *lfp, VALUE key, rb_num_t type) 01031 { 01032 VALUE val; 01033 01034 if (type == 0) { 01035 VALUE k = key; 01036 if (FIXNUM_P(key)) { 01037 k = FIX2INT(key); 01038 } 01039 val = lfp_svar_get(th, lfp, k); 01040 } 01041 else { 01042 VALUE backref = lfp_svar_get(th, lfp, 1); 01043 01044 if (type & 0x01) { 01045 switch (type >> 1) { 01046 case '&': 01047 val = rb_reg_last_match(backref); 01048 break; 01049 case '`': 01050 val = rb_reg_match_pre(backref); 01051 break; 01052 case '\'': 01053 val = rb_reg_match_post(backref); 01054 break; 01055 case '+': 01056 val = rb_reg_match_last(backref); 01057 break; 01058 default: 01059 rb_bug("unexpected back-ref"); 01060 } 01061 } 01062 else { 01063 val = rb_reg_nth_match((int)(type >> 1), backref); 01064 } 01065 } 01066 return val; 01067 } 01068 01069 static NODE * 01070 vm_get_cref0(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp) 01071 { 01072 while (1) { 01073 if (lfp == dfp) { 01074 if (!RUBY_VM_NORMAL_ISEQ_P(iseq)) return NULL; 01075 return iseq->cref_stack; 01076 } 01077 else if (dfp[-1] != Qnil) { 01078 return (NODE *)dfp[-1]; 01079 } 01080 dfp = GET_PREV_DFP(dfp); 01081 } 01082 } 01083 01084 static NODE * 01085 vm_get_cref(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp) 01086 { 01087 NODE *cref = vm_get_cref0(iseq, lfp, dfp); 01088 01089 if (cref == 0) { 01090 rb_bug("vm_get_cref: unreachable"); 01091 } 01092 return cref; 01093 } 01094 01095 static NODE * 01096 vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr) 01097 { 01098 rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp); 01099 NODE *cref = NEW_BLOCK(klass); 01100 cref->nd_visi = noex; 01101 01102 if (blockptr) { 01103 cref->nd_next = vm_get_cref0(blockptr->iseq, blockptr->lfp, blockptr->dfp); 01104 } 01105 else if (cfp) { 01106 cref->nd_next = vm_get_cref0(cfp->iseq, cfp->lfp, cfp->dfp); 01107 } 01108 01109 return cref; 01110 } 01111 01112 static inline VALUE 01113 vm_get_cbase(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp) 01114 { 01115 NODE *cref = vm_get_cref(iseq, lfp, dfp); 01116 VALUE klass = Qundef; 01117 01118 while (cref) { 01119 if ((klass = cref->nd_clss) != 0) { 01120 break; 01121 } 01122 cref = cref->nd_next; 01123 } 01124 01125 return klass; 01126 } 01127 01128 static inline VALUE 01129 vm_get_const_base(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp) 01130 { 01131 NODE *cref = vm_get_cref(iseq, lfp, dfp); 01132 VALUE klass = Qundef; 01133 01134 while (cref) { 01135 if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) && 01136 (klass = cref->nd_clss) != 0) { 01137 break; 01138 } 01139 cref = cref->nd_next; 01140 } 01141 01142 return klass; 01143 } 01144 01145 static inline void 01146 vm_check_if_namespace(VALUE klass) 01147 { 01148 VALUE str; 01149 switch (TYPE(klass)) { 01150 case T_CLASS: 01151 case T_MODULE: 01152 break; 01153 default: 01154 str = rb_inspect(klass); 01155 rb_raise(rb_eTypeError, "%s is not a class/module", 01156 StringValuePtr(str)); 01157 } 01158 } 01159 01160 static inline VALUE 01161 vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq, 01162 VALUE orig_klass, ID id, int is_defined) 01163 { 01164 VALUE val; 01165 01166 if (orig_klass == Qnil) { 01167 /* in current lexical scope */ 01168 const NODE *root_cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp); 01169 const NODE *cref; 01170 VALUE klass = orig_klass; 01171 01172 while (root_cref && root_cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) { 01173 root_cref = root_cref->nd_next; 01174 } 01175 cref = root_cref; 01176 while (cref && cref->nd_next) { 01177 if (cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) { 01178 klass = Qnil; 01179 } 01180 else { 01181 klass = cref->nd_clss; 01182 } 01183 cref = cref->nd_next; 01184 01185 if (!NIL_P(klass)) { 01186 VALUE am = 0; 01187 st_data_t data; 01188 search_continue: 01189 if (RCLASS_CONST_TBL(klass) && 01190 st_lookup(RCLASS_CONST_TBL(klass), id, &data)) { 01191 val = ((rb_const_entry_t*)data)->value; 01192 if (val == Qundef) { 01193 if (am == klass) break; 01194 am = klass; 01195 if (is_defined) return 1; 01196 rb_autoload_load(klass, id); 01197 goto search_continue; 01198 } 01199 else { 01200 if (is_defined) { 01201 return 1; 01202 } 01203 else { 01204 return val; 01205 } 01206 } 01207 } 01208 } 01209 } 01210 01211 /* search self */ 01212 if (root_cref && !NIL_P(root_cref->nd_clss)) { 01213 klass = root_cref->nd_clss; 01214 } 01215 else { 01216 klass = CLASS_OF(th->cfp->self); 01217 } 01218 01219 if (is_defined) { 01220 return rb_const_defined(klass, id); 01221 } 01222 else { 01223 return rb_const_get(klass, id); 01224 } 01225 } 01226 else { 01227 vm_check_if_namespace(orig_klass); 01228 if (is_defined) { 01229 return rb_public_const_defined_from(orig_klass, id); 01230 } 01231 else { 01232 return rb_public_const_get_from(orig_klass, id); 01233 } 01234 } 01235 } 01236 01237 static inline VALUE 01238 vm_get_cvar_base(NODE *cref) 01239 { 01240 VALUE klass; 01241 01242 while (cref && cref->nd_next && 01243 (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON) || 01244 (cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL))) { 01245 cref = cref->nd_next; 01246 01247 if (!cref->nd_next) { 01248 rb_warn("class variable access from toplevel"); 01249 } 01250 } 01251 01252 klass = cref->nd_clss; 01253 01254 if (NIL_P(klass)) { 01255 rb_raise(rb_eTypeError, "no class variables available"); 01256 } 01257 return klass; 01258 } 01259 01260 static VALUE 01261 vm_search_const_defined_class(const VALUE cbase, ID id) 01262 { 01263 if (rb_const_defined_at(cbase, id)) return cbase; 01264 if (cbase == rb_cObject) { 01265 VALUE tmp = RCLASS_SUPER(cbase); 01266 while (tmp) { 01267 if (rb_const_defined_at(tmp, id)) return tmp; 01268 tmp = RCLASS_SUPER(tmp); 01269 } 01270 } 01271 return 0; 01272 } 01273 01274 #ifndef USE_IC_FOR_IVAR 01275 #define USE_IC_FOR_IVAR 1 01276 #endif 01277 01278 static VALUE 01279 vm_getivar(VALUE obj, ID id, IC ic) 01280 { 01281 #if USE_IC_FOR_IVAR 01282 if (TYPE(obj) == T_OBJECT) { 01283 VALUE val = Qundef; 01284 VALUE klass = RBASIC(obj)->klass; 01285 01286 if (LIKELY(ic->ic_class == klass && 01287 ic->ic_vmstat == GET_VM_STATE_VERSION())) { 01288 long index = ic->ic_value.index; 01289 long len = ROBJECT_NUMIV(obj); 01290 VALUE *ptr = ROBJECT_IVPTR(obj); 01291 01292 if (index < len) { 01293 val = ptr[index]; 01294 } 01295 } 01296 else { 01297 st_data_t index; 01298 long len = ROBJECT_NUMIV(obj); 01299 VALUE *ptr = ROBJECT_IVPTR(obj); 01300 struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); 01301 01302 if (iv_index_tbl) { 01303 if (st_lookup(iv_index_tbl, id, &index)) { 01304 if ((long)index < len) { 01305 val = ptr[index]; 01306 } 01307 ic->ic_class = klass; 01308 ic->ic_value.index = index; 01309 ic->ic_vmstat = GET_VM_STATE_VERSION(); 01310 } 01311 } 01312 } 01313 if (UNLIKELY(val == Qundef)) { 01314 rb_warning("instance variable %s not initialized", rb_id2name(id)); 01315 val = Qnil; 01316 } 01317 return val; 01318 } 01319 else { 01320 return rb_ivar_get(obj, id); 01321 } 01322 #else 01323 return rb_ivar_get(obj, id); 01324 #endif 01325 } 01326 01327 static void 01328 vm_setivar(VALUE obj, ID id, VALUE val, IC ic) 01329 { 01330 #if USE_IC_FOR_IVAR 01331 if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) { 01332 rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable"); 01333 } 01334 01335 rb_check_frozen(obj); 01336 01337 if (TYPE(obj) == T_OBJECT) { 01338 VALUE klass = RBASIC(obj)->klass; 01339 st_data_t index; 01340 01341 if (LIKELY(ic->ic_class == klass && 01342 ic->ic_vmstat == GET_VM_STATE_VERSION())) { 01343 long index = ic->ic_value.index; 01344 long len = ROBJECT_NUMIV(obj); 01345 VALUE *ptr = ROBJECT_IVPTR(obj); 01346 01347 if (index < len) { 01348 ptr[index] = val; 01349 return; /* inline cache hit */ 01350 } 01351 } 01352 else { 01353 struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); 01354 01355 if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) { 01356 ic->ic_class = klass; 01357 ic->ic_value.index = index; 01358 ic->ic_vmstat = GET_VM_STATE_VERSION(); 01359 } 01360 /* fall through */ 01361 } 01362 } 01363 rb_ivar_set(obj, id, val); 01364 #else 01365 rb_ivar_set(obj, id, val); 01366 #endif 01367 } 01368 01369 static inline const rb_method_entry_t * 01370 vm_method_search(VALUE id, VALUE klass, IC ic) 01371 { 01372 rb_method_entry_t *me; 01373 #if OPT_INLINE_METHOD_CACHE 01374 if (LIKELY(klass == ic->ic_class && 01375 GET_VM_STATE_VERSION() == ic->ic_vmstat)) { 01376 me = ic->ic_value.method; 01377 } 01378 else { 01379 me = rb_method_entry(klass, id); 01380 ic->ic_class = klass; 01381 ic->ic_value.method = me; 01382 ic->ic_vmstat = GET_VM_STATE_VERSION(); 01383 } 01384 #else 01385 me = rb_method_entry(klass, id); 01386 #endif 01387 return me; 01388 } 01389 01390 static inline VALUE 01391 vm_search_normal_superclass(VALUE klass, VALUE recv) 01392 { 01393 if (BUILTIN_TYPE(klass) == T_CLASS) { 01394 return RCLASS_SUPER(klass); 01395 } 01396 else if (BUILTIN_TYPE(klass) == T_MODULE) { 01397 VALUE k = CLASS_OF(recv); 01398 while (k) { 01399 if (BUILTIN_TYPE(k) == T_ICLASS && RBASIC(k)->klass == klass) { 01400 return RCLASS_SUPER(k); 01401 } 01402 k = RCLASS_SUPER(k); 01403 } 01404 return rb_cObject; 01405 } 01406 else { 01407 rb_bug("vm_search_normal_superclass: should not be reach here"); 01408 } 01409 } 01410 01411 static void 01412 vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *iseq, 01413 VALUE recv, VALUE sigval, 01414 ID *idp, VALUE *klassp) 01415 { 01416 ID id; 01417 VALUE klass; 01418 01419 while (iseq && !iseq->klass) { 01420 iseq = iseq->parent_iseq; 01421 } 01422 01423 if (iseq == 0) { 01424 rb_raise(rb_eNoMethodError, "super called outside of method"); 01425 } 01426 01427 id = iseq->defined_method_id; 01428 01429 if (iseq != iseq->local_iseq) { 01430 /* defined by Module#define_method() */ 01431 rb_control_frame_t *lcfp = GET_CFP(); 01432 01433 if (!sigval) { 01434 /* zsuper */ 01435 rb_raise(rb_eRuntimeError, "implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly."); 01436 } 01437 01438 while (lcfp->iseq != iseq) { 01439 rb_thread_t *th = GET_THREAD(); 01440 VALUE *tdfp = GET_PREV_DFP(lcfp->dfp); 01441 while (1) { 01442 lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp); 01443 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, lcfp)) { 01444 rb_raise(rb_eNoMethodError, 01445 "super called outside of method"); 01446 } 01447 if (lcfp->dfp == tdfp) { 01448 break; 01449 } 01450 } 01451 } 01452 01453 /* temporary measure for [Bug #2420] [Bug #3136] */ 01454 if (!lcfp->me) { 01455 rb_raise(rb_eNoMethodError, "super called outside of method"); 01456 } 01457 01458 id = lcfp->me->def->original_id; 01459 klass = vm_search_normal_superclass(lcfp->me->klass, recv); 01460 } 01461 else { 01462 klass = vm_search_normal_superclass(iseq->klass, recv); 01463 } 01464 01465 *idp = id; 01466 *klassp = klass; 01467 } 01468 01469 static VALUE 01470 vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, 01471 rb_num_t throw_state, VALUE throwobj) 01472 { 01473 int state = (int)(throw_state & 0xff); 01474 int flag = (int)(throw_state & 0x8000); 01475 rb_num_t level = throw_state >> 16; 01476 01477 if (state != 0) { 01478 VALUE *pt = 0; 01479 if (flag != 0) { 01480 pt = (void *) 1; 01481 } 01482 else { 01483 if (state == TAG_BREAK) { 01484 rb_control_frame_t *cfp = GET_CFP(); 01485 VALUE *dfp = GET_DFP(); 01486 int is_orphan = 1; 01487 rb_iseq_t *base_iseq = GET_ISEQ(); 01488 01489 search_parent: 01490 if (cfp->iseq->type != ISEQ_TYPE_BLOCK) { 01491 if (cfp->iseq->type == ISEQ_TYPE_CLASS) { 01492 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); 01493 dfp = cfp->dfp; 01494 goto search_parent; 01495 } 01496 dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp); 01497 base_iseq = base_iseq->parent_iseq; 01498 01499 while ((VALUE *) cfp < th->stack + th->stack_size) { 01500 if (cfp->dfp == dfp) { 01501 goto search_parent; 01502 } 01503 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); 01504 } 01505 rb_bug("VM (throw): can't find break base."); 01506 } 01507 01508 if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) { 01509 /* lambda{... break ...} */ 01510 is_orphan = 0; 01511 pt = cfp->dfp; 01512 state = TAG_RETURN; 01513 } 01514 else { 01515 dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp); 01516 01517 while ((VALUE *)cfp < th->stack + th->stack_size) { 01518 if (cfp->dfp == dfp) { 01519 VALUE epc = cfp->pc - cfp->iseq->iseq_encoded; 01520 rb_iseq_t *iseq = cfp->iseq; 01521 int i; 01522 01523 for (i=0; i<iseq->catch_table_size; i++) { 01524 struct iseq_catch_table_entry *entry = &iseq->catch_table[i]; 01525 01526 if (entry->type == CATCH_TYPE_BREAK && 01527 entry->start < epc && entry->end >= epc) { 01528 if (entry->cont == epc) { 01529 goto found; 01530 } 01531 else { 01532 break; 01533 } 01534 } 01535 } 01536 break; 01537 01538 found: 01539 pt = dfp; 01540 is_orphan = 0; 01541 break; 01542 } 01543 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); 01544 } 01545 } 01546 01547 if (is_orphan) { 01548 rb_vm_localjump_error("break from proc-closure", throwobj, TAG_BREAK); 01549 } 01550 } 01551 else if (state == TAG_RETRY) { 01552 rb_num_t i; 01553 pt = GC_GUARDED_PTR_REF((VALUE *) * GET_DFP()); 01554 for (i = 0; i < level; i++) { 01555 pt = GC_GUARDED_PTR_REF((VALUE *) * pt); 01556 } 01557 } 01558 else if (state == TAG_RETURN) { 01559 rb_control_frame_t *cfp = GET_CFP(); 01560 VALUE *dfp = GET_DFP(); 01561 VALUE *lfp = GET_LFP(); 01562 int in_class_frame = 0; 01563 01564 /* check orphan and get dfp */ 01565 while ((VALUE *) cfp < th->stack + th->stack_size) { 01566 if (!lfp) { 01567 lfp = cfp->lfp; 01568 } 01569 if (cfp->dfp == lfp && cfp->iseq->type == ISEQ_TYPE_CLASS) { 01570 in_class_frame = 1; 01571 lfp = 0; 01572 } 01573 01574 if (cfp->lfp == lfp) { 01575 if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) { 01576 VALUE *tdfp = dfp; 01577 01578 if (in_class_frame) { 01579 /* lambda {class A; ... return ...; end} */ 01580 dfp = cfp->dfp; 01581 goto valid_return; 01582 } 01583 01584 while (lfp != tdfp) { 01585 if (cfp->dfp == tdfp) { 01586 /* in lambda */ 01587 dfp = cfp->dfp; 01588 goto valid_return; 01589 } 01590 tdfp = GC_GUARDED_PTR_REF((VALUE *)*tdfp); 01591 } 01592 } 01593 } 01594 01595 if (cfp->dfp == lfp && cfp->iseq->type == ISEQ_TYPE_METHOD) { 01596 dfp = lfp; 01597 goto valid_return; 01598 } 01599 01600 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); 01601 } 01602 01603 rb_vm_localjump_error("unexpected return", throwobj, TAG_RETURN); 01604 01605 valid_return: 01606 pt = dfp; 01607 } 01608 else { 01609 rb_bug("isns(throw): unsupport throw type"); 01610 } 01611 } 01612 th->state = state; 01613 return (VALUE)NEW_THROW_OBJECT(throwobj, (VALUE) pt, state); 01614 } 01615 else { 01616 /* continue throw */ 01617 VALUE err = throwobj; 01618 01619 if (FIXNUM_P(err)) { 01620 th->state = FIX2INT(err); 01621 } 01622 else if (SYMBOL_P(err)) { 01623 th->state = TAG_THROW; 01624 } 01625 else if (BUILTIN_TYPE(err) == T_NODE) { 01626 th->state = GET_THROWOBJ_STATE(err); 01627 } 01628 else { 01629 th->state = TAG_RAISE; 01630 /*th->state = FIX2INT(rb_ivar_get(err, idThrowState));*/ 01631 } 01632 return err; 01633 } 01634 } 01635 01636 static inline void 01637 vm_expandarray(rb_control_frame_t *cfp, VALUE ary, rb_num_t num, int flag) 01638 { 01639 int is_splat = flag & 0x01; 01640 rb_num_t space_size = num + is_splat; 01641 VALUE *base = cfp->sp, *ptr; 01642 volatile VALUE tmp_ary; 01643 rb_num_t len; 01644 01645 if (TYPE(ary) != T_ARRAY) { 01646 ary = rb_ary_to_ary(ary); 01647 } 01648 01649 cfp->sp += space_size; 01650 01651 tmp_ary = ary; 01652 ptr = RARRAY_PTR(ary); 01653 len = (rb_num_t)RARRAY_LEN(ary); 01654 01655 if (flag & 0x02) { 01656 /* post: ..., nil ,ary[-1], ..., ary[0..-num] # top */ 01657 rb_num_t i = 0, j; 01658 01659 if (len < num) { 01660 for (i=0; i<num-len; i++) { 01661 *base++ = Qnil; 01662 } 01663 } 01664 for (j=0; i<num; i++, j++) { 01665 VALUE v = ptr[len - j - 1]; 01666 *base++ = v; 01667 } 01668 if (is_splat) { 01669 *base = rb_ary_new4(len - j, ptr); 01670 } 01671 } 01672 else { 01673 /* normal: ary[num..-1], ary[num-2], ary[num-3], ..., ary[0] # top */ 01674 rb_num_t i; 01675 VALUE *bptr = &base[space_size - 1]; 01676 01677 for (i=0; i<num; i++) { 01678 if (len <= i) { 01679 for (; i<num; i++) { 01680 *bptr-- = Qnil; 01681 } 01682 break; 01683 } 01684 *bptr-- = ptr[i]; 01685 } 01686 if (is_splat) { 01687 if (num > len) { 01688 *bptr = rb_ary_new(); 01689 } 01690 else { 01691 *bptr = rb_ary_new4(len - num, ptr + num); 01692 } 01693 } 01694 } 01695 } 01696 01697 static inline int 01698 check_cfunc(const rb_method_entry_t *me, VALUE (*func)()) 01699 { 01700 if (me && me->def->type == VM_METHOD_TYPE_CFUNC && 01701 me->def->body.cfunc.func == func) { 01702 return 1; 01703 } 01704 else { 01705 return 0; 01706 } 01707 } 01708 01709 static 01710 #ifndef NO_BIG_INLINE 01711 inline 01712 #endif 01713 VALUE 01714 opt_eq_func(VALUE recv, VALUE obj, IC ic) 01715 { 01716 if (FIXNUM_2_P(recv, obj) && 01717 BASIC_OP_UNREDEFINED_P(BOP_EQ)) { 01718 return (recv == obj) ? Qtrue : Qfalse; 01719 } 01720 else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { 01721 if (HEAP_CLASS_OF(recv) == rb_cFloat && 01722 HEAP_CLASS_OF(obj) == rb_cFloat && 01723 BASIC_OP_UNREDEFINED_P(BOP_EQ)) { 01724 double a = RFLOAT_VALUE(recv); 01725 double b = RFLOAT_VALUE(obj); 01726 01727 if (isnan(a) || isnan(b)) { 01728 return Qfalse; 01729 } 01730 return (a == b) ? Qtrue : Qfalse; 01731 } 01732 else if (HEAP_CLASS_OF(recv) == rb_cString && 01733 HEAP_CLASS_OF(obj) == rb_cString && 01734 BASIC_OP_UNREDEFINED_P(BOP_EQ)) { 01735 return rb_str_equal(recv, obj); 01736 } 01737 } 01738 01739 { 01740 const rb_method_entry_t *me = vm_method_search(idEq, CLASS_OF(recv), ic); 01741 01742 if (check_cfunc(me, rb_obj_equal)) { 01743 return recv == obj ? Qtrue : Qfalse; 01744 } 01745 } 01746 01747 return Qundef; 01748 } 01749 01750