Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

vm_backtrace.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 vm_backtrace.c -
4
5 $Author: ko1 $
6 created at: Sun Jun 03 00:14:20 2012
7
8 Copyright (C) 1993-2012 Yukihiro Matsumoto
9
10 **********************************************************************/
11
12 #include "ruby/encoding.h"
13 #include "ruby/debug.h"
14 #include "internal.h"
15
16 #include "vm_core.h"
17 #include "eval_intern.h"
18 #include "iseq.h"
19
20 static VALUE rb_cBacktrace;
21 static VALUE rb_cBacktraceLocation;
22
23 static VALUE
24 id2str(ID id)
25 {
26 VALUE str = rb_id2str(id);
27 if (!str) return Qnil;
28 return str;
29 }
30 #define rb_id2str(id) id2str(id)
31
32 inline static int
33 calc_lineno(const rb_iseq_t *iseq, const VALUE *pc)
34 {
35 VM_ASSERT(iseq);
36 VM_ASSERT(iseq->body);
37 VM_ASSERT(iseq->body->iseq_encoded);
38 VM_ASSERT(iseq->body->iseq_size);
39 if (! pc) {
40 /* This can happen during VM bootup. */
41 VM_ASSERT(iseq->body->type == ISEQ_TYPE_TOP);
42 VM_ASSERT(! iseq->body->local_table);
43 VM_ASSERT(! iseq->body->local_table_size);
44 return 0;
45 }
46 else {
47 ptrdiff_t n = pc - iseq->body->iseq_encoded;
48 VM_ASSERT(n <= iseq->body->iseq_size);
49 VM_ASSERT(n >= 0);
50 ASSUME(n >= 0);
51 size_t pos = n; /* no overflow */
52 if (LIKELY(pos)) {
53 /* use pos-1 because PC points next instruction at the beginning of instruction */
54 pos--;
55 }
56 #if VMDEBUG && defined(HAVE_BUILTIN___BUILTIN_TRAP)
57 else {
58 /* SDR() is not possible; that causes infinite loop. */
59 rb_print_backtrace();
60 __builtin_trap();
61 }
62 #endif
63 return rb_iseq_line_no(iseq, pos);
64 }
65 }
66
67 int
68 rb_vm_get_sourceline(const rb_control_frame_t *cfp)
69 {
70 if (VM_FRAME_RUBYFRAME_P(cfp) && cfp->iseq) {
71 const rb_iseq_t *iseq = cfp->iseq;
72 int line = calc_lineno(iseq, cfp->pc);
73 if (line != 0) {
74 return line;
75 }
76 else {
77 return FIX2INT(rb_iseq_first_lineno(iseq));
78 }
79 }
80 else {
81 return 0;
82 }
83 }
84
85 typedef struct rb_backtrace_location_struct {
86 enum LOCATION_TYPE {
87 LOCATION_TYPE_ISEQ = 1,
88 LOCATION_TYPE_ISEQ_CALCED,
89 LOCATION_TYPE_CFUNC,
90 LOCATION_TYPE_IFUNC
91 } type;
92
93 union {
94 struct {
95 const rb_iseq_t *iseq;
96 union {
97 const VALUE *pc;
98 int lineno;
99 } lineno;
100 } iseq;
101 struct {
102 ID mid;
103 struct rb_backtrace_location_struct *prev_loc;
104 } cfunc;
105 } body;
106 } rb_backtrace_location_t;
107
108 struct valued_frame_info {
109 rb_backtrace_location_t *loc;
110 VALUE btobj;
111 };
112
113 static void
114 location_mark(void *ptr)
115 {
116 struct valued_frame_info *vfi = (struct valued_frame_info *)ptr;
117 rb_gc_mark(vfi->btobj);
118 }
119
120 static void
121 location_mark_entry(rb_backtrace_location_t *fi)
122 {
123 switch (fi->type) {
124 case LOCATION_TYPE_ISEQ:
125 case LOCATION_TYPE_ISEQ_CALCED:
126 rb_gc_mark((VALUE)fi->body.iseq.iseq);
127 break;
128 case LOCATION_TYPE_CFUNC:
129 case LOCATION_TYPE_IFUNC:
130 default:
131 break;
132 }
133 }
134
135 static size_t
136 location_memsize(const void *ptr)
137 {
138 /* rb_backtrace_location_t *fi = (rb_backtrace_location_t *)ptr; */
139 return sizeof(rb_backtrace_location_t);
140 }
141
142 static const rb_data_type_t location_data_type = {
143 "frame_info",
144 {location_mark, RUBY_TYPED_DEFAULT_FREE, location_memsize,},
145 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
146 };
147
148 static inline rb_backtrace_location_t *
149 location_ptr(VALUE locobj)
150 {
151 struct valued_frame_info *vloc;
152 GetCoreDataFromValue(locobj, struct valued_frame_info, vloc);
153 return vloc->loc;
154 }
155
156 static int
157 location_lineno(rb_backtrace_location_t *loc)
158 {
159 switch (loc->type) {
160 case LOCATION_TYPE_ISEQ:
161 loc->type = LOCATION_TYPE_ISEQ_CALCED;
162 return (loc->body.iseq.lineno.lineno = calc_lineno(loc->body.iseq.iseq, loc->body.iseq.lineno.pc));
163 case LOCATION_TYPE_ISEQ_CALCED:
164 return loc->body.iseq.lineno.lineno;
165 case LOCATION_TYPE_CFUNC:
166 if (loc->body.cfunc.prev_loc) {
167 return location_lineno(loc->body.cfunc.prev_loc);
168 }
169 return 0;
170 default:
171 rb_bug("location_lineno: unreachable");
172 UNREACHABLE;
173 }
174 }
175
176 /*
177 * Returns the line number of this frame.
178 *
179 * For example, using +caller_locations.rb+ from Thread::Backtrace::Location
180 *
181 * loc = c(0..1).first
182 * loc.lineno #=> 2
183 */
184 static VALUE
185 location_lineno_m(VALUE self)
186 {
187 return INT2FIX(location_lineno(location_ptr(self)));
188 }
189
190 static VALUE
191 location_label(rb_backtrace_location_t *loc)
192 {
193 switch (loc->type) {
194 case LOCATION_TYPE_ISEQ:
195 case LOCATION_TYPE_ISEQ_CALCED:
196 return loc->body.iseq.iseq->body->location.label;
197 case LOCATION_TYPE_CFUNC:
198 return rb_id2str(loc->body.cfunc.mid);
199 case LOCATION_TYPE_IFUNC:
200 default:
201 rb_bug("location_label: unreachable");
202 UNREACHABLE;
203 }
204 }
205
206 /*
207 * Returns the label of this frame.
208 *
209 * Usually consists of method, class, module, etc names with decoration.
210 *
211 * Consider the following example:
212 *
213 * def foo
214 * puts caller_locations(0).first.label
215 *
216 * 1.times do
217 * puts caller_locations(0).first.label
218 *
219 * 1.times do
220 * puts caller_locations(0).first.label
221 * end
222 *
223 * end
224 * end
225 *
226 * The result of calling +foo+ is this:
227 *
228 * label: foo
229 * label: block in foo
230 * label: block (2 levels) in foo
231 *
232 */
233 static VALUE
234 location_label_m(VALUE self)
235 {
236 return location_label(location_ptr(self));
237 }
238
239 static VALUE
240 location_base_label(rb_backtrace_location_t *loc)
241 {
242 switch (loc->type) {
243 case LOCATION_TYPE_ISEQ:
244 case LOCATION_TYPE_ISEQ_CALCED:
245 return loc->body.iseq.iseq->body->location.base_label;
246 case LOCATION_TYPE_CFUNC:
247 return rb_id2str(loc->body.cfunc.mid);
248 case LOCATION_TYPE_IFUNC:
249 default:
250 rb_bug("location_base_label: unreachable");
251 UNREACHABLE;
252 }
253 }
254
255 /*
256 * Returns the base label of this frame.
257 *
258 * Usually same as #label, without decoration.
259 */
260 static VALUE
261 location_base_label_m(VALUE self)
262 {
263 return location_base_label(location_ptr(self));
264 }
265
266 static VALUE
267 location_path(rb_backtrace_location_t *loc)
268 {
269 switch (loc->type) {
270 case LOCATION_TYPE_ISEQ:
271 case LOCATION_TYPE_ISEQ_CALCED:
272 return rb_iseq_path(loc->body.iseq.iseq);
273 case LOCATION_TYPE_CFUNC:
274 if (loc->body.cfunc.prev_loc) {
275 return location_path(loc->body.cfunc.prev_loc);
276 }
277 return Qnil;
278 case LOCATION_TYPE_IFUNC:
279 default:
280 rb_bug("location_path: unreachable");
281 UNREACHABLE;
282 }
283 }
284
285 /*
286 * Returns the file name of this frame.
287 *
288 * For example, using +caller_locations.rb+ from Thread::Backtrace::Location
289 *
290 * loc = c(0..1).first
291 * loc.path #=> caller_locations.rb
292 */
293 static VALUE
294 location_path_m(VALUE self)
295 {
296 return location_path(location_ptr(self));
297 }
298
299 static VALUE
300 location_realpath(rb_backtrace_location_t *loc)
301 {
302 switch (loc->type) {
303 case LOCATION_TYPE_ISEQ:
304 case LOCATION_TYPE_ISEQ_CALCED:
305 return rb_iseq_realpath(loc->body.iseq.iseq);
306 case LOCATION_TYPE_CFUNC:
307 if (loc->body.cfunc.prev_loc) {
308 return location_realpath(loc->body.cfunc.prev_loc);
309 }
310 return Qnil;
311 case LOCATION_TYPE_IFUNC:
312 default:
313 rb_bug("location_realpath: unreachable");
314 UNREACHABLE;
315 }
316 }
317
318 /*
319 * Returns the full file path of this frame.
320 *
321 * Same as #path, but includes the absolute path.
322 */
323 static VALUE
324 location_absolute_path_m(VALUE self)
325 {
326 return location_realpath(location_ptr(self));
327 }
328
329 static VALUE
330 location_format(VALUE file, int lineno, VALUE name)
331 {
332 VALUE s = rb_enc_sprintf(rb_enc_compatible(file, name), "%s", RSTRING_PTR(file));
333 if (lineno != 0) {
334 rb_str_catf(s, ":%d", lineno);
335 }
336 rb_str_cat_cstr(s, ":in ");
337 if (NIL_P(name)) {
338 rb_str_cat_cstr(s, "unknown method");
339 }
340 else {
341 rb_str_catf(s, "`%s'", RSTRING_PTR(name));
342 }
343 return s;
344 }
345
346 static VALUE
347 location_to_str(rb_backtrace_location_t *loc)
348 {
349 VALUE file, name;
350 int lineno;
351
352 switch (loc->type) {
353 case LOCATION_TYPE_ISEQ:
354 file = rb_iseq_path(loc->body.iseq.iseq);
355 name = loc->body.iseq.iseq->body->location.label;
356
357 lineno = loc->body.iseq.lineno.lineno = calc_lineno(loc->body.iseq.iseq, loc->body.iseq.lineno.pc);
358 loc->type = LOCATION_TYPE_ISEQ_CALCED;
359 break;
360 case LOCATION_TYPE_ISEQ_CALCED:
361 file = rb_iseq_path(loc->body.iseq.iseq);
362 lineno = loc->body.iseq.lineno.lineno;
363 name = loc->body.iseq.iseq->body->location.label;
364 break;
365 case LOCATION_TYPE_CFUNC:
366 if (loc->body.cfunc.prev_loc) {
367 file = rb_iseq_path(loc->body.cfunc.prev_loc->body.iseq.iseq);
368 lineno = location_lineno(loc->body.cfunc.prev_loc);
369 }
370 else {
371 file = GET_VM()->progname;
372 lineno = 0;
373 }
374 name = rb_id2str(loc->body.cfunc.mid);
375 break;
376 case LOCATION_TYPE_IFUNC:
377 default:
378 rb_bug("location_to_str: unreachable");
379 }
380
381 return location_format(file, lineno, name);
382 }
383
384 /*
385 * Returns a Kernel#caller style string representing this frame.
386 */
387 static VALUE
388 location_to_str_m(VALUE self)
389 {
390 return location_to_str(location_ptr(self));
391 }
392
393 /*
394 * Returns the same as calling +inspect+ on the string representation of
395 * #to_str
396 */
397 static VALUE
398 location_inspect_m(VALUE self)
399 {
400 return rb_str_inspect(location_to_str(location_ptr(self)));
401 }
402
403 typedef struct rb_backtrace_struct {
404 rb_backtrace_location_t *backtrace;
405 rb_backtrace_location_t *backtrace_base;
406 int backtrace_size;
407 VALUE strary;
408 VALUE locary;
409 } rb_backtrace_t;
410
411 static void
412 backtrace_mark(void *ptr)
413 {
414 rb_backtrace_t *bt = (rb_backtrace_t *)ptr;
415 size_t i, s = bt->backtrace_size;
416
417 for (i=0; i<s; i++) {
418 location_mark_entry(&bt->backtrace[i]);
419 }
420 rb_gc_mark(bt->strary);
421 rb_gc_mark(bt->locary);
422 }
423
424 static void
425 backtrace_free(void *ptr)
426 {
427 rb_backtrace_t *bt = (rb_backtrace_t *)ptr;
428 if (bt->backtrace) ruby_xfree(bt->backtrace_base);
429 ruby_xfree(bt);
430 }
431
432 static size_t
433 backtrace_memsize(const void *ptr)
434 {
435 rb_backtrace_t *bt = (rb_backtrace_t *)ptr;
436 return sizeof(rb_backtrace_t) + sizeof(rb_backtrace_location_t) * bt->backtrace_size;
437 }
438
439 static const rb_data_type_t backtrace_data_type = {
440 "backtrace",
441 {backtrace_mark, backtrace_free, backtrace_memsize,},
442 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
443 };
444
445 int
446 rb_backtrace_p(VALUE obj)
447 {
448 return rb_typeddata_is_kind_of(obj, &backtrace_data_type);
449 }
450
451 static VALUE
452 backtrace_alloc(VALUE klass)
453 {
454 rb_backtrace_t *bt;
455 VALUE obj = TypedData_Make_Struct(klass, rb_backtrace_t, &backtrace_data_type, bt);
456 return obj;
457 }
458
459 static void
460 backtrace_each(const rb_execution_context_t *ec,
461 void (*init)(void *arg, size_t size),
462 void (*iter_iseq)(void *arg, const rb_control_frame_t *cfp),
463 void (*iter_cfunc)(void *arg, const rb_control_frame_t *cfp, ID mid),
464 void *arg)
465 {
466 const rb_control_frame_t *last_cfp = ec->cfp;
467 const rb_control_frame_t *start_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
468 const rb_control_frame_t *cfp;
469 ptrdiff_t size, i;
470
471 // In the case the thread vm_stack or cfp is not initialized, there is no backtrace.
472 if (start_cfp == NULL) {
473 init(arg, 0);
474 return;
475 }
476
477 /* <- start_cfp (end control frame)
478 * top frame (dummy)
479 * top frame (dummy)
480 * top frame <- start_cfp
481 * top frame
482 * ...
483 * 2nd frame <- lev:0
484 * current frame <- ec->cfp
485 */
486
487 start_cfp =
488 RUBY_VM_NEXT_CONTROL_FRAME(
489 RUBY_VM_NEXT_CONTROL_FRAME(start_cfp)); /* skip top frames */
490
491 if (start_cfp < last_cfp) {
492 size = 0;
493 }
494 else {
495 size = start_cfp - last_cfp + 1;
496 }
497
498 init(arg, size);
499
500 /* SDR(); */
501 for (i=0, cfp = start_cfp; i<size; i++, cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
502 /* fprintf(stderr, "cfp: %d\n", (rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size) - cfp); */
503 if (cfp->iseq) {
504 if (cfp->pc) {
505 iter_iseq(arg, cfp);
506 }
507 }
508 else if (RUBYVM_CFUNC_FRAME_P(cfp)) {
509 const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
510 ID mid = me->def->original_id;
511
512 iter_cfunc(arg, cfp, mid);
513 }
514 }
515 }
516
517 struct bt_iter_arg {
518 rb_backtrace_t *bt;
519 VALUE btobj;
520 rb_backtrace_location_t *prev_loc;
521 };
522
523 static void
524 bt_init(void *ptr, size_t size)
525 {
526 struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
527 arg->btobj = backtrace_alloc(rb_cBacktrace);
528 GetCoreDataFromValue(arg->btobj, rb_backtrace_t, arg->bt);
529 arg->bt->backtrace_base = arg->bt->backtrace = ALLOC_N(rb_backtrace_location_t, size);
530 arg->bt->backtrace_size = 0;
531 }
532
533 static void
534 bt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
535 {
536 const rb_iseq_t *iseq = cfp->iseq;
537 const VALUE *pc = cfp->pc;
538 struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
539 rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++];
540 loc->type = LOCATION_TYPE_ISEQ;
541 loc->body.iseq.iseq = iseq;
542 loc->body.iseq.lineno.pc = pc;
543 arg->prev_loc = loc;
544 }
545
546 static void
547 bt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
548 {
549 struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
550 rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++];
551 loc->type = LOCATION_TYPE_CFUNC;
552 loc->body.cfunc.mid = mid;
553 loc->body.cfunc.prev_loc = arg->prev_loc;
554 }
555
556 MJIT_FUNC_EXPORTED VALUE
557 rb_ec_backtrace_object(const rb_execution_context_t *ec)
558 {
559 struct bt_iter_arg arg;
560 arg.prev_loc = 0;
561
562 backtrace_each(ec,
563 bt_init,
564 bt_iter_iseq,
565 bt_iter_cfunc,
566 &arg);
567
568 return arg.btobj;
569 }
570
571 static VALUE
572 backtrace_collect(rb_backtrace_t *bt, long lev, long n, VALUE (*func)(rb_backtrace_location_t *, void *arg), void *arg)
573 {
574 VALUE btary;
575 int i;
576
577 if (UNLIKELY(lev < 0 || n < 0)) {
578 rb_bug("backtrace_collect: unreachable");
579 }
580
581 btary = rb_ary_new2(n);
582
583 for (i=0; i+lev<bt->backtrace_size && i<n; i++) {
584 rb_backtrace_location_t *loc = &bt->backtrace[bt->backtrace_size - 1 - (lev+i)];
585 rb_ary_push(btary, func(loc, arg));
586 }
587
588 return btary;
589 }
590
591 static VALUE
592 location_to_str_dmyarg(rb_backtrace_location_t *loc, void *dmy)
593 {
594 return location_to_str(loc);
595 }
596
597 static VALUE
598 backtrace_to_str_ary(VALUE self, long lev, long n)
599 {
600 rb_backtrace_t *bt;
601 int size;
602 VALUE r;
603
604 GetCoreDataFromValue(self, rb_backtrace_t, bt);
605 size = bt->backtrace_size;
606
607 if (n == 0) {
608 n = size;
609 }
610 if (lev > size) {
611 return Qnil;
612 }
613
614 r = backtrace_collect(bt, lev, n, location_to_str_dmyarg, 0);
615 RB_GC_GUARD(self);
616 return r;
617 }
618
619 VALUE
620 rb_backtrace_to_str_ary(VALUE self)
621 {
622 rb_backtrace_t *bt;
623 GetCoreDataFromValue(self, rb_backtrace_t, bt);
624
625 if (!bt->strary) {
626 bt->strary = backtrace_to_str_ary(self, 0, bt->backtrace_size);
627 }
628 return bt->strary;
629 }
630
631 MJIT_FUNC_EXPORTED void
632 rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self)
633 {
634 const rb_backtrace_t *bt;
635 const rb_iseq_t *iseq;
636 rb_backtrace_location_t *loc;
637
638 GetCoreDataFromValue(self, rb_backtrace_t, bt);
639 VM_ASSERT(bt->backtrace_size > 0);
640
641 loc = &bt->backtrace[bt->backtrace_size - 1];
642 iseq = loc->body.iseq.iseq;
643
644 VM_ASSERT(loc->type == LOCATION_TYPE_ISEQ);
645
646 loc->body.iseq.lineno.lineno = FIX2INT(iseq->body->location.first_lineno);
647 loc->type = LOCATION_TYPE_ISEQ_CALCED;
648 }
649
650 static VALUE
651 location_create(rb_backtrace_location_t *srcloc, void *btobj)
652 {
653 VALUE obj;
654 struct valued_frame_info *vloc;
655 obj = TypedData_Make_Struct(rb_cBacktraceLocation, struct valued_frame_info, &location_data_type, vloc);
656
657 vloc->loc = srcloc;
658 vloc->btobj = (VALUE)btobj;
659
660 return obj;
661 }
662
663 static VALUE
664 backtrace_to_location_ary(VALUE self, long lev, long n)
665 {
666 rb_backtrace_t *bt;
667 int size;
668 VALUE r;
669
670 GetCoreDataFromValue(self, rb_backtrace_t, bt);
671 size = bt->backtrace_size;
672
673 if (n == 0) {
674 n = size;
675 }
676 if (lev > size) {
677 return Qnil;
678 }
679
680 r = backtrace_collect(bt, lev, n, location_create, (void *)self);
681 RB_GC_GUARD(self);
682 return r;
683 }
684
685 VALUE
686 rb_backtrace_to_location_ary(VALUE self)
687 {
688 rb_backtrace_t *bt;
689 GetCoreDataFromValue(self, rb_backtrace_t, bt);
690
691 if (!bt->locary) {
692 bt->locary = backtrace_to_location_ary(self, 0, 0);
693 }
694 return bt->locary;
695 }
696
697 static VALUE
698 backtrace_dump_data(VALUE self)
699 {
700 VALUE str = rb_backtrace_to_str_ary(self);
701 return str;
702 }
703
704 static VALUE
705 backtrace_load_data(VALUE self, VALUE str)
706 {
707 rb_backtrace_t *bt;
708 GetCoreDataFromValue(self, rb_backtrace_t, bt);
709 bt->strary = str;
710 return self;
711 }
712
713 VALUE
714 rb_ec_backtrace_str_ary(const rb_execution_context_t *ec, long lev, long n)
715 {
716 return backtrace_to_str_ary(rb_ec_backtrace_object(ec), lev, n);
717 }
718
719 VALUE
720 rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n)
721 {
722 return backtrace_to_location_ary(rb_ec_backtrace_object(ec), lev, n);
723 }
724
725 /* make old style backtrace directly */
726
727 struct oldbt_arg {
728 VALUE filename;
729 int lineno;
730 void (*func)(void *data, VALUE file, int lineno, VALUE name);
731 void *data; /* result */
732 };
733
734 static void
735 oldbt_init(void *ptr, size_t dmy)
736 {
737 struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
738 arg->filename = GET_VM()->progname;
739 arg->lineno = 0;
740 }
741
742 static void
743 oldbt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
744 {
745 const rb_iseq_t *iseq = cfp->iseq;
746 const VALUE *pc = cfp->pc;
747 struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
748 VALUE file = arg->filename = rb_iseq_path(iseq);
749 VALUE name = iseq->body->location.label;
750 int lineno = arg->lineno = calc_lineno(iseq, pc);
751
752 (arg->func)(arg->data, file, lineno, name);
753 }
754
755 static void
756 oldbt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
757 {
758 struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
759 VALUE file = arg->filename;
760 VALUE name = rb_id2str(mid);
761 int lineno = arg->lineno;
762
763 (arg->func)(arg->data, file, lineno, name);
764 }
765
766 static void
767 oldbt_print(void *data, VALUE file, int lineno, VALUE name)
768 {
769 FILE *fp = (FILE *)data;
770
771 if (NIL_P(name)) {
772 fprintf(fp, "\tfrom %s:%d:in unknown method\n",
773 RSTRING_PTR(file), lineno);
774 }
775 else {
776 fprintf(fp, "\tfrom %s:%d:in `%s'\n",
777 RSTRING_PTR(file), lineno, RSTRING_PTR(name));
778 }
779 }
780
781 static void
782 vm_backtrace_print(FILE *fp)
783 {
784 struct oldbt_arg arg;
785
786 arg.func = oldbt_print;
787 arg.data = (void *)fp;
788 backtrace_each(GET_EC(),
789 oldbt_init,
790 oldbt_iter_iseq,
791 oldbt_iter_cfunc,
792 &arg);
793 }
794
795 static void
796 oldbt_bugreport(void *arg, VALUE file, int line, VALUE method)
797 {
798 const char *filename = NIL_P(file) ? "ruby" : RSTRING_PTR(file);
799 if (!*(int *)arg) {
800 fprintf(stderr, "-- Ruby level backtrace information "
801 "----------------------------------------\n");
802 *(int *)arg = 1;
803 }
804 if (NIL_P(method)) {
805 fprintf(stderr, "%s:%d:in unknown method\n", filename, line);
806 }
807 else {
808 fprintf(stderr, "%s:%d:in `%s'\n", filename, line, RSTRING_PTR(method));
809 }
810 }
811
812 void
813 rb_backtrace_print_as_bugreport(void)
814 {
815 struct oldbt_arg arg;
816 int i = 0;
817
818 arg.func = oldbt_bugreport;
819 arg.data = (int *)&i;
820
821 backtrace_each(GET_EC(),
822 oldbt_init,
823 oldbt_iter_iseq,
824 oldbt_iter_cfunc,
825 &arg);
826 }
827
828 void
829 rb_backtrace(void)
830 {
831 vm_backtrace_print(stderr);
832 }
833
834 struct print_to_arg {
835 VALUE (*iter)(VALUE recv, VALUE str);
836 VALUE output;
837 };
838
839 static void
840 oldbt_print_to(void *data, VALUE file, int lineno, VALUE name)
841 {
842 const struct print_to_arg *arg = data;
843 VALUE str = rb_sprintf("\tfrom %"PRIsVALUE":%d:in ", file, lineno);
844
845 if (NIL_P(name)) {
846 rb_str_cat2(str, "unknown method\n");
847 }
848 else {
849 rb_str_catf(str, " `%"PRIsVALUE"'\n", name);
850 }
851 (*arg->iter)(arg->output, str);
852 }
853
854 void
855 rb_backtrace_each(VALUE (*iter)(VALUE recv, VALUE str), VALUE output)
856 {
857 struct oldbt_arg arg;
858 struct print_to_arg parg;
859
860 parg.iter = iter;
861 parg.output = output;
862 arg.func = oldbt_print_to;
863 arg.data = &parg;
864 backtrace_each(GET_EC(),
865 oldbt_init,
866 oldbt_iter_iseq,
867 oldbt_iter_cfunc,
868 &arg);
869 }
870
871 VALUE
872 rb_make_backtrace(void)
873 {
874 return rb_ec_backtrace_str_ary(GET_EC(), 0, 0);
875 }
876
877 static VALUE
878 ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *argv, int lev_default, int lev_plus, int to_str)
879 {
880 VALUE level, vn;
881 long lev, n;
882 VALUE btval = rb_ec_backtrace_object(ec);
883 VALUE r;
884 rb_backtrace_t *bt;
885
886 GetCoreDataFromValue(btval, rb_backtrace_t, bt);
887
888 rb_scan_args(argc, argv, "02", &level, &vn);
889
890 if (argc == 2 && NIL_P(vn)) argc--;
891
892 switch (argc) {
893 case 0:
894 lev = lev_default + lev_plus;
895 n = bt->backtrace_size - lev;
896 break;
897 case 1:
898 {
899 long beg, len;
900 switch (rb_range_beg_len(level, &beg, &len, bt->backtrace_size - lev_plus, 0)) {
901 case Qfalse:
902 lev = NUM2LONG(level);
903 if (lev < 0) {
904 rb_raise(rb_eArgError, "negative level (%ld)", lev);
905 }
906 lev += lev_plus;
907 n = bt->backtrace_size - lev;
908 break;
909 case Qnil:
910 return Qnil;
911 default:
912 lev = beg + lev_plus;
913 n = len;
914 break;
915 }
916 break;
917 }
918 case 2:
919 lev = NUM2LONG(level);
920 n = NUM2LONG(vn);
921 if (lev < 0) {
922 rb_raise(rb_eArgError, "negative level (%ld)", lev);
923 }
924 if (n < 0) {
925 rb_raise(rb_eArgError, "negative size (%ld)", n);
926 }
927 lev += lev_plus;
928 break;
929 default:
930 lev = n = 0; /* to avoid warning */
931 break;
932 }
933
934 if (n == 0) {
935 return rb_ary_new();
936 }
937
938 if (to_str) {
939 r = backtrace_to_str_ary(btval, lev, n);
940 }
941 else {
942 r = backtrace_to_location_ary(btval, lev, n);
943 }
944 RB_GC_GUARD(btval);
945 return r;
946 }
947
948 static VALUE
949 thread_backtrace_to_ary(int argc, const VALUE *argv, VALUE thval, int to_str)
950 {
951 rb_thread_t *target_th = rb_thread_ptr(thval);
952
953 if (target_th->to_kill || target_th->status == THREAD_KILLED)
954 return Qnil;
955
956 return ec_backtrace_to_ary(target_th->ec, argc, argv, 0, 0, to_str);
957 }
958
959 VALUE
960 rb_vm_thread_backtrace(int argc, const VALUE *argv, VALUE thval)
961 {
962 return thread_backtrace_to_ary(argc, argv, thval, 1);
963 }
964
965 VALUE
966 rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval)
967 {
968 return thread_backtrace_to_ary(argc, argv, thval, 0);
969 }
970
971 /*
972 * call-seq:
973 * caller(start=1, length=nil) -> array or nil
974 * caller(range) -> array or nil
975 *
976 * Returns the current execution stack---an array containing strings in
977 * the form <code>file:line</code> or <code>file:line: in
978 * `method'</code>.
979 *
980 * The optional _start_ parameter determines the number of initial stack
981 * entries to omit from the top of the stack.
982 *
983 * A second optional +length+ parameter can be used to limit how many entries
984 * are returned from the stack.
985 *
986 * Returns +nil+ if _start_ is greater than the size of
987 * current execution stack.
988 *
989 * Optionally you can pass a range, which will return an array containing the
990 * entries within the specified range.
991 *
992 * def a(skip)
993 * caller(skip)
994 * end
995 * def b(skip)
996 * a(skip)
997 * end
998 * def c(skip)
999 * b(skip)
1000 * end
1001 * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10:in `<main>'"]
1002 * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11:in `<main>'"]
1003 * c(2) #=> ["prog:8:in `c'", "prog:12:in `<main>'"]
1004 * c(3) #=> ["prog:13:in `<main>'"]
1005 * c(4) #=> []
1006 * c(5) #=> nil
1007 */
1008
1009 static VALUE
1010 rb_f_caller(int argc, VALUE *argv, VALUE _)
1011 {
1012 return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 1);
1013 }
1014
1015 /*
1016 * call-seq:
1017 * caller_locations(start=1, length=nil) -> array or nil
1018 * caller_locations(range) -> array or nil
1019 *
1020 * Returns the current execution stack---an array containing
1021 * backtrace location objects.
1022 *
1023 * See Thread::Backtrace::Location for more information.
1024 *
1025 * The optional _start_ parameter determines the number of initial stack
1026 * entries to omit from the top of the stack.
1027 *
1028 * A second optional +length+ parameter can be used to limit how many entries
1029 * are returned from the stack.
1030 *
1031 * Returns +nil+ if _start_ is greater than the size of
1032 * current execution stack.
1033 *
1034 * Optionally you can pass a range, which will return an array containing the
1035 * entries within the specified range.
1036 */
1037 static VALUE
1038 rb_f_caller_locations(int argc, VALUE *argv, VALUE _)
1039 {
1040 return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 0);
1041 }
1042
1043 /* called from Init_vm() in vm.c */
1044 void
1045 Init_vm_backtrace(void)
1046 {
1047 /* :nodoc: */
1048 rb_cBacktrace = rb_define_class_under(rb_cThread, "Backtrace", rb_cObject);
1049 rb_define_alloc_func(rb_cBacktrace, backtrace_alloc);
1050 rb_undef_method(CLASS_OF(rb_cBacktrace), "new");
1051 rb_marshal_define_compat(rb_cBacktrace, rb_cArray, backtrace_dump_data, backtrace_load_data);
1052
1053 /*
1054 * An object representation of a stack frame, initialized by
1055 * Kernel#caller_locations.
1056 *
1057 * For example:
1058 *
1059 * # caller_locations.rb
1060 * def a(skip)
1061 * caller_locations(skip)
1062 * end
1063 * def b(skip)
1064 * a(skip)
1065 * end
1066 * def c(skip)
1067 * b(skip)
1068 * end
1069 *
1070 * c(0..2).map do |call|
1071 * puts call.to_s
1072 * end
1073 *
1074 * Running <code>ruby caller_locations.rb</code> will produce:
1075 *
1076 * caller_locations.rb:2:in `a'
1077 * caller_locations.rb:5:in `b'
1078 * caller_locations.rb:8:in `c'
1079 *
1080 * Here's another example with a slightly different result:
1081 *
1082 * # foo.rb
1083 * class Foo
1084 * attr_accessor :locations
1085 * def initialize(skip)
1086 * @locations = caller_locations(skip)
1087 * end
1088 * end
1089 *
1090 * Foo.new(0..2).locations.map do |call|
1091 * puts call.to_s
1092 * end
1093 *
1094 * Now run <code>ruby foo.rb</code> and you should see:
1095 *
1096 * init.rb:4:in `initialize'
1097 * init.rb:8:in `new'
1098 * init.rb:8:in `<main>'
1099 */
1100 rb_cBacktraceLocation = rb_define_class_under(rb_cBacktrace, "Location", rb_cObject);
1101 rb_undef_alloc_func(rb_cBacktraceLocation);
1102 rb_undef_method(CLASS_OF(rb_cBacktraceLocation), "new");
1103 rb_define_method(rb_cBacktraceLocation, "lineno", location_lineno_m, 0);
1104 rb_define_method(rb_cBacktraceLocation, "label", location_label_m, 0);
1105 rb_define_method(rb_cBacktraceLocation, "base_label", location_base_label_m, 0);
1106 rb_define_method(rb_cBacktraceLocation, "path", location_path_m, 0);
1107 rb_define_method(rb_cBacktraceLocation, "absolute_path", location_absolute_path_m, 0);
1108 rb_define_method(rb_cBacktraceLocation, "to_s", location_to_str_m, 0);
1109 rb_define_method(rb_cBacktraceLocation, "inspect", location_inspect_m, 0);
1110
1111 rb_define_global_function("caller", rb_f_caller, -1);
1112 rb_define_global_function("caller_locations", rb_f_caller_locations, -1);
1113 }
1114
1115 /* debugger API */
1116
1117 RUBY_SYMBOL_EXPORT_BEGIN
1118
1119 RUBY_SYMBOL_EXPORT_END
1120
1121 struct rb_debug_inspector_struct {
1122 rb_execution_context_t *ec;
1123 rb_control_frame_t *cfp;
1124 VALUE backtrace;
1125 VALUE contexts; /* [[klass, binding, iseq, cfp], ...] */
1126 long backtrace_size;
1127 };
1128
1129 enum {
1130 CALLER_BINDING_SELF,
1131 CALLER_BINDING_CLASS,
1132 CALLER_BINDING_BINDING,
1133 CALLER_BINDING_ISEQ,
1134 CALLER_BINDING_CFP
1135 };
1136
1137 struct collect_caller_bindings_data {
1138 VALUE ary;
1139 };
1140
1141 static void
1142 collect_caller_bindings_init(void *arg, size_t size)
1143 {
1144 /* */
1145 }
1146
1147 static VALUE
1148 get_klass(const rb_control_frame_t *cfp)
1149 {
1150 VALUE klass;
1151 if (rb_vm_control_frame_id_and_class(cfp, 0, 0, &klass)) {
1152 if (RB_TYPE_P(klass, T_ICLASS)) {
1153 return RBASIC(klass)->klass;
1154 }
1155 else {
1156 return klass;
1157 }
1158 }
1159 else {
1160 return Qnil;
1161 }
1162 }
1163
1164 static void
1165 collect_caller_bindings_iseq(void *arg, const rb_control_frame_t *cfp)
1166 {
1167 struct collect_caller_bindings_data *data = (struct collect_caller_bindings_data *)arg;
1168 VALUE frame = rb_ary_new2(5);
1169
1170 rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self);
1171 rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
1172 rb_ary_store(frame, CALLER_BINDING_BINDING, GC_GUARDED_PTR(cfp)); /* create later */
1173 rb_ary_store(frame, CALLER_BINDING_ISEQ, cfp->iseq ? (VALUE)cfp->iseq : Qnil);
1174 rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp));
1175
1176 rb_ary_push(data->ary, frame);
1177 }
1178
1179 static void
1180 collect_caller_bindings_cfunc(void *arg, const rb_control_frame_t *cfp, ID mid)
1181 {
1182 struct collect_caller_bindings_data *data = (struct collect_caller_bindings_data *)arg;
1183 VALUE frame = rb_ary_new2(5);
1184
1185 rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self);
1186 rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
1187 rb_ary_store(frame, CALLER_BINDING_BINDING, Qnil); /* not available */
1188 rb_ary_store(frame, CALLER_BINDING_ISEQ, Qnil); /* not available */
1189 rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp));
1190
1191 rb_ary_push(data->ary, frame);
1192 }
1193
1194 static VALUE
1195 collect_caller_bindings(const rb_execution_context_t *ec)
1196 {
1197 struct collect_caller_bindings_data data;
1198 VALUE result;
1199 int i;
1200
1201 data.ary = rb_ary_new();
1202
1203 backtrace_each(ec,
1204 collect_caller_bindings_init,
1205 collect_caller_bindings_iseq,
1206 collect_caller_bindings_cfunc,
1207 &data);
1208
1209 result = rb_ary_reverse(data.ary);
1210
1211 /* bindings should be created from top of frame */
1212 for (i=0; i<RARRAY_LEN(result); i++) {
1213 VALUE entry = rb_ary_entry(result, i);
1214 VALUE cfp_val = rb_ary_entry(entry, CALLER_BINDING_BINDING);
1215
1216 if (!NIL_P(cfp_val)) {
1217 rb_control_frame_t *cfp = GC_GUARDED_PTR_REF(cfp_val);
1218 rb_ary_store(entry, CALLER_BINDING_BINDING, rb_vm_make_binding(ec, cfp));
1219 }
1220 }
1221
1222 return result;
1223 }
1224
1225 /*
1226 * Note that the passed `rb_debug_inspector_t' will be disabled
1227 * after `rb_debug_inspector_open'.
1228 */
1229
1230 VALUE
1231 rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data)
1232 {
1233 rb_debug_inspector_t dbg_context;
1234 rb_execution_context_t *ec = GET_EC();
1235 enum ruby_tag_type state;
1236 volatile VALUE MAYBE_UNUSED(result);
1237
1238 /* escape all env to heap */
1239 rb_vm_stack_to_heap(ec);
1240
1241 dbg_context.ec = ec;
1242 dbg_context.cfp = dbg_context.ec->cfp;
1243 dbg_context.backtrace = rb_ec_backtrace_location_ary(ec, 0, 0);
1244 dbg_context.backtrace_size = RARRAY_LEN(dbg_context.backtrace);
1245 dbg_context.contexts = collect_caller_bindings(ec);
1246
1247 EC_PUSH_TAG(ec);
1248 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1249 result = (*func)(&dbg_context, data);
1250 }
1251 EC_POP_TAG();
1252
1253 /* invalidate bindings? */
1254
1255 if (state) {
1256 EC_JUMP_TAG(ec, state);
1257 }
1258
1259 return result;
1260 }
1261
1262 static VALUE
1263 frame_get(const rb_debug_inspector_t *dc, long index)
1264 {
1265 if (index < 0 || index >= dc->backtrace_size) {
1266 rb_raise(rb_eArgError, "no such frame");
1267 }
1268 return rb_ary_entry(dc->contexts, index);
1269 }
1270
1271 VALUE
1272 rb_debug_inspector_frame_self_get(const rb_debug_inspector_t *dc, long index)
1273 {
1274 VALUE frame = frame_get(dc, index);
1275 return rb_ary_entry(frame, CALLER_BINDING_SELF);
1276 }
1277
1278 VALUE
1279 rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, long index)
1280 {
1281 VALUE frame = frame_get(dc, index);
1282 return rb_ary_entry(frame, CALLER_BINDING_CLASS);
1283 }
1284
1285 VALUE
1286 rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long index)
1287 {
1288 VALUE frame = frame_get(dc, index);
1289 return rb_ary_entry(frame, CALLER_BINDING_BINDING);
1290 }
1291
1292 VALUE
1293 rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index)
1294 {
1295 VALUE frame = frame_get(dc, index);
1296 VALUE iseq = rb_ary_entry(frame, CALLER_BINDING_ISEQ);
1297
1298 return RTEST(iseq) ? rb_iseqw_new((rb_iseq_t *)iseq) : Qnil;
1299 }
1300
1301 VALUE
1302 rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc)
1303 {
1304 return dc->backtrace;
1305 }
1306
1307 int
1308 rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
1309 {
1310 int i;
1311 const rb_execution_context_t *ec = GET_EC();
1312 const rb_control_frame_t *cfp = ec->cfp, *end_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
1313 const rb_callable_method_entry_t *cme;
1314
1315 for (i=0; i<limit && cfp != end_cfp;) {
1316 if (VM_FRAME_RUBYFRAME_P(cfp)) {
1317 if (start > 0) {
1318 start--;
1319 continue;
1320 }
1321
1322 /* record frame info */
1323 cme = rb_vm_frame_method_entry(cfp);
1324 if (cme && cme->def->type == VM_METHOD_TYPE_ISEQ) {
1325 buff[i] = (VALUE)cme;
1326 }
1327 else {
1328 buff[i] = (VALUE)cfp->iseq;
1329 }
1330
1331 if (lines) lines[i] = calc_lineno(cfp->iseq, cfp->pc);
1332
1333 i++;
1334 }
1335 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
1336 }
1337
1338 return i;
1339 }
1340
1341 static const rb_iseq_t *
1342 frame2iseq(VALUE frame)
1343 {
1344 if (frame == Qnil) return NULL;
1345
1346 if (RB_TYPE_P(frame, T_IMEMO)) {
1347 switch (imemo_type(frame)) {
1348 case imemo_iseq:
1349 return (const rb_iseq_t *)frame;
1350 case imemo_ment:
1351 {
1352 const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame;
1353 switch (cme->def->type) {
1354 case VM_METHOD_TYPE_ISEQ:
1355 return cme->def->body.iseq.iseqptr;
1356 default:
1357 return NULL;
1358 }
1359 }
1360 default:
1361 break;
1362 }
1363 }
1364 rb_bug("frame2iseq: unreachable");
1365 }
1366
1367 VALUE
1368 rb_profile_frame_path(VALUE frame)
1369 {
1370 const rb_iseq_t *iseq = frame2iseq(frame);
1371 return iseq ? rb_iseq_path(iseq) : Qnil;
1372 }
1373
1374 VALUE
1375 rb_profile_frame_absolute_path(VALUE frame)
1376 {
1377 const rb_iseq_t *iseq = frame2iseq(frame);
1378 return iseq ? rb_iseq_realpath(iseq) : Qnil;
1379 }
1380
1381 VALUE
1382 rb_profile_frame_label(VALUE frame)
1383 {
1384 const rb_iseq_t *iseq = frame2iseq(frame);
1385 return iseq ? rb_iseq_label(iseq) : Qnil;
1386 }
1387
1388 VALUE
1389 rb_profile_frame_base_label(VALUE frame)
1390 {
1391 const rb_iseq_t *iseq = frame2iseq(frame);
1392 return iseq ? rb_iseq_base_label(iseq) : Qnil;
1393 }
1394
1395 VALUE
1396 rb_profile_frame_first_lineno(VALUE frame)
1397 {
1398 const rb_iseq_t *iseq = frame2iseq(frame);
1399 return iseq ? rb_iseq_first_lineno(iseq) : Qnil;
1400 }
1401
1402 static VALUE
1403 frame2klass(VALUE frame)
1404 {
1405 if (frame == Qnil) return Qnil;
1406
1407 if (RB_TYPE_P(frame, T_IMEMO)) {
1408 const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame;
1409
1410 if (imemo_type(frame) == imemo_ment) {
1411 return cme->defined_class;
1412 }
1413 }
1414 return Qnil;
1415 }
1416
1417 VALUE
1418 rb_profile_frame_classpath(VALUE frame)
1419 {
1420 VALUE klass = frame2klass(frame);
1421
1422 if (klass && !NIL_P(klass)) {
1423 if (RB_TYPE_P(klass, T_ICLASS)) {
1424 klass = RBASIC(klass)->klass;
1425 }
1426 else if (FL_TEST(klass, FL_SINGLETON)) {
1427 klass = rb_ivar_get(klass, id__attached__);
1428 if (!RB_TYPE_P(klass, T_CLASS))
1429 return rb_sprintf("#<%s:%p>", rb_class2name(rb_obj_class(klass)), (void*)klass);
1430 }
1431 return rb_class_path(klass);
1432 }
1433 else {
1434 return Qnil;
1435 }
1436 }
1437
1438 VALUE
1439 rb_profile_frame_singleton_method_p(VALUE frame)
1440 {
1441 VALUE klass = frame2klass(frame);
1442
1443 if (klass && !NIL_P(klass) && FL_TEST(klass, FL_SINGLETON)) {
1444 return Qtrue;
1445 }
1446 else {
1447 return Qfalse;
1448 }
1449 }
1450
1451 VALUE
1452 rb_profile_frame_method_name(VALUE frame)
1453 {
1454 const rb_iseq_t *iseq = frame2iseq(frame);
1455 return iseq ? rb_iseq_method_name(iseq) : Qnil;
1456 }
1457
1458 VALUE
1459 rb_profile_frame_qualified_method_name(VALUE frame)
1460 {
1461 VALUE method_name = rb_profile_frame_method_name(frame);
1462
1463 if (method_name != Qnil) {
1464 VALUE classpath = rb_profile_frame_classpath(frame);
1465 VALUE singleton_p = rb_profile_frame_singleton_method_p(frame);
1466
1467 if (classpath != Qnil) {
1468 return rb_sprintf("%"PRIsVALUE"%s%"PRIsVALUE,
1469 classpath, singleton_p == Qtrue ? "." : "#", method_name);
1470 }
1471 else {
1472 return method_name;
1473 }
1474 }
1475 else {
1476 return Qnil;
1477 }
1478 }
1479
1480 VALUE
1481 rb_profile_frame_full_label(VALUE frame)
1482 {
1483 VALUE label = rb_profile_frame_label(frame);
1484 VALUE base_label = rb_profile_frame_base_label(frame);
1485 VALUE qualified_method_name = rb_profile_frame_qualified_method_name(frame);
1486
1487 if (NIL_P(qualified_method_name) || base_label == qualified_method_name) {
1488 return label;
1489 }
1490 else {
1491 long label_length = RSTRING_LEN(label);
1492 long base_label_length = RSTRING_LEN(base_label);
1493 int prefix_len = rb_long2int(label_length - base_label_length);
1494
1495 return rb_sprintf("%.*s%"PRIsVALUE, prefix_len, RSTRING_PTR(label), qualified_method_name);
1496 }
1497 }
rb_cArray
VALUE rb_cArray
Definition: array.c:27
rb_backtrace_location_struct::body
union rb_backtrace_location_struct::@171 body
rb_iseq_realpath
VALUE rb_iseq_realpath(const rb_iseq_t *iseq)
Definition: iseq.c:1033
rb_backtrace_location_struct::cfunc
struct rb_backtrace_location_struct::@171::@173 cfunc
UNLIKELY
#define UNLIKELY(x)
Definition: ffi_common.h:126
ID
unsigned long ID
Definition: ruby.h:103
RUBY_SYMBOL_EXPORT_END
#define RUBY_SYMBOL_EXPORT_END
Definition: missing.h:49
ruby_xfree
void ruby_xfree(void *x)
Definition: gc.c:10150
print_to_arg::output
VALUE output
Definition: vm_backtrace.c:836
void
void
Definition: rb_mjit_min_header-2.7.0.h:13273
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1244
rb_profile_frame_method_name
VALUE rb_profile_frame_method_name(VALUE frame)
Definition: vm_backtrace.c:1452
rb_backtrace_to_location_ary
VALUE rb_backtrace_to_location_ary(VALUE self)
Definition: vm_backtrace.c:686
rb_iseq_label
VALUE rb_iseq_label(const rb_iseq_t *iseq)
Definition: iseq.c:1045
rb_iseq_first_lineno
VALUE rb_iseq_first_lineno(const rb_iseq_t *iseq)
Definition: iseq.c:1057
collect_caller_bindings_data::ary
VALUE ary
Definition: vm_backtrace.c:1138
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:717
rb_iseq_struct
Definition: vm_core.h:456
rb_profile_frame_base_label
VALUE rb_profile_frame_base_label(VALUE frame)
Definition: vm_backtrace.c:1389
rb_debug_inspector_struct::backtrace
VALUE backtrace
Definition: vm_backtrace.c:1124
rb_make_backtrace
VALUE rb_make_backtrace(void)
Definition: vm_backtrace.c:872
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
rb_backtrace_struct::backtrace
rb_backtrace_location_t * backtrace
Definition: vm_backtrace.c:404
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
rb_backtrace_struct
Definition: vm_backtrace.c:403
rb_profile_frame_label
VALUE rb_profile_frame_label(VALUE frame)
Definition: vm_backtrace.c:1382
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
rb_backtrace_p
int rb_backtrace_p(VALUE obj)
Definition: vm_backtrace.c:446
rb_marshal_define_compat
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Definition: marshal.c:133
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
rb_backtrace_use_iseq_first_lineno_for_last_location
MJIT_FUNC_EXPORTED void rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self)
Definition: vm_backtrace.c:632
rb_enc_sprintf
VALUE rb_enc_sprintf(rb_encoding *enc, const char *format,...)
Definition: sprintf.c:1178
VALUE
unsigned long VALUE
Definition: ruby.h:102
index
int index
Definition: rb_mjit_min_header-2.7.0.h:11246
GET_VM
#define GET_VM()
Definition: vm_core.h:1764
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
encoding.h
rb_ary_store
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:1079
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
rb_callable_method_entry_struct
Definition: method.h:59
imemo_iseq
@ imemo_iseq
Definition: internal.h:1140
rb_method_definition_struct::type
rb_method_type_t type
Definition: rb_mjit_min_header-2.7.0.h:8877
rb_backtrace_location_struct::prev_loc
struct rb_backtrace_location_struct * prev_loc
Definition: vm_backtrace.c:103
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1787
rb_iseq_path
VALUE rb_iseq_path(const rb_iseq_t *iseq)
Definition: iseq.c:1027
rb_backtrace_location_struct::mid
ID mid
Definition: vm_backtrace.c:102
EC_JUMP_TAG
#define EC_JUMP_TAG(ec, st)
Definition: eval_intern.h:184
rb_thread_struct::to_kill
unsigned int to_kill
Definition: vm_core.h:933
rb_profile_frame_classpath
VALUE rb_profile_frame_classpath(VALUE frame)
Definition: vm_backtrace.c:1418
rb_iseq_constant_body::location
rb_iseq_location_t location
Definition: vm_core.h:399
RUBY_VM_NEXT_CONTROL_FRAME
#define RUBY_VM_NEXT_CONTROL_FRAME(cfp)
Definition: vm_core.h:1385
rb_iseq_location_struct::first_lineno
VALUE first_lineno
Definition: vm_core.h:276
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
rb_backtrace_location_struct::LOCATION_TYPE_ISEQ
@ LOCATION_TYPE_ISEQ
Definition: vm_backtrace.c:87
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
GET_EC
#define GET_EC()
Definition: vm_core.h:1766
rb_long2int
#define rb_long2int(n)
Definition: ruby.h:350
rb_backtrace_each
void rb_backtrace_each(VALUE(*iter)(VALUE recv, VALUE str), VALUE output)
Definition: vm_backtrace.c:855
rb_ec_backtrace_location_ary
VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n)
Definition: vm_backtrace.c:720
ptr
struct RIMemo * ptr
Definition: debug.c:74
rb_str_inspect
VALUE rb_str_inspect(VALUE)
Definition: string.c:5930
rb_method_iseq_struct::iseqptr
rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
Definition: method.h:127
rb_backtrace_struct::strary
VALUE strary
Definition: vm_backtrace.c:407
Qfalse
#define Qfalse
Definition: ruby.h:467
THREAD_KILLED
@ THREAD_KILLED
Definition: vm_core.h:786
rb_debug_inspector_frame_iseq_get
VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index)
Definition: vm_backtrace.c:1293
rb_profile_frame_full_label
VALUE rb_profile_frame_full_label(VALUE frame)
Definition: vm_backtrace.c:1481
rb_backtrace_struct::backtrace_size
int backtrace_size
Definition: vm_backtrace.c:406
rb_backtrace_location_struct::LOCATION_TYPE_ISEQ_CALCED
@ LOCATION_TYPE_ISEQ_CALCED
Definition: vm_backtrace.c:88
rb_id2str
#define rb_id2str(id)
Definition: vm_backtrace.c:30
CALLER_BINDING_CFP
@ CALLER_BINDING_CFP
Definition: vm_backtrace.c:1134
NULL
#define NULL
Definition: _sdbm.c:101
rb_print_backtrace
void rb_print_backtrace(void)
Definition: vm_dump.c:750
valued_frame_info
Definition: vm_backtrace.c:108
FL_TEST
#define FL_TEST(x, f)
Definition: ruby.h:1353
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
oldbt_arg::filename
VALUE filename
Definition: vm_backtrace.c:728
rb_ec_backtrace_str_ary
VALUE rb_ec_backtrace_str_ary(const rb_execution_context_t *ec, long lev, long n)
Definition: vm_backtrace.c:714
oldbt_arg::data
void * data
Definition: vm_backtrace.c:731
rb_profile_frame_singleton_method_p
VALUE rb_profile_frame_singleton_method_p(VALUE frame)
Definition: vm_backtrace.c:1439
rb_thread_struct::ec
rb_execution_context_t * ec
Definition: vm_core.h:915
VM_ASSERT
#define VM_ASSERT(expr)
Definition: vm_core.h:56
rb_profile_frame_first_lineno
VALUE rb_profile_frame_first_lineno(VALUE frame)
Definition: vm_backtrace.c:1396
rb_backtrace_location_struct::lineno
int lineno
Definition: vm_backtrace.c:98
ASSUME
#define ASSUME(x)
Definition: ruby.h:52
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1575
rb_backtrace_location_struct::type
enum rb_backtrace_location_struct::LOCATION_TYPE type
pc
rb_control_frame_t const VALUE * pc
Definition: rb_mjit_min_header-2.7.0.h:16923
rb_backtrace_location_struct
Definition: vm_backtrace.c:85
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
RUBY_TYPED_DEFAULT_FREE
#define RUBY_TYPED_DEFAULT_FREE
Definition: ruby.h:1203
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
rb_debug_inspector_open
VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data)
Definition: vm_backtrace.c:1231
rb_ivar_get
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1070
rb_execution_context_struct::cfp
rb_control_frame_t * cfp
Definition: vm_core.h:847
rb_iseq_constant_body::local_table
const ID * local_table
Definition: vm_core.h:411
rb_debug_inspector_backtrace_locations
VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc)
Definition: vm_backtrace.c:1302
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
rb_obj_class
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
rb_method_definition_struct::body
union rb_method_definition_struct::@118 body
T_ICLASS
#define T_ICLASS
Definition: ruby.h:525
rb_debug_inspector_struct
Definition: vm_backtrace.c:1121
imemo_type
imemo_type
Definition: internal.h:1132
bt_iter_arg::bt
rb_backtrace_t * bt
Definition: vm_backtrace.c:518
fprintf
int fprintf(FILE *__restrict, const char *__restrict,...) __attribute__((__format__(__printf__
LIKELY
#define LIKELY(x)
Definition: ffi_common.h:125
EC_POP_TAG
#define EC_POP_TAG()
Definition: eval_intern.h:137
rb_callable_method_entry_struct::defined_class
const VALUE defined_class
Definition: method.h:61
rb_vm_make_binding
VALUE rb_vm_make_binding(const rb_execution_context_t *ec, const rb_control_frame_t *src_cfp)
Definition: vm.c:953
rb_iseqw_new
VALUE rb_iseqw_new(const rb_iseq_t *)
Definition: iseq.c:1157
iseq.h
rb_iseq_location_struct::label
VALUE label
Definition: vm_core.h:275
rb_debug_inspector_frame_self_get
VALUE rb_debug_inspector_frame_self_get(const rb_debug_inspector_t *dc, long index)
Definition: vm_backtrace.c:1272
rb_iseq_constant_body::local_table_size
unsigned int local_table_size
Definition: vm_core.h:435
rb_thread_struct::status
enum rb_thread_status status
Definition: rb_mjit_min_header-2.7.0.h:9892
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
rb_backtrace_struct::backtrace_base
rb_backtrace_location_t * backtrace_base
Definition: vm_backtrace.c:405
rb_backtrace_location_struct::LOCATION_TYPE_CFUNC
@ LOCATION_TYPE_CFUNC
Definition: vm_backtrace.c:89
CALLER_BINDING_BINDING
@ CALLER_BINDING_BINDING
Definition: vm_backtrace.c:1132
rb_backtrace_location_struct::LOCATION_TYPE_IFUNC
@ LOCATION_TYPE_IFUNC
Definition: vm_backtrace.c:90
rb_backtrace_print_as_bugreport
void rb_backtrace_print_as_bugreport(void)
Definition: vm_backtrace.c:813
rb_debug_inspector_frame_class_get
VALUE rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, long index)
Definition: vm_backtrace.c:1279
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
rb_backtrace_struct::locary
VALUE locary
Definition: vm_backtrace.c:408
EC_EXEC_TAG
#define EC_EXEC_TAG()
Definition: eval_intern.h:181
rb_profile_frame_absolute_path
VALUE rb_profile_frame_absolute_path(VALUE frame)
Definition: vm_backtrace.c:1375
rb_method_definition_struct::iseq
rb_method_iseq_t iseq
Definition: method.h:169
rb_backtrace_location_t
struct rb_backtrace_location_struct rb_backtrace_location_t
rb_debug_inspector_struct::ec
rb_execution_context_t * ec
Definition: vm_backtrace.c:1122
vm_core.h
stderr
#define stderr
Definition: rb_mjit_min_header-2.7.0.h:1485
rb_iseq_constant_body::type
enum rb_iseq_constant_body::iseq_type type
T_CLASS
#define T_CLASS
Definition: ruby.h:524
rb_vm_thread_backtrace
VALUE rb_vm_thread_backtrace(int argc, const VALUE *argv, VALUE thval)
Definition: vm_backtrace.c:960
rb_control_frame_struct
Definition: vm_core.h:760
rb_ec_backtrace_object
MJIT_FUNC_EXPORTED VALUE rb_ec_backtrace_object(const rb_execution_context_t *ec)
Definition: vm_backtrace.c:557
size
int size
Definition: encoding.c:58
rb_enc_compatible
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
Definition: encoding.c:974
print_to_arg
Definition: vm_backtrace.c:834
oldbt_arg
Definition: vm_backtrace.c:727
rb_iseq_base_label
VALUE rb_iseq_base_label(const rb_iseq_t *iseq)
Definition: iseq.c:1051
rb_class2name
const char * rb_class2name(VALUE)
Definition: variable.c:280
me
const rb_callable_method_entry_t * me
Definition: rb_mjit_min_header-2.7.0.h:13226
RUBYVM_CFUNC_FRAME_P
#define RUBYVM_CFUNC_FRAME_P(cfp)
Definition: vm_core.h:1287
rb_cThread
RUBY_EXTERN VALUE rb_cThread
Definition: ruby.h:2047
Init_vm_backtrace
void Init_vm_backtrace(void)
Definition: vm_backtrace.c:1045
rb_typeddata_is_kind_of
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:872
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
CALLER_BINDING_SELF
@ CALLER_BINDING_SELF
Definition: vm_backtrace.c:1130
rb_iseq_line_no
unsigned int rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
Definition: iseq.c:1761
rb_profile_frame_path
VALUE rb_profile_frame_path(VALUE frame)
Definition: vm_backtrace.c:1368
rb_vm_frame_method_entry
const MJIT_STATIC rb_callable_method_entry_t * rb_vm_frame_method_entry(const rb_control_frame_t *cfp)
Definition: rb_mjit_min_header-2.7.0.h:12521
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
imemo_ment
@ imemo_ment
Definition: internal.h:1139
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
rb_str_cat_cstr
#define rb_str_cat_cstr(str, ptr)
Definition: rb_mjit_min_header-2.7.0.h:6126
oldbt_arg::func
void(* func)(void *data, VALUE file, int lineno, VALUE name)
Definition: vm_backtrace.c:730
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:634
rb_control_frame_struct::self
VALUE self
Definition: vm_core.h:764
rb_profile_frame_qualified_method_name
VALUE rb_profile_frame_qualified_method_name(VALUE frame)
Definition: vm_backtrace.c:1459
internal.h
oldbt_arg::lineno
int lineno
Definition: vm_backtrace.c:729
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
argv
char ** argv
Definition: ruby.c:223
rb_debug_inspector_frame_binding_get
VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long index)
Definition: vm_backtrace.c:1286
rb_profile_frames
int rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
Definition: vm_backtrace.c:1308
rb_iseq_constant_body::iseq_encoded
VALUE * iseq_encoded
Definition: vm_core.h:325
RUBY_SYMBOL_EXPORT_BEGIN
#define RUBY_SYMBOL_EXPORT_BEGIN
Definition: missing.h:48
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:63
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1197
rb_range_beg_len
VALUE rb_range_beg_len(VALUE, long *, long *, long, int)
Definition: range.c:1273
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
valued_frame_info::loc
rb_backtrace_location_t * loc
Definition: vm_backtrace.c:109
rb_backtrace_location_struct::iseq
const rb_iseq_t * iseq
Definition: vm_backtrace.c:95
CALLER_BINDING_ISEQ
@ CALLER_BINDING_ISEQ
Definition: vm_backtrace.c:1133
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
bt_iter_arg::prev_loc
rb_backtrace_location_t * prev_loc
Definition: vm_backtrace.c:520
rb_control_frame_struct::iseq
const rb_iseq_t * iseq
Definition: vm_core.h:763
rb_vm_control_frame_id_and_class
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp)
Definition: vm.c:2184
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
rb_vm_thread_backtrace_locations
VALUE rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval)
Definition: vm_backtrace.c:966
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
TAG_NONE
#define TAG_NONE
Definition: vm_core.h:197
rb_vm_stack_to_heap
void rb_vm_stack_to_heap(rb_execution_context_t *ec)
Definition: vm.c:786
argc
int argc
Definition: ruby.c:222
VM_METHOD_TYPE_ISEQ
@ VM_METHOD_TYPE_ISEQ
Ruby method.
Definition: method.h:102
rb_debug_inspector_struct::contexts
VALUE contexts
Definition: vm_backtrace.c:1125
T_IMEMO
#define T_IMEMO
Definition: ruby.h:543
rb_data_type_struct
Definition: ruby.h:1148
rb_method_definition_struct::original_id
ID original_id
Definition: method.h:179
bt_iter_arg::btobj
VALUE btobj
Definition: vm_backtrace.c:519
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
bt_iter_arg
Definition: vm_backtrace.c:517
rb_debug_inspector_struct::cfp
rb_control_frame_t * cfp
Definition: vm_backtrace.c:1123
CALLER_BINDING_CLASS
@ CALLER_BINDING_CLASS
Definition: vm_backtrace.c:1131
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5212
MJIT_FUNC_EXPORTED
#define MJIT_FUNC_EXPORTED
Definition: defines.h:396
_
#define _(args)
Definition: dln.h:28
EC_PUSH_TAG
#define EC_PUSH_TAG(ec)
Definition: eval_intern.h:130
rb_callable_method_entry_struct::def
struct rb_method_definition_struct *const def
Definition: method.h:62
Qtrue
#define Qtrue
Definition: ruby.h:468
rb_str_catf
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1237
len
uint8_t len
Definition: escape.c:17
rb_class_path
VALUE rb_class_path(VALUE)
Definition: variable.c:153
rb_iseq_struct::body
struct rb_iseq_constant_body * body
Definition: vm_core.h:460
rb_control_frame_struct::pc
const VALUE * pc
Definition: vm_core.h:761
rb_iseq_constant_body::iseq_size
unsigned int iseq_size
Definition: vm_core.h:324
MAYBE_UNUSED
#define MAYBE_UNUSED
Definition: ffi_common.h:32
FL_SINGLETON
#define FL_SINGLETON
Definition: ruby.h:1278
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
rb_backtrace_to_str_ary
VALUE rb_backtrace_to_str_ary(VALUE self)
Definition: vm_backtrace.c:620
iseq
const rb_iseq_t * iseq
Definition: rb_mjit_min_header-2.7.0.h:13504
eval_intern.h
rb_backtrace_t
struct rb_backtrace_struct rb_backtrace_t
rb_debug_inspector_func_t
VALUE(* rb_debug_inspector_func_t)(const rb_debug_inspector_t *, void *)
Definition: debug.h:43
rb_ary_reverse
VALUE rb_ary_reverse(VALUE ary)
Definition: array.c:2544
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
rb_vm_get_sourceline
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:68
Qnil
#define Qnil
Definition: ruby.h:469
collect_caller_bindings_data
Definition: vm_backtrace.c:1137
rb_backtrace_location_struct::pc
const VALUE * pc
Definition: vm_backtrace.c:97
rb_debug_inspector_struct::backtrace_size
long backtrace_size
Definition: vm_backtrace.c:1126
valued_frame_info::btobj
VALUE btobj
Definition: vm_backtrace.c:110
GetCoreDataFromValue
#define GetCoreDataFromValue(obj, type, ptr)
Definition: vm_core.h:270
rb_undef_alloc_func
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:722
rb_iseq_method_name
VALUE rb_iseq_method_name(const rb_iseq_t *iseq)
Definition: iseq.c:1063
rb_backtrace_location_struct::LOCATION_TYPE
LOCATION_TYPE
Definition: vm_backtrace.c:86
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
rb_thread_struct
Definition: vm_core.h:910
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
ptrdiff_t
long int ptrdiff_t
Definition: rb_mjit_min_header-2.7.0.h:802
RUBY_VM_PREVIOUS_CONTROL_FRAME
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)
Definition: vm_core.h:1384
id__attached__
@ id__attached__
Definition: rb_mjit_min_header-2.7.0.h:8708
ruby_tag_type
ruby_tag_type
Definition: vm_core.h:184
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
RTEST
#define RTEST(v)
Definition: ruby.h:481
debug.h
rb_iseq_location_struct::base_label
VALUE base_label
Definition: vm_core.h:274
__sFILE
Definition: vsnprintf.c:169
GC_GUARDED_PTR_REF
#define GC_GUARDED_PTR_REF(p)
Definition: vm_core.h:1149
GC_GUARDED_PTR
#define GC_GUARDED_PTR(p)
Definition: vm_core.h:1148
cfp
rb_control_frame_t * cfp
Definition: rb_mjit_min_header-2.7.0.h:14544
print_to_arg::iter
VALUE(* iter)(VALUE recv, VALUE str)
Definition: vm_backtrace.c:835
name
const char * name
Definition: nkf.c:208
rb_execution_context_struct
Definition: vm_core.h:843
rb_backtrace
void rb_backtrace(void)
Definition: vm_backtrace.c:829