1 /**********************************************************************
2
3 vm_eval.c -
4
5 $Author: nagachika $
6 created at: Sat May 24 16:02:32 JST 2008
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
11
12 **********************************************************************/
13
14 struct local_var_list {
15 VALUE tbl;
16 };
17
18 static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status);
19 static inline VALUE vm_yield_with_cref(rb_execution_context_t *ec, int argc, const VALUE *argv, const rb_cref_t *cref, int is_lambda);
20 static inline VALUE vm_yield(rb_execution_context_t *ec, int argc, const VALUE *argv);
21 static inline VALUE vm_yield_with_block(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE block_handler);
22 static inline VALUE vm_yield_force_blockarg(rb_execution_context_t *ec, VALUE args);
23 VALUE vm_exec(rb_execution_context_t *ec, int mjit_enable_p);
24 static void vm_set_eval_stack(rb_execution_context_t * th, const rb_iseq_t *iseq, const rb_cref_t *cref, const struct rb_block *base_block);
25 static int vm_collect_local_variables_in_heap(const VALUE *dfp, const struct local_var_list *vars);
26
27 static VALUE rb_eUncaughtThrow;
28 static ID id_result, id_tag, id_value;
29 #define id_mesg idMesg
30
31 typedef enum call_type {
32 CALL_PUBLIC,
33 CALL_FCALL,
34 CALL_VCALL,
35 CALL_TYPE_MAX
36 } call_type;
37
38 static VALUE send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope);
39 static VALUE vm_call0_body(rb_execution_context_t* ec, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc, const VALUE *argv);
40
41 #ifndef MJIT_HEADER
42
43 MJIT_FUNC_EXPORTED VALUE
rb_vm_call0(rb_execution_context_t * ec,VALUE recv,ID id,int argc,const VALUE * argv,const rb_callable_method_entry_t * me)44 rb_vm_call0(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me)
45 {
46 struct rb_calling_info calling_entry, *calling;
47 struct rb_call_info ci_entry;
48 struct rb_call_cache cc_entry;
49
50 calling = &calling_entry;
51
52 ci_entry.flag = 0;
53 ci_entry.mid = id;
54
55 cc_entry.me = me;
56
57 calling->recv = recv;
58 calling->argc = argc;
59
60 return vm_call0_body(ec, calling, &ci_entry, &cc_entry, argv);
61 }
62
63 static VALUE
vm_call0_cfunc_with_frame(rb_execution_context_t * ec,struct rb_calling_info * calling,const struct rb_call_info * ci,struct rb_call_cache * cc,const VALUE * argv)64 vm_call0_cfunc_with_frame(rb_execution_context_t* ec, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc, const VALUE *argv)
65 {
66 VALUE val;
67 const rb_callable_method_entry_t *me = cc->me;
68 const rb_method_cfunc_t *cfunc = &me->def->body.cfunc;
69 int len = cfunc->argc;
70 VALUE recv = calling->recv;
71 int argc = calling->argc;
72 ID mid = ci->mid;
73 VALUE block_handler = calling->block_handler;
74
75 RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
76 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, recv, me->def->original_id, mid, me->owner, Qnil);
77 {
78 rb_control_frame_t *reg_cfp = ec->cfp;
79
80 vm_push_frame(ec, 0, VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL, recv,
81 block_handler, (VALUE)me,
82 0, reg_cfp->sp, 0, 0);
83
84 if (len >= 0) rb_check_arity(argc, len, len);
85
86 val = (*cfunc->invoker)(cfunc->func, recv, argc, argv);
87
88 CHECK_CFP_CONSISTENCY("vm_call0_cfunc_with_frame");
89 rb_vm_pop_frame(ec);
90 }
91 EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, recv, me->def->original_id, mid, me->owner, val);
92 RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
93
94 return val;
95 }
96
97 static VALUE
vm_call0_cfunc(rb_execution_context_t * ec,struct rb_calling_info * calling,const struct rb_call_info * ci,struct rb_call_cache * cc,const VALUE * argv)98 vm_call0_cfunc(rb_execution_context_t *ec, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc, const VALUE *argv)
99 {
100 return vm_call0_cfunc_with_frame(ec, calling, ci, cc, argv);
101 }
102
103 /* `ci' should point temporal value (on stack value) */
104 static VALUE
vm_call0_body(rb_execution_context_t * ec,struct rb_calling_info * calling,const struct rb_call_info * ci,struct rb_call_cache * cc,const VALUE * argv)105 vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc, const VALUE *argv)
106 {
107 VALUE ret;
108
109 calling->block_handler = vm_passed_block_handler(ec);
110
111 again:
112 switch (cc->me->def->type) {
113 case VM_METHOD_TYPE_ISEQ:
114 {
115 rb_control_frame_t *reg_cfp = ec->cfp;
116 int i;
117
118 CHECK_VM_STACK_OVERFLOW(reg_cfp, calling->argc + 1);
119
120 *reg_cfp->sp++ = calling->recv;
121 for (i = 0; i < calling->argc; i++) {
122 *reg_cfp->sp++ = argv[i];
123 }
124
125 vm_call_iseq_setup(ec, reg_cfp, calling, ci, cc);
126 VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);
127 return vm_exec(ec, TRUE); /* CHECK_INTS in this function */
128 }
129 case VM_METHOD_TYPE_NOTIMPLEMENTED:
130 case VM_METHOD_TYPE_CFUNC:
131 ret = vm_call0_cfunc(ec, calling, ci, cc, argv);
132 goto success;
133 case VM_METHOD_TYPE_ATTRSET:
134 rb_check_arity(calling->argc, 1, 1);
135 ret = rb_ivar_set(calling->recv, cc->me->def->body.attr.id, argv[0]);
136 goto success;
137 case VM_METHOD_TYPE_IVAR:
138 rb_check_arity(calling->argc, 0, 0);
139 ret = rb_attr_get(calling->recv, cc->me->def->body.attr.id);
140 goto success;
141 case VM_METHOD_TYPE_BMETHOD:
142 ret = vm_call_bmethod_body(ec, calling, ci, cc, argv);
143 goto success;
144 case VM_METHOD_TYPE_ZSUPER:
145 case VM_METHOD_TYPE_REFINED:
146 {
147 const rb_method_type_t type = cc->me->def->type;
148 VALUE super_class = cc->me->defined_class;
149
150 if (type == VM_METHOD_TYPE_ZSUPER) {
151 super_class = RCLASS_ORIGIN(super_class);
152 }
153 else if (cc->me->def->body.refined.orig_me) {
154 cc->me = refined_method_callable_without_refinement(cc->me);
155 goto again;
156 }
157
158 super_class = RCLASS_SUPER(super_class);
159
160 if (!super_class || !(cc->me = rb_callable_method_entry(super_class, ci->mid))) {
161 enum method_missing_reason ex = (type == VM_METHOD_TYPE_ZSUPER) ? MISSING_SUPER : 0;
162 ret = method_missing(calling->recv, ci->mid, calling->argc, argv, ex);
163 goto success;
164 }
165 RUBY_VM_CHECK_INTS(ec);
166 goto again;
167 }
168 case VM_METHOD_TYPE_ALIAS:
169 cc->me = aliased_callable_method_entry(cc->me);
170 goto again;
171 case VM_METHOD_TYPE_MISSING:
172 {
173 vm_passed_block_handler_set(ec, calling->block_handler);
174 return method_missing(calling->recv, ci->mid, calling->argc,
175 argv, MISSING_NOENTRY);
176 }
177 case VM_METHOD_TYPE_OPTIMIZED:
178 switch (cc->me->def->body.optimize_type) {
179 case OPTIMIZED_METHOD_TYPE_SEND:
180 ret = send_internal(calling->argc, argv, calling->recv, CALL_FCALL);
181 goto success;
182 case OPTIMIZED_METHOD_TYPE_CALL:
183 {
184 rb_proc_t *proc;
185 GetProcPtr(calling->recv, proc);
186 ret = rb_vm_invoke_proc(ec, proc, calling->argc, argv, calling->block_handler);
187 goto success;
188 }
189 default:
190 rb_bug("vm_call0: unsupported optimized method type (%d)", cc->me->def->body.optimize_type);
191 }
192 break;
193 case VM_METHOD_TYPE_UNDEF:
194 break;
195 }
196 rb_bug("vm_call0: unsupported method type (%d)", cc->me->def->type);
197 return Qundef;
198
199 success:
200 RUBY_VM_CHECK_INTS(ec);
201 return ret;
202 }
203
204 VALUE
rb_vm_call(rb_execution_context_t * ec,VALUE recv,VALUE id,int argc,const VALUE * argv,const rb_callable_method_entry_t * me)205 rb_vm_call(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me)
206 {
207 return rb_vm_call0(ec, recv, id, argc, argv, me);
208 }
209
210 static inline VALUE
vm_call_super(rb_execution_context_t * ec,int argc,const VALUE * argv)211 vm_call_super(rb_execution_context_t *ec, int argc, const VALUE *argv)
212 {
213 VALUE recv = ec->cfp->self;
214 VALUE klass;
215 ID id;
216 rb_control_frame_t *cfp = ec->cfp;
217 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
218
219 if (VM_FRAME_RUBYFRAME_P(cfp)) {
220 rb_bug("vm_call_super: should not be reached");
221 }
222
223 klass = RCLASS_ORIGIN(me->defined_class);
224 klass = RCLASS_SUPER(klass);
225 id = me->def->original_id;
226 me = rb_callable_method_entry(klass, id);
227
228 if (!me) {
229 return method_missing(recv, id, argc, argv, MISSING_SUPER);
230 }
231 else {
232 return rb_vm_call0(ec, recv, id, argc, argv, me);
233 }
234 }
235
236 VALUE
rb_call_super(int argc,const VALUE * argv)237 rb_call_super(int argc, const VALUE *argv)
238 {
239 rb_execution_context_t *ec = GET_EC();
240 PASS_PASSED_BLOCK_HANDLER_EC(ec);
241 return vm_call_super(ec, argc, argv);
242 }
243
244 VALUE
rb_current_receiver(void)245 rb_current_receiver(void)
246 {
247 const rb_execution_context_t *ec = GET_EC();
248 rb_control_frame_t *cfp;
249 if (!ec || !(cfp = ec->cfp)) {
250 rb_raise(rb_eRuntimeError, "no self, no life");
251 }
252 return cfp->self;
253 }
254
255 #endif /* #ifndef MJIT_HEADER */
256
257 static inline void
stack_check(rb_execution_context_t * ec)258 stack_check(rb_execution_context_t *ec)
259 {
260 if (!rb_ec_raised_p(ec, RAISED_STACKOVERFLOW) &&
261 rb_ec_stack_check(ec)) {
262 rb_ec_raised_set(ec, RAISED_STACKOVERFLOW);
263 rb_ec_stack_overflow(ec, FALSE);
264 }
265 }
266
267 #ifndef MJIT_HEADER
268
269 static inline const rb_callable_method_entry_t *rb_search_method_entry(VALUE recv, ID mid);
270 static inline enum method_missing_reason rb_method_call_status(rb_execution_context_t *ec, const rb_callable_method_entry_t *me, call_type scope, VALUE self);
271
272 /*!
273 * \internal
274 * calls the specified method.
275 *
276 * This function is called by functions in rb_call* family.
277 * \param ec current execution context
278 * \param recv receiver of the method
279 * \param mid an ID that represents the name of the method
280 * \param argc the number of method arguments
281 * \param argv a pointer to an array of method arguments
282 * \param scope
283 * \param self self in the caller. Qundef means no self is considered and
284 * protected methods cannot be called
285 *
286 * \note \a self is used in order to controlling access to protected methods.
287 */
288 static inline VALUE
rb_call0(rb_execution_context_t * ec,VALUE recv,ID mid,int argc,const VALUE * argv,call_type scope,VALUE self)289 rb_call0(rb_execution_context_t *ec,
290 VALUE recv, ID mid, int argc, const VALUE *argv,
291 call_type scope, VALUE self)
292 {
293 const rb_callable_method_entry_t *me;
294 enum method_missing_reason call_status;
295
296 if (scope == CALL_PUBLIC) {
297 me = rb_callable_method_entry_with_refinements(CLASS_OF(recv), mid, NULL);
298 }
299 else {
300 me = rb_search_method_entry(recv, mid);
301 }
302 call_status = rb_method_call_status(ec, me, scope, self);
303
304 if (call_status != MISSING_NONE) {
305 return method_missing(recv, mid, argc, argv, call_status);
306 }
307 stack_check(ec);
308 return rb_vm_call0(ec, recv, mid, argc, argv, me);
309 }
310
311 struct rescue_funcall_args {
312 VALUE defined_class;
313 VALUE recv;
314 ID mid;
315 rb_execution_context_t *ec;
316 const rb_method_entry_t *me;
317 unsigned int respond: 1;
318 unsigned int respond_to_missing: 1;
319 int argc;
320 const VALUE *argv;
321 };
322
323 static VALUE
check_funcall_exec(struct rescue_funcall_args * args)324 check_funcall_exec(struct rescue_funcall_args *args)
325 {
326 return call_method_entry(args->ec, args->defined_class,
327 args->recv, idMethodMissing,
328 args->me, args->argc, args->argv);
329 }
330
331 static VALUE
check_funcall_failed(struct rescue_funcall_args * args,VALUE e)332 check_funcall_failed(struct rescue_funcall_args *args, VALUE e)
333 {
334 int ret = args->respond;
335 if (!ret) {
336 switch (rb_method_boundp(args->defined_class, args->mid,
337 BOUND_PRIVATE|BOUND_RESPONDS)) {
338 case 2:
339 ret = TRUE;
340 break;
341 case 0:
342 ret = args->respond_to_missing;
343 break;
344 default:
345 ret = FALSE;
346 break;
347 }
348 }
349 if (ret) {
350 rb_exc_raise(e);
351 }
352 return Qundef;
353 }
354
355 static int
check_funcall_respond_to(rb_execution_context_t * ec,VALUE klass,VALUE recv,ID mid)356 check_funcall_respond_to(rb_execution_context_t *ec, VALUE klass, VALUE recv, ID mid)
357 {
358 return vm_respond_to(ec, klass, recv, mid, TRUE);
359 }
360
361 static int
check_funcall_callable(rb_execution_context_t * ec,const rb_callable_method_entry_t * me)362 check_funcall_callable(rb_execution_context_t *ec, const rb_callable_method_entry_t *me)
363 {
364 return rb_method_call_status(ec, me, CALL_FCALL, ec->cfp->self) == MISSING_NONE;
365 }
366
367 static VALUE
check_funcall_missing(rb_execution_context_t * ec,VALUE klass,VALUE recv,ID mid,int argc,const VALUE * argv,int respond,VALUE def)368 check_funcall_missing(rb_execution_context_t *ec, VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int respond, VALUE def)
369 {
370 struct rescue_funcall_args args;
371 const rb_method_entry_t *me;
372 VALUE ret = Qundef;
373
374 ret = basic_obj_respond_to_missing(ec, klass, recv,
375 ID2SYM(mid), Qtrue);
376 if (!RTEST(ret)) return def;
377 args.respond = respond > 0;
378 args.respond_to_missing = (ret != Qundef);
379 ret = def;
380 me = method_entry_get(klass, idMethodMissing, &args.defined_class);
381 if (me && !METHOD_ENTRY_BASIC(me)) {
382 VALUE argbuf, *new_args = ALLOCV_N(VALUE, argbuf, argc+1);
383
384 new_args[0] = ID2SYM(mid);
385 MEMCPY(new_args+1, argv, VALUE, argc);
386 ec->method_missing_reason = MISSING_NOENTRY;
387 args.ec = ec;
388 args.recv = recv;
389 args.me = me;
390 args.mid = mid;
391 args.argc = argc + 1;
392 args.argv = new_args;
393 ret = rb_rescue2(check_funcall_exec, (VALUE)&args,
394 check_funcall_failed, (VALUE)&args,
395 rb_eNoMethodError, (VALUE)0);
396 ALLOCV_END(argbuf);
397 }
398 return ret;
399 }
400
401 VALUE
rb_check_funcall(VALUE recv,ID mid,int argc,const VALUE * argv)402 rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
403 {
404 return rb_check_funcall_default(recv, mid, argc, argv, Qundef);
405 }
406
407 VALUE
rb_check_funcall_default(VALUE recv,ID mid,int argc,const VALUE * argv,VALUE def)408 rb_check_funcall_default(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE def)
409 {
410 VALUE klass = CLASS_OF(recv);
411 const rb_callable_method_entry_t *me;
412 rb_execution_context_t *ec = GET_EC();
413 int respond = check_funcall_respond_to(ec, klass, recv, mid);
414
415 if (!respond)
416 return def;
417
418 me = rb_search_method_entry(recv, mid);
419 if (!check_funcall_callable(ec, me)) {
420 VALUE ret = check_funcall_missing(ec, klass, recv, mid, argc, argv,
421 respond, def);
422 if (ret == Qundef) ret = def;
423 return ret;
424 }
425 stack_check(ec);
426 return rb_vm_call0(ec, recv, mid, argc, argv, me);
427 }
428
429 VALUE
rb_check_funcall_with_hook(VALUE recv,ID mid,int argc,const VALUE * argv,rb_check_funcall_hook * hook,VALUE arg)430 rb_check_funcall_with_hook(VALUE recv, ID mid, int argc, const VALUE *argv,
431 rb_check_funcall_hook *hook, VALUE arg)
432 {
433 VALUE klass = CLASS_OF(recv);
434 const rb_callable_method_entry_t *me;
435 rb_execution_context_t *ec = GET_EC();
436 int respond = check_funcall_respond_to(ec, klass, recv, mid);
437
438 if (!respond) {
439 (*hook)(FALSE, recv, mid, argc, argv, arg);
440 return Qundef;
441 }
442
443 me = rb_search_method_entry(recv, mid);
444 if (!check_funcall_callable(ec, me)) {
445 VALUE ret = check_funcall_missing(ec, klass, recv, mid, argc, argv,
446 respond, Qundef);
447 (*hook)(ret != Qundef, recv, mid, argc, argv, arg);
448 return ret;
449 }
450 stack_check(ec);
451 (*hook)(TRUE, recv, mid, argc, argv, arg);
452 return rb_vm_call0(ec, recv, mid, argc, argv, me);
453 }
454
455 const char *
rb_type_str(enum ruby_value_type type)456 rb_type_str(enum ruby_value_type type)
457 {
458 #define type_case(t) t: return #t
459 switch (type) {
460 case type_case(T_NONE);
461 case type_case(T_OBJECT);
462 case type_case(T_CLASS);
463 case type_case(T_MODULE);
464 case type_case(T_FLOAT);
465 case type_case(T_STRING);
466 case type_case(T_REGEXP);
467 case type_case(T_ARRAY);
468 case type_case(T_HASH);
469 case type_case(T_STRUCT);
470 case type_case(T_BIGNUM);
471 case type_case(T_FILE);
472 case type_case(T_DATA);
473 case type_case(T_MATCH);
474 case type_case(T_COMPLEX);
475 case type_case(T_RATIONAL);
476 case type_case(T_NIL);
477 case type_case(T_TRUE);
478 case type_case(T_FALSE);
479 case type_case(T_SYMBOL);
480 case type_case(T_FIXNUM);
481 case type_case(T_IMEMO);
482 case type_case(T_UNDEF);
483 case type_case(T_NODE);
484 case type_case(T_ICLASS);
485 case type_case(T_ZOMBIE);
486 case T_MASK: break;
487 }
488 #undef type_case
489 return NULL;
490 }
491
492 NORETURN(static void uncallable_object(VALUE recv, ID mid));
493 static void
uncallable_object(VALUE recv,ID mid)494 uncallable_object(VALUE recv, ID mid)
495 {
496 VALUE flags;
497 int type;
498 const char *typestr;
499 VALUE mname = rb_id2str(mid);
500
501 if (SPECIAL_CONST_P(recv)) {
502 rb_raise(rb_eNotImpError,
503 "method `%"PRIsVALUE"' called on unexpected immediate object (%p)",
504 mname, (void *)recv);
505 }
506 else if ((flags = RBASIC(recv)->flags) == 0) {
507 rb_raise(rb_eNotImpError,
508 "method `%"PRIsVALUE"' called on terminated object (%p)",
509 mname, (void *)recv);
510 }
511 else if (!(typestr = rb_type_str(type = BUILTIN_TYPE(recv)))) {
512 rb_raise(rb_eNotImpError,
513 "method `%"PRIsVALUE"' called on broken T_?""?""?(0x%02x) object"
514 " (%p flags=0x%"PRIxVALUE")",
515 mname, type, (void *)recv, flags);
516 }
517 else if (T_OBJECT <= type && type < T_NIL) {
518 rb_raise(rb_eNotImpError,
519 "method `%"PRIsVALUE"' called on hidden %s object"
520 " (%p flags=0x%"PRIxVALUE")",
521 mname, typestr, (void *)recv, flags);
522 }
523 else {
524 rb_raise(rb_eNotImpError,
525 "method `%"PRIsVALUE"' called on unexpected %s object"
526 " (%p flags=0x%"PRIxVALUE")",
527 mname, typestr, (void *)recv, flags);
528 }
529 }
530
531 static inline const rb_callable_method_entry_t *
rb_search_method_entry(VALUE recv,ID mid)532 rb_search_method_entry(VALUE recv, ID mid)
533 {
534 VALUE klass = CLASS_OF(recv);
535
536 if (!klass) uncallable_object(recv, mid);
537 return rb_callable_method_entry(klass, mid);
538 }
539
540 static inline enum method_missing_reason
rb_method_call_status(rb_execution_context_t * ec,const rb_callable_method_entry_t * me,call_type scope,VALUE self)541 rb_method_call_status(rb_execution_context_t *ec, const rb_callable_method_entry_t *me, call_type scope, VALUE self)
542 {
543 VALUE klass;
544 ID oid;
545 rb_method_visibility_t visi;
546
547 if (UNDEFINED_METHOD_ENTRY_P(me)) {
548 undefined:
549 return scope == CALL_VCALL ? MISSING_VCALL : MISSING_NOENTRY;
550 }
551 if (me->def->type == VM_METHOD_TYPE_REFINED) {
552 me = rb_resolve_refined_method_callable(Qnil, me);
553 if (UNDEFINED_METHOD_ENTRY_P(me)) goto undefined;
554 }
555
556 klass = me->owner;
557 oid = me->def->original_id;
558 visi = METHOD_ENTRY_VISI(me);
559
560 if (oid != idMethodMissing) {
561 /* receiver specified form for private method */
562 if (UNLIKELY(visi != METHOD_VISI_PUBLIC)) {
563 if (visi == METHOD_VISI_PRIVATE && scope == CALL_PUBLIC) {
564 return MISSING_PRIVATE;
565 }
566
567 /* self must be kind of a specified form for protected method */
568 if (visi == METHOD_VISI_PROTECTED && scope == CALL_PUBLIC) {
569 VALUE defined_class = klass;
570
571 if (RB_TYPE_P(defined_class, T_ICLASS)) {
572 defined_class = RBASIC(defined_class)->klass;
573 }
574
575 if (self == Qundef || !rb_obj_is_kind_of(self, defined_class)) {
576 return MISSING_PROTECTED;
577 }
578 }
579 }
580 }
581
582 return MISSING_NONE;
583 }
584
585
586 /*!
587 * \internal
588 * calls the specified method.
589 *
590 * This function is called by functions in rb_call* family.
591 * \param recv receiver
592 * \param mid an ID that represents the name of the method
593 * \param argc the number of method arguments
594 * \param argv a pointer to an array of method arguments
595 * \param scope
596 */
597 static inline VALUE
rb_call(VALUE recv,ID mid,int argc,const VALUE * argv,call_type scope)598 rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
599 {
600 rb_execution_context_t *ec = GET_EC();
601 return rb_call0(ec, recv, mid, argc, argv, scope, ec->cfp->self);
602 }
603
604 NORETURN(static void raise_method_missing(rb_execution_context_t *ec, int argc, const VALUE *argv,
605 VALUE obj, enum method_missing_reason call_status));
606
607 /*
608 * call-seq:
609 * obj.method_missing(symbol [, *args] ) -> result
610 *
611 * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
612 * <i>symbol</i> is the symbol for the method called, and <i>args</i>
613 * are any arguments that were passed to it. By default, the interpreter
614 * raises an error when this method is called. However, it is possible
615 * to override the method to provide more dynamic behavior.
616 * If it is decided that a particular method should not be handled, then
617 * <i>super</i> should be called, so that ancestors can pick up the
618 * missing method.
619 * The example below creates
620 * a class <code>Roman</code>, which responds to methods with names
621 * consisting of roman numerals, returning the corresponding integer
622 * values.
623 *
624 * class Roman
625 * def roman_to_int(str)
626 * # ...
627 * end
628 * def method_missing(methId)
629 * str = methId.id2name
630 * roman_to_int(str)
631 * end
632 * end
633 *
634 * r = Roman.new
635 * r.iv #=> 4
636 * r.xxiii #=> 23
637 * r.mm #=> 2000
638 */
639
640 static VALUE
rb_method_missing(int argc,const VALUE * argv,VALUE obj)641 rb_method_missing(int argc, const VALUE *argv, VALUE obj)
642 {
643 rb_execution_context_t *ec = GET_EC();
644 raise_method_missing(ec, argc, argv, obj, ec->method_missing_reason);
645 UNREACHABLE_RETURN(Qnil);
646 }
647
648 MJIT_FUNC_EXPORTED VALUE
rb_make_no_method_exception(VALUE exc,VALUE format,VALUE obj,int argc,const VALUE * argv,int priv)649 rb_make_no_method_exception(VALUE exc, VALUE format, VALUE obj,
650 int argc, const VALUE *argv, int priv)
651 {
652 VALUE name = argv[0];
653
654 if (!format) {
655 format = rb_fstring_lit("undefined method `%s' for %s%s%s");
656 }
657 if (exc == rb_eNoMethodError) {
658 VALUE args = rb_ary_new4(argc - 1, argv + 1);
659 return rb_nomethod_err_new(format, obj, name, args, priv);
660 }
661 else {
662 return rb_name_err_new(format, obj, name);
663 }
664 }
665
666 #endif /* #ifndef MJIT_HEADER */
667
668 static void
raise_method_missing(rb_execution_context_t * ec,int argc,const VALUE * argv,VALUE obj,enum method_missing_reason last_call_status)669 raise_method_missing(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE obj,
670 enum method_missing_reason last_call_status)
671 {
672 VALUE exc = rb_eNoMethodError;
673 VALUE format = 0;
674
675 if (UNLIKELY(argc == 0)) {
676 rb_raise(rb_eArgError, "no method name given");
677 }
678 else if (UNLIKELY(!SYMBOL_P(argv[0]))) {
679 const VALUE e = rb_eArgError; /* TODO: TypeError? */
680 rb_raise(e, "method name must be a Symbol but %"PRIsVALUE" is given",
681 rb_obj_class(argv[0]));
682 }
683
684 stack_check(ec);
685
686 if (last_call_status & MISSING_PRIVATE) {
687 format = rb_fstring_lit("private method `%s' called for %s%s%s");
688 }
689 else if (last_call_status & MISSING_PROTECTED) {
690 format = rb_fstring_lit("protected method `%s' called for %s%s%s");
691 }
692 else if (last_call_status & MISSING_VCALL) {
693 format = rb_fstring_lit("undefined local variable or method `%s' for %s%s%s");
694 exc = rb_eNameError;
695 }
696 else if (last_call_status & MISSING_SUPER) {
697 format = rb_fstring_lit("super: no superclass method `%s' for %s%s%s");
698 }
699
700 {
701 exc = rb_make_no_method_exception(exc, format, obj, argc, argv,
702 last_call_status & (MISSING_FCALL|MISSING_VCALL));
703 if (!(last_call_status & MISSING_MISSING)) {
704 rb_vm_pop_cfunc_frame();
705 }
706 rb_exc_raise(exc);
707 }
708 }
709
710 static void
vm_raise_method_missing(rb_execution_context_t * ec,int argc,const VALUE * argv,VALUE obj,int call_status)711 vm_raise_method_missing(rb_execution_context_t *ec, int argc, const VALUE *argv,
712 VALUE obj, int call_status)
713 {
714 vm_passed_block_handler_set(ec, VM_BLOCK_HANDLER_NONE);
715 raise_method_missing(ec, argc, argv, obj, call_status | MISSING_MISSING);
716 }
717
718 static inline VALUE
method_missing(VALUE obj,ID id,int argc,const VALUE * argv,enum method_missing_reason call_status)719 method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status)
720 {
721 VALUE *nargv, result, work, klass;
722 rb_execution_context_t *ec = GET_EC();
723 VALUE block_handler = vm_passed_block_handler(ec);
724 const rb_callable_method_entry_t *me;
725
726 ec->method_missing_reason = call_status;
727
728 if (id == idMethodMissing) {
729 missing:
730 raise_method_missing(ec, argc, argv, obj, call_status | MISSING_MISSING);
731 }
732
733 nargv = ALLOCV_N(VALUE, work, argc + 1);
734 nargv[0] = ID2SYM(id);
735 MEMCPY(nargv + 1, argv, VALUE, argc);
736 ++argc;
737 argv = nargv;
738
739 klass = CLASS_OF(obj);
740 if (!klass) goto missing;
741 me = rb_callable_method_entry(klass, idMethodMissing);
742 if (!me || METHOD_ENTRY_BASIC(me)) goto missing;
743 vm_passed_block_handler_set(ec, block_handler);
744 result = rb_vm_call0(ec, obj, idMethodMissing, argc, argv, me);
745 if (work) ALLOCV_END(work);
746 return result;
747 }
748
749 #ifndef MJIT_HEADER
750
751 /*!
752 * Calls a method
753 * \param recv receiver of the method
754 * \param mid an ID that represents the name of the method
755 * \param args an Array object which contains method arguments
756 *
757 * \pre \a args must refer an Array object.
758 */
759 VALUE
rb_apply(VALUE recv,ID mid,VALUE args)760 rb_apply(VALUE recv, ID mid, VALUE args)
761 {
762 int argc;
763 VALUE *argv, ret;
764
765 argc = RARRAY_LENINT(args);
766 if (argc >= 0x100) {
767 args = rb_ary_subseq(args, 0, argc);
768 RBASIC_CLEAR_CLASS(args);
769 OBJ_FREEZE(args);
770 ret = rb_call(recv, mid, argc, RARRAY_CONST_PTR(args), CALL_FCALL);
771 RB_GC_GUARD(args);
772 return ret;
773 }
774 argv = ALLOCA_N(VALUE, argc);
775 MEMCPY(argv, RARRAY_CONST_PTR_TRANSIENT(args), VALUE, argc);
776 return rb_call(recv, mid, argc, argv, CALL_FCALL);
777 }
778
779 #undef rb_funcall
780 /*!
781 * Calls a method
782 * \param recv receiver of the method
783 * \param mid an ID that represents the name of the method
784 * \param n the number of arguments
785 * \param ... arbitrary number of method arguments
786 *
787 * \pre each of arguments after \a n must be a VALUE.
788 */
789 VALUE
rb_funcall(VALUE recv,ID mid,int n,...)790 rb_funcall(VALUE recv, ID mid, int n, ...)
791 {
792 VALUE *argv;
793 va_list ar;
794
795 if (n > 0) {
796 long i;
797
798 va_init_list(ar, n);
799
800 argv = ALLOCA_N(VALUE, n);
801
802 for (i = 0; i < n; i++) {
803 argv[i] = va_arg(ar, VALUE);
804 }
805 va_end(ar);
806 }
807 else {
808 argv = 0;
809 }
810 return rb_call(recv, mid, n, argv, CALL_FCALL);
811 }
812
813 /*!
814 * Calls a method
815 * \param recv receiver of the method
816 * \param mid an ID that represents the name of the method
817 * \param argc the number of arguments
818 * \param argv pointer to an array of method arguments
819 */
820 VALUE
rb_funcallv(VALUE recv,ID mid,int argc,const VALUE * argv)821 rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
822 {
823 return rb_call(recv, mid, argc, argv, CALL_FCALL);
824 }
825
826 /*!
827 * Calls a method.
828 *
829 * Same as rb_funcallv but this function can call only public methods.
830 * \param recv receiver of the method
831 * \param mid an ID that represents the name of the method
832 * \param argc the number of arguments
833 * \param argv pointer to an array of method arguments
834 */
835 VALUE
rb_funcallv_public(VALUE recv,ID mid,int argc,const VALUE * argv)836 rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv)
837 {
838 return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
839 }
840
841 VALUE
rb_funcall_passing_block(VALUE recv,ID mid,int argc,const VALUE * argv)842 rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv)
843 {
844 PASS_PASSED_BLOCK_HANDLER();
845 return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
846 }
847
848 VALUE
rb_funcall_with_block(VALUE recv,ID mid,int argc,const VALUE * argv,VALUE passed_procval)849 rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE passed_procval)
850 {
851 if (!NIL_P(passed_procval)) {
852 vm_passed_block_handler_set(GET_EC(), passed_procval);
853 }
854
855 return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
856 }
857
858 static VALUE *
current_vm_stack_arg(const rb_execution_context_t * ec,const VALUE * argv)859 current_vm_stack_arg(const rb_execution_context_t *ec, const VALUE *argv)
860 {
861 rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp);
862 if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, prev_cfp)) return NULL;
863 if (prev_cfp->sp + 1 != argv) return NULL;
864 return prev_cfp->sp + 1;
865 }
866
867 static VALUE
send_internal(int argc,const VALUE * argv,VALUE recv,call_type scope)868 send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
869 {
870 ID id;
871 VALUE vid;
872 VALUE self;
873 VALUE ret, vargv = 0;
874 rb_execution_context_t *ec = GET_EC();
875
876 if (scope == CALL_PUBLIC) {
877 self = Qundef;
878 }
879 else {
880 self = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp)->self;
881 }
882
883 if (argc == 0) {
884 rb_raise(rb_eArgError, "no method name given");
885 }
886
887 vid = *argv;
888
889 id = rb_check_id(&vid);
890 if (!id) {
891 if (rb_method_basic_definition_p(CLASS_OF(recv), idMethodMissing)) {
892 VALUE exc = rb_make_no_method_exception(rb_eNoMethodError, 0,
893 recv, argc, argv,
894 scope != CALL_PUBLIC);
895 rb_exc_raise(exc);
896 }
897 if (!SYMBOL_P(*argv)) {
898 VALUE *tmp_argv = current_vm_stack_arg(ec, argv);
899 vid = rb_str_intern(vid);
900 if (tmp_argv) {
901 tmp_argv[0] = vid;
902 }
903 else if (argc > 1) {
904 tmp_argv = ALLOCV_N(VALUE, vargv, argc);
905 tmp_argv[0] = vid;
906 MEMCPY(tmp_argv+1, argv+1, VALUE, argc-1);
907 argv = tmp_argv;
908 }
909 else {
910 argv = &vid;
911 }
912 }
913 id = idMethodMissing;
914 ec->method_missing_reason = MISSING_NOENTRY;
915 }
916 else {
917 argv++; argc--;
918 }
919 PASS_PASSED_BLOCK_HANDLER_EC(ec);
920 ret = rb_call0(ec, recv, id, argc, argv, scope, self);
921 ALLOCV_END(vargv);
922 return ret;
923 }
924
925 /*
926 * call-seq:
927 * foo.send(symbol [, args...]) -> obj
928 * foo.__send__(symbol [, args...]) -> obj
929 * foo.send(string [, args...]) -> obj
930 * foo.__send__(string [, args...]) -> obj
931 *
932 * Invokes the method identified by _symbol_, passing it any
933 * arguments specified. You can use <code>__send__</code> if the name
934 * +send+ clashes with an existing method in _obj_.
935 * When the method is identified by a string, the string is converted
936 * to a symbol.
937 *
938 * class Klass
939 * def hello(*args)
940 * "Hello " + args.join(' ')
941 * end
942 * end
943 * k = Klass.new
944 * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
945 */
946
947 VALUE
rb_f_send(int argc,VALUE * argv,VALUE recv)948 rb_f_send(int argc, VALUE *argv, VALUE recv)
949 {
950 return send_internal(argc, argv, recv, CALL_FCALL);
951 }
952
953 /*
954 * call-seq:
955 * obj.public_send(symbol [, args...]) -> obj
956 * obj.public_send(string [, args...]) -> obj
957 *
958 * Invokes the method identified by _symbol_, passing it any
959 * arguments specified. Unlike send, public_send calls public
960 * methods only.
961 * When the method is identified by a string, the string is converted
962 * to a symbol.
963 *
964 * 1.public_send(:puts, "hello") # causes NoMethodError
965 */
966
967 static VALUE
rb_f_public_send(int argc,VALUE * argv,VALUE recv)968 rb_f_public_send(int argc, VALUE *argv, VALUE recv)
969 {
970 return send_internal(argc, argv, recv, CALL_PUBLIC);
971 }
972
973 /* yield */
974
975 static inline VALUE
rb_yield_0(int argc,const VALUE * argv)976 rb_yield_0(int argc, const VALUE * argv)
977 {
978 return vm_yield(GET_EC(), argc, argv);
979 }
980
981 VALUE
rb_yield_1(VALUE val)982 rb_yield_1(VALUE val)
983 {
984 return rb_yield_0(1, &val);
985 }
986
987 VALUE
rb_yield(VALUE val)988 rb_yield(VALUE val)
989 {
990 if (val == Qundef) {
991 return rb_yield_0(0, 0);
992 }
993 else {
994 return rb_yield_1(val);
995 }
996 }
997
998 #undef rb_yield_values
999 VALUE
rb_yield_values(int n,...)1000 rb_yield_values(int n, ...)
1001 {
1002 if (n == 0) {
1003 return rb_yield_0(0, 0);
1004 }
1005 else {
1006 int i;
1007 VALUE *argv;
1008 va_list args;
1009 argv = ALLOCA_N(VALUE, n);
1010
1011 va_init_list(args, n);
1012 for (i=0; i<n; i++) {
1013 argv[i] = va_arg(args, VALUE);
1014 }
1015 va_end(args);
1016
1017 return rb_yield_0(n, argv);
1018 }
1019 }
1020
1021 VALUE
rb_yield_values2(int argc,const VALUE * argv)1022 rb_yield_values2(int argc, const VALUE *argv)
1023 {
1024 return rb_yield_0(argc, argv);
1025 }
1026
1027 VALUE
rb_yield_splat(VALUE values)1028 rb_yield_splat(VALUE values)
1029 {
1030 VALUE tmp = rb_check_array_type(values);
1031 VALUE v;
1032 if (NIL_P(tmp)) {
1033 rb_raise(rb_eArgError, "not an array");
1034 }
1035 v = rb_yield_0(RARRAY_LENINT(tmp), RARRAY_CONST_PTR(tmp));
1036 RB_GC_GUARD(tmp);
1037 return v;
1038 }
1039
1040 VALUE
rb_yield_force_blockarg(VALUE values)1041 rb_yield_force_blockarg(VALUE values)
1042 {
1043 return vm_yield_force_blockarg(GET_EC(), values);
1044 }
1045
1046 VALUE
rb_yield_block(VALUE val,VALUE arg,int argc,const VALUE * argv,VALUE blockarg)1047 rb_yield_block(VALUE val, VALUE arg, int argc, const VALUE *argv, VALUE blockarg)
1048 {
1049 return vm_yield_with_block(GET_EC(), argc, argv,
1050 NIL_P(blockarg) ? VM_BLOCK_HANDLER_NONE : blockarg);
1051 }
1052
1053 static VALUE
loop_i(void)1054 loop_i(void)
1055 {
1056 for (;;) {
1057 rb_yield_0(0, 0);
1058 }
1059 return Qnil;
1060 }
1061
1062 static VALUE
loop_stop(VALUE dummy,VALUE exc)1063 loop_stop(VALUE dummy, VALUE exc)
1064 {
1065 return rb_attr_get(exc, id_result);
1066 }
1067
1068 static VALUE
rb_f_loop_size(VALUE self,VALUE args,VALUE eobj)1069 rb_f_loop_size(VALUE self, VALUE args, VALUE eobj)
1070 {
1071 return DBL2NUM(HUGE_VAL);
1072 }
1073
1074 /*
1075 * call-seq:
1076 * loop { block }
1077 * loop -> an_enumerator
1078 *
1079 * Repeatedly executes the block.
1080 *
1081 * If no block is given, an enumerator is returned instead.
1082 *
1083 * loop do
1084 * print "Input: "
1085 * line = gets
1086 * break if !line or line =~ /^qQ/
1087 * # ...
1088 * end
1089 *
1090 * StopIteration raised in the block breaks the loop. In this case,
1091 * loop returns the "result" value stored in the exception.
1092 *
1093 * enum = Enumerator.new { |y|
1094 * y << "one"
1095 * y << "two"
1096 * :ok
1097 * }
1098 *
1099 * result = loop {
1100 * puts enum.next
1101 * } #=> :ok
1102 */
1103
1104 static VALUE
rb_f_loop(VALUE self)1105 rb_f_loop(VALUE self)
1106 {
1107 RETURN_SIZED_ENUMERATOR(self, 0, 0, rb_f_loop_size);
1108 return rb_rescue2(loop_i, (VALUE)0, loop_stop, (VALUE)0, rb_eStopIteration, (VALUE)0);
1109 }
1110
1111 #if VMDEBUG
1112 static const char *
1113 vm_frametype_name(const rb_control_frame_t *cfp);
1114 #endif
1115
1116 static VALUE
rb_iterate0(VALUE (* it_proc)(VALUE),VALUE data1,const struct vm_ifunc * const ifunc,rb_execution_context_t * ec)1117 rb_iterate0(VALUE (* it_proc) (VALUE), VALUE data1,
1118 const struct vm_ifunc *const ifunc,
1119 rb_execution_context_t *ec)
1120 {
1121 enum ruby_tag_type state;
1122 volatile VALUE retval = Qnil;
1123 rb_control_frame_t *const cfp = ec->cfp;
1124
1125 EC_PUSH_TAG(ec);
1126 state = EC_EXEC_TAG();
1127 if (state == 0) {
1128 iter_retry:
1129 {
1130 VALUE block_handler;
1131
1132 if (ifunc) {
1133 struct rb_captured_block *captured = VM_CFP_TO_CAPTURED_BLOCK(cfp);
1134 captured->code.ifunc = ifunc;
1135 block_handler = VM_BH_FROM_IFUNC_BLOCK(captured);
1136 }
1137 else {
1138 block_handler = VM_CF_BLOCK_HANDLER(cfp);
1139 }
1140 vm_passed_block_handler_set(ec, block_handler);
1141 }
1142 retval = (*it_proc) (data1);
1143 }
1144 else if (state == TAG_BREAK || state == TAG_RETRY) {
1145 const struct vm_throw_data *const err = (struct vm_throw_data *)ec->errinfo;
1146 const rb_control_frame_t *const escape_cfp = THROW_DATA_CATCH_FRAME(err);
1147
1148 if (cfp == escape_cfp) {
1149 rb_vm_rewind_cfp(ec, cfp);
1150
1151 state = 0;
1152 ec->tag->state = TAG_NONE;
1153 ec->errinfo = Qnil;
1154
1155 if (state == TAG_RETRY) goto iter_retry;
1156 retval = THROW_DATA_VAL(err);
1157 }
1158 else if (0) {
1159 SDR(); fprintf(stderr, "%p, %p\n", (void *)cfp, (void *)escape_cfp);
1160 }
1161 }
1162 EC_POP_TAG();
1163
1164 if (state) {
1165 EC_JUMP_TAG(ec, state);
1166 }
1167 return retval;
1168 }
1169
1170 VALUE
rb_iterate(VALUE (* it_proc)(VALUE),VALUE data1,VALUE (* bl_proc)(ANYARGS),VALUE data2)1171 rb_iterate(VALUE (* it_proc)(VALUE), VALUE data1,
1172 VALUE (* bl_proc)(ANYARGS), VALUE data2)
1173 {
1174 return rb_iterate0(it_proc, data1,
1175 bl_proc ? rb_vm_ifunc_proc_new(bl_proc, (void *)data2) : 0,
1176 GET_EC());
1177 }
1178
1179 struct iter_method_arg {
1180 VALUE obj;
1181 ID mid;
1182 int argc;
1183 const VALUE *argv;
1184 };
1185
1186 static VALUE
iterate_method(VALUE obj)1187 iterate_method(VALUE obj)
1188 {
1189 const struct iter_method_arg * arg =
1190 (struct iter_method_arg *) obj;
1191
1192 return rb_call(arg->obj, arg->mid, arg->argc, arg->argv, CALL_FCALL);
1193 }
1194
1195 VALUE
rb_block_call(VALUE obj,ID mid,int argc,const VALUE * argv,VALUE (* bl_proc)(ANYARGS),VALUE data2)1196 rb_block_call(VALUE obj, ID mid, int argc, const VALUE * argv,
1197 VALUE (*bl_proc) (ANYARGS), VALUE data2)
1198 {
1199 struct iter_method_arg arg;
1200
1201 arg.obj = obj;
1202 arg.mid = mid;
1203 arg.argc = argc;
1204 arg.argv = argv;
1205 return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
1206 }
1207
1208 VALUE
rb_lambda_call(VALUE obj,ID mid,int argc,const VALUE * argv,rb_block_call_func_t bl_proc,int min_argc,int max_argc,VALUE data2)1209 rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv,
1210 rb_block_call_func_t bl_proc, int min_argc, int max_argc,
1211 VALUE data2)
1212 {
1213 struct iter_method_arg arg;
1214 struct vm_ifunc *block;
1215
1216 if (!bl_proc) rb_raise(rb_eArgError, "NULL lambda function");
1217 arg.obj = obj;
1218 arg.mid = mid;
1219 arg.argc = argc;
1220 arg.argv = argv;
1221 block = rb_vm_ifunc_new(bl_proc, (void *)data2, min_argc, max_argc);
1222 return rb_iterate0(iterate_method, (VALUE)&arg, block, GET_EC());
1223 }
1224
1225 static VALUE
iterate_check_method(VALUE obj)1226 iterate_check_method(VALUE obj)
1227 {
1228 const struct iter_method_arg * arg =
1229 (struct iter_method_arg *) obj;
1230
1231 return rb_check_funcall(arg->obj, arg->mid, arg->argc, arg->argv);
1232 }
1233
1234 VALUE
rb_check_block_call(VALUE obj,ID mid,int argc,const VALUE * argv,VALUE (* bl_proc)(ANYARGS),VALUE data2)1235 rb_check_block_call(VALUE obj, ID mid, int argc, const VALUE *argv,
1236 VALUE (*bl_proc) (ANYARGS), VALUE data2)
1237 {
1238 struct iter_method_arg arg;
1239
1240 arg.obj = obj;
1241 arg.mid = mid;
1242 arg.argc = argc;
1243 arg.argv = argv;
1244 return rb_iterate(iterate_check_method, (VALUE)&arg, bl_proc, data2);
1245 }
1246
1247 VALUE
rb_each(VALUE obj)1248 rb_each(VALUE obj)
1249 {
1250 return rb_call(obj, idEach, 0, 0, CALL_FCALL);
1251 }
1252
1253 void rb_parser_warn_location(VALUE, int);
1254 static const rb_iseq_t *
eval_make_iseq(VALUE src,VALUE fname,int line,const rb_binding_t * bind,const struct rb_block * base_block)1255 eval_make_iseq(VALUE src, VALUE fname, int line, const rb_binding_t *bind,
1256 const struct rb_block *base_block)
1257 {
1258 const VALUE parser = rb_parser_new();
1259 const rb_iseq_t *const parent = vm_block_iseq(base_block);
1260 VALUE realpath = Qnil;
1261 rb_iseq_t *iseq = 0;
1262 rb_ast_t *ast;
1263
1264 if (!fname) {
1265 fname = rb_source_location(&line);
1266 }
1267
1268 if (fname != Qundef) {
1269 if (!NIL_P(fname)) fname = rb_fstring(fname);
1270 realpath = fname;
1271 }
1272 else if (bind) {
1273 fname = pathobj_path(bind->pathobj);
1274 realpath = pathobj_realpath(bind->pathobj);
1275 line = bind->first_lineno;
1276 rb_parser_warn_location(parser, TRUE);
1277 }
1278 else {
1279 fname = rb_fstring_lit("(eval)");
1280 }
1281
1282 rb_parser_set_context(parser, base_block, FALSE);
1283 ast = rb_parser_compile_string_path(parser, fname, src, line);
1284 if (ast->body.root) {
1285 iseq = rb_iseq_new_with_opt(&ast->body,
1286 parent->body->location.label,
1287 fname, realpath, INT2FIX(line),
1288 parent, ISEQ_TYPE_EVAL, NULL);
1289 }
1290 rb_ast_dispose(ast);
1291
1292 if (0 && iseq) { /* for debug */
1293 VALUE disasm = rb_iseq_disasm(iseq);
1294 printf("%s\n", StringValuePtr(disasm));
1295 }
1296
1297 rb_exec_event_hook_script_compiled(GET_EC(), iseq, src);
1298
1299 return iseq;
1300 }
1301
1302 static VALUE
eval_string_with_cref(VALUE self,VALUE src,rb_cref_t * cref,VALUE file,int line)1303 eval_string_with_cref(VALUE self, VALUE src, rb_cref_t *cref, VALUE file, int line)
1304 {
1305 rb_execution_context_t *ec = GET_EC();
1306 struct rb_block block;
1307 const rb_iseq_t *iseq;
1308 rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
1309 if (!cfp) {
1310 rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
1311 }
1312
1313 block.as.captured = *VM_CFP_TO_CAPTURED_BLOCK(cfp);
1314 block.as.captured.self = self;
1315 block.as.captured.code.iseq = cfp->iseq;
1316 block.type = block_type_iseq;
1317
1318 iseq = eval_make_iseq(src, file, line, NULL, &block);
1319 if (!iseq) {
1320 rb_exc_raise(ec->errinfo);
1321 }
1322
1323 /* TODO: what the code checking? */
1324 if (!cref && block.as.captured.code.val) {
1325 rb_cref_t *orig_cref = rb_vm_get_cref(vm_block_ep(&block));
1326 cref = vm_cref_dup(orig_cref);
1327 }
1328 vm_set_eval_stack(ec, iseq, cref, &block);
1329
1330 /* kick */
1331 return vm_exec(ec, TRUE);
1332 }
1333
1334 static VALUE
eval_string_with_scope(VALUE scope,VALUE src,VALUE file,int line)1335 eval_string_with_scope(VALUE scope, VALUE src, VALUE file, int line)
1336 {
1337 rb_execution_context_t *ec = GET_EC();
1338 rb_binding_t *bind = Check_TypedStruct(scope, &ruby_binding_data_type);
1339 const rb_iseq_t *iseq = eval_make_iseq(src, file, line, bind, &bind->block);
1340 if (!iseq) {
1341 rb_exc_raise(ec->errinfo);
1342 }
1343
1344 vm_set_eval_stack(ec, iseq, NULL, &bind->block);
1345
1346 /* save new env */
1347 if (iseq->body->local_table_size > 0) {
1348 vm_bind_update_env(scope, bind, vm_make_env_object(ec, ec->cfp));
1349 }
1350
1351 /* kick */
1352 return vm_exec(ec, TRUE);
1353 }
1354
1355 /*
1356 * call-seq:
1357 * eval(string [, binding [, filename [,lineno]]]) -> obj
1358 *
1359 * Evaluates the Ruby expression(s) in <em>string</em>. If
1360 * <em>binding</em> is given, which must be a <code>Binding</code>
1361 * object, the evaluation is performed in its context. If the
1362 * optional <em>filename</em> and <em>lineno</em> parameters are
1363 * present, they will be used when reporting syntax errors.
1364 *
1365 * def get_binding(str)
1366 * return binding
1367 * end
1368 * str = "hello"
1369 * eval "str + ' Fred'" #=> "hello Fred"
1370 * eval "str + ' Fred'", get_binding("bye") #=> "bye Fred"
1371 */
1372
1373 VALUE
rb_f_eval(int argc,const VALUE * argv,VALUE self)1374 rb_f_eval(int argc, const VALUE *argv, VALUE self)
1375 {
1376 VALUE src, scope, vfile, vline;
1377 VALUE file = Qundef;
1378 int line = 1;
1379
1380 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
1381 SafeStringValue(src);
1382 if (argc >= 3) {
1383 StringValue(vfile);
1384 }
1385 if (argc >= 4) {
1386 line = NUM2INT(vline);
1387 }
1388
1389 if (!NIL_P(vfile))
1390 file = vfile;
1391
1392 if (NIL_P(scope))
1393 return eval_string_with_cref(self, src, NULL, file, line);
1394 else
1395 return eval_string_with_scope(scope, src, file, line);
1396 }
1397
1398 /** @note This function name is not stable. */
1399 VALUE
ruby_eval_string_from_file(const char * str,const char * filename)1400 ruby_eval_string_from_file(const char *str, const char *filename)
1401 {
1402 VALUE file = filename ? rb_str_new_cstr(filename) : 0;
1403 return eval_string_with_cref(rb_vm_top_self(), rb_str_new2(str), NULL, file, 1);
1404 }
1405
1406 struct eval_string_from_file_arg {
1407 VALUE str;
1408 VALUE filename;
1409 };
1410
1411 static VALUE
eval_string_from_file_helper(VALUE data)1412 eval_string_from_file_helper(VALUE data)
1413 {
1414 const struct eval_string_from_file_arg *const arg = (struct eval_string_from_file_arg*)data;
1415 return eval_string_with_cref(rb_vm_top_self(), arg->str, NULL, arg->filename, 1);
1416 }
1417
1418 VALUE
ruby_eval_string_from_file_protect(const char * str,const char * filename,int * state)1419 ruby_eval_string_from_file_protect(const char *str, const char *filename, int *state)
1420 {
1421 struct eval_string_from_file_arg arg;
1422 arg.str = rb_str_new_cstr(str);
1423 arg.filename = filename ? rb_str_new_cstr(filename) : 0;
1424 return rb_protect(eval_string_from_file_helper, (VALUE)&arg, state);
1425 }
1426
1427 /**
1428 * Evaluates the given string in an isolated binding.
1429 *
1430 * Here "isolated" means the binding does not inherit any other binding. This
1431 * behaves same as the binding for required libraries.
1432 *
1433 * __FILE__ will be "(eval)", and __LINE__ starts from 1 in the evaluation.
1434 *
1435 * @param str Ruby code to evaluate.
1436 * @return The evaluated result.
1437 * @throw Exception Raises an exception on error.
1438 */
1439 VALUE
rb_eval_string(const char * str)1440 rb_eval_string(const char *str)
1441 {
1442 return ruby_eval_string_from_file(str, "eval");
1443 }
1444
1445 static VALUE
eval_string_protect(VALUE str)1446 eval_string_protect(VALUE str)
1447 {
1448 return rb_eval_string((char *)str);
1449 }
1450
1451 /**
1452 * Evaluates the given string in an isolated binding.
1453 *
1454 * __FILE__ will be "(eval)", and __LINE__ starts from 1 in the evaluation.
1455 *
1456 * @sa rb_eval_string
1457 * @param str Ruby code to evaluate.
1458 * @param state Being set to zero if succeeded. Nonzero if an error occurred.
1459 * @return The evaluated result if succeeded, an undefined value if otherwise.
1460 */
1461 VALUE
rb_eval_string_protect(const char * str,int * pstate)1462 rb_eval_string_protect(const char *str, int *pstate)
1463 {
1464 return rb_protect(eval_string_protect, (VALUE)str, pstate);
1465 }
1466
1467 /**
1468 * Evaluates the given string under a module binding in an isolated binding.
1469 * This is same as the binding for loaded libraries on "load('foo', true)".
1470 *
1471 * __FILE__ will be "(eval)", and __LINE__ starts from 1 in the evaluation.
1472 *
1473 * @sa rb_eval_string
1474 * @param str Ruby code to evaluate.
1475 * @param state Being set to zero if succeeded. Nonzero if an error occurred.
1476 * @return The evaluated result if succeeded, an undefined value if otherwise.
1477 */
1478 VALUE
rb_eval_string_wrap(const char * str,int * pstate)1479 rb_eval_string_wrap(const char *str, int *pstate)
1480 {
1481 int state;
1482 rb_thread_t *th = GET_THREAD();
1483 VALUE self = th->top_self;
1484 VALUE wrapper = th->top_wrapper;
1485 VALUE val;
1486
1487 th->top_wrapper = rb_module_new();
1488 th->top_self = rb_obj_clone(rb_vm_top_self());
1489 rb_extend_object(th->top_self, th->top_wrapper);
1490
1491 val = rb_eval_string_protect(str, &state);
1492
1493 th->top_self = self;
1494 th->top_wrapper = wrapper;
1495
1496 if (pstate) {
1497 *pstate = state;
1498 }
1499 else if (state != TAG_NONE) {
1500 EC_JUMP_TAG(th->ec, state);
1501 }
1502 return val;
1503 }
1504
1505 VALUE
rb_eval_cmd(VALUE cmd,VALUE arg,int level)1506 rb_eval_cmd(VALUE cmd, VALUE arg, int level)
1507 {
1508 enum ruby_tag_type state;
1509 volatile VALUE val = Qnil; /* OK */
1510 const int VAR_NOCLOBBERED(current_safe_level) = rb_safe_level();
1511 rb_execution_context_t * volatile ec = GET_EC();
1512
1513 if (OBJ_TAINTED(cmd)) {
1514 level = RUBY_SAFE_LEVEL_MAX;
1515 }
1516
1517 EC_PUSH_TAG(ec);
1518 rb_set_safe_level_force(level);
1519 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1520 if (!RB_TYPE_P(cmd, T_STRING)) {
1521 val = rb_funcallv(cmd, idCall, RARRAY_LENINT(arg),
1522 RARRAY_CONST_PTR(arg));
1523 }
1524 else {
1525 val = eval_string_with_cref(rb_vm_top_self(), cmd, NULL, 0, 0);
1526 }
1527 }
1528 EC_POP_TAG();
1529
1530 rb_set_safe_level_force(current_safe_level);
1531 if (state) EC_JUMP_TAG(ec, state);
1532 return val;
1533 }
1534
1535 /* block eval under the class/module context */
1536
1537 static VALUE
yield_under(VALUE under,VALUE self,int argc,const VALUE * argv)1538 yield_under(VALUE under, VALUE self, int argc, const VALUE *argv)
1539 {
1540 rb_execution_context_t *ec = GET_EC();
1541 rb_control_frame_t *cfp = ec->cfp;
1542 VALUE block_handler = VM_CF_BLOCK_HANDLER(cfp);
1543 VALUE new_block_handler = 0;
1544 const struct rb_captured_block *captured = NULL;
1545 struct rb_captured_block new_captured;
1546 const VALUE *ep = NULL;
1547 rb_cref_t *cref;
1548 int is_lambda = FALSE;
1549
1550 if (block_handler != VM_BLOCK_HANDLER_NONE) {
1551 again:
1552 switch (vm_block_handler_type(block_handler)) {
1553 case block_handler_type_iseq:
1554 captured = VM_BH_TO_CAPT_BLOCK(block_handler);
1555 new_captured = *captured;
1556 new_block_handler = VM_BH_FROM_ISEQ_BLOCK(&new_captured);
1557 break;
1558 case block_handler_type_ifunc:
1559 captured = VM_BH_TO_CAPT_BLOCK(block_handler);
1560 new_captured = *captured;
1561 new_block_handler = VM_BH_FROM_IFUNC_BLOCK(&new_captured);
1562 break;
1563 case block_handler_type_proc:
1564 is_lambda = rb_proc_lambda_p(block_handler) != Qfalse;
1565 block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler));
1566 goto again;
1567 case block_handler_type_symbol:
1568 return rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler)),
1569 argc, argv, VM_BLOCK_HANDLER_NONE);
1570 }
1571
1572 new_captured.self = self;
1573 ep = captured->ep;
1574
1575 VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler);
1576 }
1577
1578 cref = vm_cref_push(ec, under, ep, TRUE);
1579 return vm_yield_with_cref(ec, argc, argv, cref, is_lambda);
1580 }
1581
1582 VALUE
rb_yield_refine_block(VALUE refinement,VALUE refinements)1583 rb_yield_refine_block(VALUE refinement, VALUE refinements)
1584 {
1585 rb_execution_context_t *ec = GET_EC();
1586 VALUE block_handler = VM_CF_BLOCK_HANDLER(ec->cfp);
1587
1588 if (vm_block_handler_type(block_handler) != block_handler_type_iseq) {
1589 rb_bug("rb_yield_refine_block: an iseq block is required");
1590 }
1591 else {
1592 const struct rb_captured_block *captured = VM_BH_TO_ISEQ_BLOCK(block_handler);
1593 struct rb_captured_block new_captured = *captured;
1594 VALUE new_block_handler = VM_BH_FROM_ISEQ_BLOCK(&new_captured);
1595 const VALUE *ep = captured->ep;
1596 rb_cref_t *cref = vm_cref_push(ec, refinement, ep, TRUE);
1597 CREF_REFINEMENTS_SET(cref, refinements);
1598 VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler);
1599 new_captured.self = refinement;
1600 return vm_yield_with_cref(ec, 0, NULL, cref, FALSE);
1601 }
1602 }
1603
1604 /* string eval under the class/module context */
1605 static VALUE
eval_under(VALUE under,VALUE self,VALUE src,VALUE file,int line)1606 eval_under(VALUE under, VALUE self, VALUE src, VALUE file, int line)
1607 {
1608 rb_cref_t *cref = vm_cref_push(GET_EC(), under, NULL, SPECIAL_CONST_P(self) && !NIL_P(under));
1609 SafeStringValue(src);
1610 return eval_string_with_cref(self, src, cref, file, line);
1611 }
1612
1613 static VALUE
specific_eval(int argc,const VALUE * argv,VALUE klass,VALUE self)1614 specific_eval(int argc, const VALUE *argv, VALUE klass, VALUE self)
1615 {
1616 if (rb_block_given_p()) {
1617 rb_check_arity(argc, 0, 0);
1618 return yield_under(klass, self, 1, &self);
1619 }
1620 else {
1621 VALUE file = Qundef;
1622 int line = 1;
1623 VALUE code;
1624
1625 rb_check_arity(argc, 1, 3);
1626 code = argv[0];
1627 SafeStringValue(code);
1628 if (argc > 2)
1629 line = NUM2INT(argv[2]);
1630 if (argc > 1) {
1631 file = argv[1];
1632 if (!NIL_P(file)) StringValue(file);
1633 }
1634 return eval_under(klass, self, code, file, line);
1635 }
1636 }
1637
1638 static VALUE
singleton_class_for_eval(VALUE self)1639 singleton_class_for_eval(VALUE self)
1640 {
1641 if (SPECIAL_CONST_P(self)) {
1642 return rb_special_singleton_class(self);
1643 }
1644 switch (BUILTIN_TYPE(self)) {
1645 case T_FLOAT: case T_BIGNUM: case T_SYMBOL:
1646 return Qnil;
1647 case T_STRING:
1648 if (FL_TEST_RAW(self, RSTRING_FSTR)) return Qnil;
1649 default:
1650 return rb_singleton_class(self);
1651 }
1652 }
1653
1654 /*
1655 * call-seq:
1656 * obj.instance_eval(string [, filename [, lineno]] ) -> obj
1657 * obj.instance_eval {|obj| block } -> obj
1658 *
1659 * Evaluates a string containing Ruby source code, or the given block,
1660 * within the context of the receiver (_obj_). In order to set the
1661 * context, the variable +self+ is set to _obj_ while
1662 * the code is executing, giving the code access to _obj_'s
1663 * instance variables and private methods.
1664 *
1665 * When <code>instance_eval</code> is given a block, _obj_ is also
1666 * passed in as the block's only argument.
1667 *
1668 * When <code>instance_eval</code> is given a +String+, the optional
1669 * second and third parameters supply a filename and starting line number
1670 * that are used when reporting compilation errors.
1671 *
1672 * class KlassWithSecret
1673 * def initialize
1674 * @secret = 99
1675 * end
1676 * private
1677 * def the_secret
1678 * "Ssssh! The secret is #{@secret}."
1679 * end
1680 * end
1681 * k = KlassWithSecret.new
1682 * k.instance_eval { @secret } #=> 99
1683 * k.instance_eval { the_secret } #=> "Ssssh! The secret is 99."
1684 * k.instance_eval {|obj| obj == self } #=> true
1685 */
1686
1687 VALUE
rb_obj_instance_eval(int argc,const VALUE * argv,VALUE self)1688 rb_obj_instance_eval(int argc, const VALUE *argv, VALUE self)
1689 {
1690 VALUE klass = singleton_class_for_eval(self);
1691 return specific_eval(argc, argv, klass, self);
1692 }
1693
1694 /*
1695 * call-seq:
1696 * obj.instance_exec(arg...) {|var...| block } -> obj
1697 *
1698 * Executes the given block within the context of the receiver
1699 * (_obj_). In order to set the context, the variable +self+ is set
1700 * to _obj_ while the code is executing, giving the code access to
1701 * _obj_'s instance variables. Arguments are passed as block parameters.
1702 *
1703 * class KlassWithSecret
1704 * def initialize
1705 * @secret = 99
1706 * end
1707 * end
1708 * k = KlassWithSecret.new
1709 * k.instance_exec(5) {|x| @secret+x } #=> 104
1710 */
1711
1712 VALUE
rb_obj_instance_exec(int argc,const VALUE * argv,VALUE self)1713 rb_obj_instance_exec(int argc, const VALUE *argv, VALUE self)
1714 {
1715 VALUE klass = singleton_class_for_eval(self);
1716 return yield_under(klass, self, argc, argv);
1717 }
1718
1719 /*
1720 * call-seq:
1721 * mod.class_eval(string [, filename [, lineno]]) -> obj
1722 * mod.class_eval {|mod| block } -> obj
1723 * mod.module_eval(string [, filename [, lineno]]) -> obj
1724 * mod.module_eval {|mod| block } -> obj
1725 *
1726 * Evaluates the string or block in the context of _mod_, except that when
1727 * a block is given, constant/class variable lookup is not affected. This
1728 * can be used to add methods to a class. <code>module_eval</code> returns
1729 * the result of evaluating its argument. The optional _filename_ and
1730 * _lineno_ parameters set the text for error messages.
1731 *
1732 * class Thing
1733 * end
1734 * a = %q{def hello() "Hello there!" end}
1735 * Thing.module_eval(a)
1736 * puts Thing.new.hello()
1737 * Thing.module_eval("invalid code", "dummy", 123)
1738 *
1739 * <em>produces:</em>
1740 *
1741 * Hello there!
1742 * dummy:123:in `module_eval': undefined local variable
1743 * or method `code' for Thing:Class
1744 */
1745
1746 VALUE
rb_mod_module_eval(int argc,const VALUE * argv,VALUE mod)1747 rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod)
1748 {
1749 return specific_eval(argc, argv, mod, mod);
1750 }
1751
1752 /*
1753 * call-seq:
1754 * mod.module_exec(arg...) {|var...| block } -> obj
1755 * mod.class_exec(arg...) {|var...| block } -> obj
1756 *
1757 * Evaluates the given block in the context of the class/module.
1758 * The method defined in the block will belong to the receiver.
1759 * Any arguments passed to the method will be passed to the block.
1760 * This can be used if the block needs to access instance variables.
1761 *
1762 * class Thing
1763 * end
1764 * Thing.class_exec{
1765 * def hello() "Hello there!" end
1766 * }
1767 * puts Thing.new.hello()
1768 *
1769 * <em>produces:</em>
1770 *
1771 * Hello there!
1772 */
1773
1774 VALUE
rb_mod_module_exec(int argc,const VALUE * argv,VALUE mod)1775 rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod)
1776 {
1777 return yield_under(mod, mod, argc, argv);
1778 }
1779
1780 /*
1781 * Document-class: UncaughtThrowError
1782 *
1783 * Raised when +throw+ is called with a _tag_ which does not have
1784 * corresponding +catch+ block.
1785 *
1786 * throw "foo", "bar"
1787 *
1788 * <em>raises the exception:</em>
1789 *
1790 * UncaughtThrowError: uncaught throw "foo"
1791 */
1792
1793 static VALUE
uncaught_throw_init(int argc,const VALUE * argv,VALUE exc)1794 uncaught_throw_init(int argc, const VALUE *argv, VALUE exc)
1795 {
1796 rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
1797 rb_call_super(argc - 2, argv + 2);
1798 rb_ivar_set(exc, id_tag, argv[0]);
1799 rb_ivar_set(exc, id_value, argv[1]);
1800 return exc;
1801 }
1802
1803 /*
1804 * call-seq:
1805 * uncaught_throw.tag -> obj
1806 *
1807 * Return the tag object which was called for.
1808 */
1809
1810 static VALUE
uncaught_throw_tag(VALUE exc)1811 uncaught_throw_tag(VALUE exc)
1812 {
1813 return rb_ivar_get(exc, id_tag);
1814 }
1815
1816 /*
1817 * call-seq:
1818 * uncaught_throw.value -> obj
1819 *
1820 * Return the return value which was called for.
1821 */
1822
1823 static VALUE
uncaught_throw_value(VALUE exc)1824 uncaught_throw_value(VALUE exc)
1825 {
1826 return rb_ivar_get(exc, id_value);
1827 }
1828
1829 /*
1830 * call-seq:
1831 * uncaught_throw.to_s -> string
1832 *
1833 * Returns formatted message with the inspected tag.
1834 */
1835
1836 static VALUE
uncaught_throw_to_s(VALUE exc)1837 uncaught_throw_to_s(VALUE exc)
1838 {
1839 VALUE mesg = rb_attr_get(exc, id_mesg);
1840 VALUE tag = uncaught_throw_tag(exc);
1841 return rb_str_format(1, &tag, mesg);
1842 }
1843
1844 /*
1845 * call-seq:
1846 * throw(tag [, obj])
1847 *
1848 * Transfers control to the end of the active +catch+ block
1849 * waiting for _tag_. Raises +UncaughtThrowError+ if there
1850 * is no +catch+ block for the _tag_. The optional second
1851 * parameter supplies a return value for the +catch+ block,
1852 * which otherwise defaults to +nil+. For examples, see
1853 * <code>Kernel::catch</code>.
1854 */
1855
1856 static VALUE
rb_f_throw(int argc,VALUE * argv)1857 rb_f_throw(int argc, VALUE *argv)
1858 {
1859 VALUE tag, value;
1860
1861 rb_scan_args(argc, argv, "11", &tag, &value);
1862 rb_throw_obj(tag, value);
1863 UNREACHABLE_RETURN(Qnil);
1864 }
1865
1866 void
rb_throw_obj(VALUE tag,VALUE value)1867 rb_throw_obj(VALUE tag, VALUE value)
1868 {
1869 rb_execution_context_t *ec = GET_EC();
1870 struct rb_vm_tag *tt = ec->tag;
1871
1872 while (tt) {
1873 if (tt->tag == tag) {
1874 tt->retval = value;
1875 break;
1876 }
1877 tt = tt->prev;
1878 }
1879 if (!tt) {
1880 VALUE desc[3];
1881 desc[0] = tag;
1882 desc[1] = value;
1883 desc[2] = rb_str_new_cstr("uncaught throw %p");
1884 rb_exc_raise(rb_class_new_instance(numberof(desc), desc, rb_eUncaughtThrow));
1885 }
1886
1887 ec->errinfo = (VALUE)THROW_DATA_NEW(tag, NULL, TAG_THROW);
1888 EC_JUMP_TAG(ec, TAG_THROW);
1889 }
1890
1891 void
rb_throw(const char * tag,VALUE val)1892 rb_throw(const char *tag, VALUE val)
1893 {
1894 rb_throw_obj(rb_sym_intern_ascii_cstr(tag), val);
1895 }
1896
1897 static VALUE
catch_i(VALUE tag,VALUE data)1898 catch_i(VALUE tag, VALUE data)
1899 {
1900 return rb_yield_0(1, &tag);
1901 }
1902
1903 /*
1904 * call-seq:
1905 * catch([tag]) {|tag| block } -> obj
1906 *
1907 * +catch+ executes its block. If +throw+ is not called, the block executes
1908 * normally, and +catch+ returns the value of the last expression evaluated.
1909 *
1910 * catch(1) { 123 } # => 123
1911 *
1912 * If <code>throw(tag2, val)</code> is called, Ruby searches up its stack for
1913 * a +catch+ block whose +tag+ has the same +object_id+ as _tag2_. When found,
1914 * the block stops executing and returns _val_ (or +nil+ if no second argument
1915 * was given to +throw+).
1916 *
1917 * catch(1) { throw(1, 456) } # => 456
1918 * catch(1) { throw(1) } # => nil
1919 *
1920 * When +tag+ is passed as the first argument, +catch+ yields it as the
1921 * parameter of the block.
1922 *
1923 * catch(1) {|x| x + 2 } # => 3
1924 *
1925 * When no +tag+ is given, +catch+ yields a new unique object (as from
1926 * +Object.new+) as the block parameter. This object can then be used as the
1927 * argument to +throw+, and will match the correct +catch+ block.
1928 *
1929 * catch do |obj_A|
1930 * catch do |obj_B|
1931 * throw(obj_B, 123)
1932 * puts "This puts is not reached"
1933 * end
1934 *
1935 * puts "This puts is displayed"
1936 * 456
1937 * end
1938 *
1939 * # => 456
1940 *
1941 * catch do |obj_A|
1942 * catch do |obj_B|
1943 * throw(obj_A, 123)
1944 * puts "This puts is still not reached"
1945 * end
1946 *
1947 * puts "Now this puts is also not reached"
1948 * 456
1949 * end
1950 *
1951 * # => 123
1952 */
1953
1954 static VALUE
rb_f_catch(int argc,VALUE * argv,VALUE self)1955 rb_f_catch(int argc, VALUE *argv, VALUE self)
1956 {
1957 VALUE tag = rb_check_arity(argc, 0, 1) ? argv[0] : rb_obj_alloc(rb_cObject);
1958 return rb_catch_obj(tag, catch_i, 0);
1959 }
1960
1961 VALUE
rb_catch(const char * tag,VALUE (* func)(),VALUE data)1962 rb_catch(const char *tag, VALUE (*func)(), VALUE data)
1963 {
1964 VALUE vtag = tag ? rb_sym_intern_ascii_cstr(tag) : rb_obj_alloc(rb_cObject);
1965 return rb_catch_obj(vtag, func, data);
1966 }
1967
1968 static VALUE
vm_catch_protect(VALUE tag,rb_block_call_func * func,VALUE data,enum ruby_tag_type * stateptr,rb_execution_context_t * volatile ec)1969 vm_catch_protect(VALUE tag, rb_block_call_func *func, VALUE data,
1970 enum ruby_tag_type *stateptr, rb_execution_context_t *volatile ec)
1971 {
1972 enum ruby_tag_type state;
1973 VALUE val = Qnil; /* OK */
1974 rb_control_frame_t *volatile saved_cfp = ec->cfp;
1975
1976 EC_PUSH_TAG(ec);
1977
1978 _tag.tag = tag;
1979
1980 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1981 /* call with argc=1, argv = [tag], block = Qnil to insure compatibility */
1982 val = (*func)(tag, data, 1, (const VALUE *)&tag, Qnil);
1983 }
1984 else if (state == TAG_THROW && THROW_DATA_VAL((struct vm_throw_data *)ec->errinfo) == tag) {
1985 rb_vm_rewind_cfp(ec, saved_cfp);
1986 val = ec->tag->retval;
1987 ec->errinfo = Qnil;
1988 state = 0;
1989 }
1990 EC_POP_TAG();
1991 if (stateptr)
1992 *stateptr = state;
1993
1994 return val;
1995 }
1996
1997 VALUE
rb_catch_protect(VALUE t,rb_block_call_func * func,VALUE data,enum ruby_tag_type * stateptr)1998 rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, enum ruby_tag_type *stateptr)
1999 {
2000 return vm_catch_protect(t, func, data, stateptr, GET_EC());
2001 }
2002
2003 VALUE
rb_catch_obj(VALUE t,VALUE (* func)(),VALUE data)2004 rb_catch_obj(VALUE t, VALUE (*func)(), VALUE data)
2005 {
2006 enum ruby_tag_type state;
2007 rb_execution_context_t *ec = GET_EC();
2008 VALUE val = vm_catch_protect(t, (rb_block_call_func *)func, data, &state, ec);
2009 if (state) EC_JUMP_TAG(ec, state);
2010 return val;
2011 }
2012
2013 static void
local_var_list_init(struct local_var_list * vars)2014 local_var_list_init(struct local_var_list *vars)
2015 {
2016 vars->tbl = rb_hash_new_compare_by_id();
2017 RBASIC_CLEAR_CLASS(vars->tbl);
2018 }
2019
2020 static VALUE
local_var_list_finish(struct local_var_list * vars)2021 local_var_list_finish(struct local_var_list *vars)
2022 {
2023 /* TODO: not to depend on the order of st_table */
2024 VALUE ary = rb_hash_keys(vars->tbl);
2025 rb_hash_clear(vars->tbl);
2026 vars->tbl = 0;
2027 return ary;
2028 }
2029
2030 static int
local_var_list_update(st_data_t * key,st_data_t * value,st_data_t arg,int existing)2031 local_var_list_update(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
2032 {
2033 if (existing) return ST_STOP;
2034 *value = (st_data_t)Qtrue; /* INT2FIX(arg) */
2035 return ST_CONTINUE;
2036 }
2037
2038 static void
local_var_list_add(const struct local_var_list * vars,ID lid)2039 local_var_list_add(const struct local_var_list *vars, ID lid)
2040 {
2041 if (lid && rb_is_local_id(lid)) {
2042 /* should skip temporary variable */
2043 st_data_t idx = 0; /* tbl->num_entries */
2044 rb_hash_stlike_update(vars->tbl, ID2SYM(lid), local_var_list_update, idx);
2045 }
2046 }
2047
2048 /*
2049 * call-seq:
2050 * local_variables -> array
2051 *
2052 * Returns the names of the current local variables.
2053 *
2054 * fred = 1
2055 * for i in 1..10
2056 * # ...
2057 * end
2058 * local_variables #=> [:fred, :i]
2059 */
2060
2061 static VALUE
rb_f_local_variables(void)2062 rb_f_local_variables(void)
2063 {
2064 struct local_var_list vars;
2065 rb_execution_context_t *ec = GET_EC();
2066 rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp));
2067 unsigned int i;
2068
2069 local_var_list_init(&vars);
2070 while (cfp) {
2071 if (cfp->iseq) {
2072 for (i = 0; i < cfp->iseq->body->local_table_size; i++) {
2073 local_var_list_add(&vars, cfp->iseq->body->local_table[i]);
2074 }
2075 }
2076 if (!VM_ENV_LOCAL_P(cfp->ep)) {
2077 /* block */
2078 const VALUE *ep = VM_CF_PREV_EP(cfp);
2079
2080 if (vm_collect_local_variables_in_heap(ep, &vars)) {
2081 break;
2082 }
2083 else {
2084 while (cfp->ep != ep) {
2085 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
2086 }
2087 }
2088 }
2089 else {
2090 break;
2091 }
2092 }
2093 return local_var_list_finish(&vars);
2094 }
2095
2096 /*
2097 * call-seq:
2098 * block_given? -> true or false
2099 * iterator? -> true or false
2100 *
2101 * Returns <code>true</code> if <code>yield</code> would execute a
2102 * block in the current context. The <code>iterator?</code> form
2103 * is mildly deprecated.
2104 *
2105 * def try
2106 * if block_given?
2107 * yield
2108 * else
2109 * "no block"
2110 * end
2111 * end
2112 * try #=> "no block"
2113 * try { "hello" } #=> "hello"
2114 * try do "hello" end #=> "hello"
2115 */
2116
2117
2118 static VALUE
rb_f_block_given_p(void)2119 rb_f_block_given_p(void)
2120 {
2121 rb_execution_context_t *ec = GET_EC();
2122 rb_control_frame_t *cfp = ec->cfp;
2123 cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
2124
2125 if (cfp != NULL && VM_CF_BLOCK_HANDLER(cfp) != VM_BLOCK_HANDLER_NONE) {
2126 return Qtrue;
2127 }
2128 else {
2129 return Qfalse;
2130 }
2131 }
2132
2133 VALUE
rb_current_realfilepath(void)2134 rb_current_realfilepath(void)
2135 {
2136 const rb_execution_context_t *ec = GET_EC();
2137 rb_control_frame_t *cfp = ec->cfp;
2138 cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
2139 if (cfp != 0) return rb_iseq_realpath(cfp->iseq);
2140 return Qnil;
2141 }
2142
2143 void
Init_vm_eval(void)2144 Init_vm_eval(void)
2145 {
2146 rb_define_global_function("eval", rb_f_eval, -1);
2147 rb_define_global_function("local_variables", rb_f_local_variables, 0);
2148 rb_define_global_function("iterator?", rb_f_block_given_p, 0);
2149 rb_define_global_function("block_given?", rb_f_block_given_p, 0);
2150
2151 rb_define_global_function("catch", rb_f_catch, -1);
2152 rb_define_global_function("throw", rb_f_throw, -1);
2153
2154 rb_define_global_function("loop", rb_f_loop, 0);
2155
2156 rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
2157 rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
2158 rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
2159
2160 #if 1
2161 rb_add_method(rb_cBasicObject, id__send__,
2162 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, METHOD_VISI_PUBLIC);
2163 rb_add_method(rb_mKernel, idSend,
2164 VM_METHOD_TYPE_OPTIMIZED, (void *)OPTIMIZED_METHOD_TYPE_SEND, METHOD_VISI_PUBLIC);
2165 #else
2166 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
2167 rb_define_method(rb_mKernel, "send", rb_f_send, -1);
2168 #endif
2169 rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
2170
2171 rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
2172 rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
2173 rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
2174 rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
2175
2176 rb_eUncaughtThrow = rb_define_class("UncaughtThrowError", rb_eArgError);
2177 rb_define_method(rb_eUncaughtThrow, "initialize", uncaught_throw_init, -1);
2178 rb_define_method(rb_eUncaughtThrow, "tag", uncaught_throw_tag, 0);
2179 rb_define_method(rb_eUncaughtThrow, "value", uncaught_throw_value, 0);
2180 rb_define_method(rb_eUncaughtThrow, "to_s", uncaught_throw_to_s, 0);
2181
2182 id_result = rb_intern_const("result");
2183 id_tag = rb_intern_const("tag");
2184 id_value = rb_intern_const("value");
2185 }
2186
2187 #endif /* #ifndef MJIT_HEADER */
2188