12#include "eval_intern.h"
14#include "internal/error.h"
15#include "internal/vm.h"
21static VALUE rb_cBacktrace;
22static VALUE rb_cBacktraceLocation;
27 VALUE str = rb_id2str(
id);
28 if (!str)
return Qnil;
31#define rb_id2str(id) id2str(id)
33#define BACKTRACE_START 0
34#define ALL_BACKTRACE_LINES -1
37calc_pos(
const rb_iseq_t *iseq,
const VALUE *pc,
int *lineno,
int *node_id)
42 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_TOP) {
43 VM_ASSERT(! ISEQ_BODY(iseq)->local_table);
44 VM_ASSERT(! ISEQ_BODY(iseq)->local_table_size);
47 if (lineno) *lineno = ISEQ_BODY(iseq)->location.first_lineno;
48#ifdef USE_ISEQ_NODE_ID
49 if (node_id) *node_id = -1;
54 VM_ASSERT(ISEQ_BODY(iseq));
55 VM_ASSERT(ISEQ_BODY(iseq)->iseq_encoded);
56 VM_ASSERT(ISEQ_BODY(iseq)->iseq_size);
58 ptrdiff_t n = pc - ISEQ_BODY(iseq)->iseq_encoded;
59 VM_ASSERT(n <= ISEQ_BODY(iseq)->iseq_size);
67#if VMDEBUG && defined(HAVE_BUILTIN___BUILTIN_TRAP)
74 if (lineno) *lineno = rb_iseq_line_no(iseq, pos);
75#ifdef USE_ISEQ_NODE_ID
76 if (node_id) *node_id = rb_iseq_node_id(iseq, pos);
86 if (calc_pos(iseq, pc, &lineno, NULL))
return lineno;
90#ifdef USE_ISEQ_NODE_ID
95 if (calc_pos(iseq, pc, NULL, &node_id))
return node_id;
103 if (VM_FRAME_RUBYFRAME_P(cfp) && cfp->iseq) {
105 int line = calc_lineno(iseq, cfp->pc);
110 return ISEQ_BODY(iseq)->location.first_lineno;
120 LOCATION_TYPE_ISEQ = 1,
135location_mark(
void *ptr)
138 rb_gc_mark(vfi->btobj);
145 case LOCATION_TYPE_ISEQ:
146 rb_gc_mark_movable((
VALUE)fi->iseq);
148 case LOCATION_TYPE_CFUNC:
150 rb_gc_mark_movable((
VALUE)fi->iseq);
159location_memsize(
const void *ptr)
168 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
172rb_frame_info_p(
VALUE obj)
178location_ptr(
VALUE locobj)
189 case LOCATION_TYPE_ISEQ:
190 return calc_lineno(loc->iseq, loc->pc);
191 case LOCATION_TYPE_CFUNC:
192 if (loc->iseq && loc->pc) {
193 return calc_lineno(loc->iseq, loc->pc);
197 rb_bug(
"location_lineno: unreachable");
211location_lineno_m(
VALUE self)
213 return INT2FIX(location_lineno(location_ptr(self)));
220 case LOCATION_TYPE_ISEQ:
221 return ISEQ_BODY(loc->iseq)->location.label;
222 case LOCATION_TYPE_CFUNC:
223 return rb_id2str(loc->mid);
225 rb_bug(
"location_label: unreachable");
258location_label_m(
VALUE self)
260 return location_label(location_ptr(self));
267 case LOCATION_TYPE_ISEQ:
268 return ISEQ_BODY(loc->iseq)->location.base_label;
269 case LOCATION_TYPE_CFUNC:
270 return rb_id2str(loc->mid);
272 rb_bug(
"location_base_label: unreachable");
283location_base_label_m(
VALUE self)
285 return location_base_label(location_ptr(self));
292 case LOCATION_TYPE_ISEQ:
294 case LOCATION_TYPE_CFUNC:
297 rb_bug(
"location_iseq: unreachable");
313location_path_m(
VALUE self)
315 const rb_iseq_t *iseq = location_iseq(location_ptr(self));
316 return iseq ? rb_iseq_path(iseq) :
Qnil;
319#ifdef USE_ISEQ_NODE_ID
324 case LOCATION_TYPE_ISEQ:
325 return calc_node_id(loc->iseq, loc->pc);
326 case LOCATION_TYPE_CFUNC:
327 if (loc->iseq && loc->pc) {
328 return calc_node_id(loc->iseq, loc->pc);
332 rb_bug(
"location_node_id: unreachable");
339rb_get_node_id_from_frame_info(
VALUE obj)
341#ifdef USE_ISEQ_NODE_ID
343 return location_node_id(loc);
350rb_get_iseq_from_frame_info(
VALUE obj)
353 const rb_iseq_t *iseq = location_iseq(loc);
361 case LOCATION_TYPE_ISEQ:
362 return rb_iseq_realpath(loc->iseq);
363 case LOCATION_TYPE_CFUNC:
365 return rb_iseq_realpath(loc->iseq);
369 rb_bug(
"location_realpath: unreachable");
381location_absolute_path_m(
VALUE self)
383 return location_realpath(location_ptr(self));
387location_format(
VALUE file,
int lineno,
VALUE name)
410 case LOCATION_TYPE_ISEQ:
411 file = rb_iseq_path(loc->iseq);
412 name = ISEQ_BODY(loc->iseq)->location.label;
414 lineno = calc_lineno(loc->iseq, loc->pc);
416 case LOCATION_TYPE_CFUNC:
417 if (loc->iseq && loc->pc) {
418 file = rb_iseq_path(loc->iseq);
419 lineno = calc_lineno(loc->iseq, loc->pc);
422 file = GET_VM()->progname;
425 name = rb_id2str(loc->mid);
428 rb_bug(
"location_to_str: unreachable");
431 return location_format(file, lineno, name);
438location_to_str_m(
VALUE self)
440 return location_to_str(location_ptr(self));
448location_inspect_m(
VALUE self)
461backtrace_mark(
void *ptr)
464 size_t i, s = bt->backtrace_size;
466 for (i=0; i<s; i++) {
467 location_mark_entry(&bt->backtrace[i]);
469 rb_gc_mark_movable(bt->strary);
470 rb_gc_mark_movable(bt->locary);
474backtrace_free(
void *ptr)
477 if (bt->backtrace) ruby_xfree(bt->backtrace);
485 case LOCATION_TYPE_ISEQ:
488 case LOCATION_TYPE_CFUNC:
499backtrace_update(
void *ptr)
502 size_t i, s = bt->backtrace_size;
504 for (i=0; i<s; i++) {
505 location_update_entry(&bt->backtrace[i]);
507 bt->strary = rb_gc_location(bt->strary);
508 bt->locary = rb_gc_location(bt->locary);
512backtrace_memsize(
const void *ptr)
520 {backtrace_mark, backtrace_free, backtrace_memsize, backtrace_update},
521 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
525rb_backtrace_p(
VALUE obj)
531backtrace_alloc(
VALUE klass)
544 if (start_cfp == NULL) {
549 RUBY_VM_NEXT_CONTROL_FRAME(
550 RUBY_VM_NEXT_CONTROL_FRAME(start_cfp));
552 if (start_cfp < last_cfp) {
556 return start_cfp - last_cfp + 1;
562 static const char prefix[] =
"<internal:";
563 const size_t prefix_len =
sizeof(prefix) - 1;
564 VALUE file = rb_iseq_path(cfp->iseq);
565 return strncmp(prefix, RSTRING_PTR(file), prefix_len) == 0;
571 for (; cfunc_counter > 0; cfunc_counter--, cfunc_loc--) {
572 cfunc_loc->iseq = iseq;
582 for (; num_frames > 0; num_frames--, loc++) {
583 rb_yield(location_create(loc, (
void *)btobj));
588rb_ec_partial_backtrace_object(
const rb_execution_context_t *ec,
long start_frame,
long num_frames,
int* start_too_large,
bool skip_internal,
bool do_yield)
594 VALUE btobj = backtrace_alloc(rb_cBacktrace);
596 unsigned long cfunc_counter = 0;
600 if (end_cfp == NULL) {
604 end_cfp = RUBY_VM_NEXT_CONTROL_FRAME(end_cfp);
616 size = end_cfp - cfp + 1;
620 else if (num_frames < 0 || num_frames > size) {
626 bt->backtrace_size = 0;
627 if (num_frames == 0) {
628 if (start_too_large) *start_too_large = 0;
632 for (; cfp != end_cfp && (bt->backtrace_size < num_frames); cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) {
635 if (start_frame > 0) {
638 else if (!skip_internal || !is_internal_location(cfp)) {
640 const VALUE *pc = cfp->pc;
641 loc = &bt->backtrace[bt->backtrace_size++];
642 loc->type = LOCATION_TYPE_ISEQ;
645 bt_update_cfunc_loc(cfunc_counter, loc-1, iseq, pc);
647 bt_yield_loc(loc - cfunc_counter, cfunc_counter+1, btobj);
654 VM_ASSERT(RUBYVM_CFUNC_FRAME_P(cfp));
655 if (start_frame > 0) {
659 loc = &bt->backtrace[bt->backtrace_size++];
660 loc->type = LOCATION_TYPE_CFUNC;
663 loc->mid = rb_vm_frame_method_entry(cfp)->def->original_id;
669 if (cfunc_counter > 0) {
670 for (; cfp != end_cfp; cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) {
671 if (cfp->iseq && cfp->pc && (!skip_internal || !is_internal_location(cfp))) {
672 bt_update_cfunc_loc(cfunc_counter, loc, cfp->iseq, cfp->pc);
674 bt_yield_loc(loc - cfunc_counter, cfunc_counter, btobj);
681 if (start_too_large) *start_too_large = (start_frame > 0 ? -1 : 0);
685MJIT_FUNC_EXPORTED
VALUE
688 return rb_ec_partial_backtrace_object(ec, BACKTRACE_START, ALL_BACKTRACE_LINES, NULL, FALSE, FALSE);
699 for (i=0; i<bt->backtrace_size; i++) {
701 rb_ary_push(btary, func(loc, arg));
710 return location_to_str(loc);
714backtrace_to_str_ary(
VALUE self)
719 r = backtrace_collect(bt, location_to_str_dmyarg, 0);
725rb_backtrace_to_str_ary(
VALUE self)
731 bt->strary = backtrace_to_str_ary(self);
736MJIT_FUNC_EXPORTED
void
737rb_backtrace_use_iseq_first_lineno_for_last_location(
VALUE self)
743 VM_ASSERT(bt->backtrace_size > 0);
745 loc = &bt->backtrace[0];
747 VM_ASSERT(loc->type == LOCATION_TYPE_ISEQ);
760 vloc->btobj = (
VALUE)btobj;
766backtrace_to_location_ary(
VALUE self)
771 r = backtrace_collect(bt, location_create, (
void *)self);
777rb_backtrace_to_location_ary(
VALUE self)
783 bt->locary = backtrace_to_location_ary(self);
789backtrace_dump_data(
VALUE self)
791 VALUE str = rb_backtrace_to_str_ary(self);
855backtrace_limit(
VALUE self)
857 return LONG2NUM(rb_backtrace_length_limit);
863 return rb_backtrace_to_str_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL, FALSE, FALSE));
869 return rb_backtrace_to_location_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL, skip_internal, FALSE));
876 void (*init)(
void *arg,
size_t size),
887 if (start_cfp == NULL) {
903 RUBY_VM_NEXT_CONTROL_FRAME(
904 RUBY_VM_NEXT_CONTROL_FRAME(start_cfp));
906 if (start_cfp < last_cfp) {
910 size = start_cfp - last_cfp + 1;
916 for (i=0, cfp = start_cfp; i<size; i++, cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
924 VM_ASSERT(RUBYVM_CFUNC_FRAME_P(cfp));
926 ID mid = me->def->original_id;
928 iter_cfunc(arg, cfp, mid);
936 void (*func)(
void *data,
VALUE file,
int lineno,
VALUE name);
941oldbt_init(
void *ptr,
size_t dmy)
944 arg->filename = GET_VM()->progname;
952 const VALUE *pc = cfp->pc;
954 VALUE file = arg->filename = rb_iseq_path(iseq);
955 VALUE name = ISEQ_BODY(iseq)->location.label;
956 int lineno = arg->lineno = calc_lineno(iseq, pc);
958 (arg->func)(arg->data, file, lineno, name);
965 VALUE file = arg->filename;
966 VALUE name = rb_id2str(mid);
967 int lineno = arg->lineno;
969 (arg->func)(arg->data, file, lineno, name);
973oldbt_print(
void *data,
VALUE file,
int lineno,
VALUE name)
978 fprintf(fp,
"\tfrom %s:%d:in unknown method\n",
979 RSTRING_PTR(file), lineno);
982 fprintf(fp,
"\tfrom %s:%d:in `%s'\n",
983 RSTRING_PTR(file), lineno, RSTRING_PTR(name));
988vm_backtrace_print(
FILE *fp)
992 arg.func = oldbt_print;
993 arg.data = (
void *)fp;
994 backtrace_each(GET_EC(),
1002oldbt_bugreport(
void *arg,
VALUE file,
int line,
VALUE method)
1004 const char *filename =
NIL_P(file) ?
"ruby" : RSTRING_PTR(file);
1006 fprintf(stderr,
"-- Ruby level backtrace information "
1007 "----------------------------------------\n");
1010 if (
NIL_P(method)) {
1011 fprintf(stderr,
"%s:%d:in unknown method\n", filename, line);
1014 fprintf(stderr,
"%s:%d:in `%s'\n", filename, line, RSTRING_PTR(method));
1019rb_backtrace_print_as_bugreport(
void)
1024 arg.func = oldbt_bugreport;
1025 arg.data = (
int *)&i;
1027 backtrace_each(GET_EC(),
1037 vm_backtrace_print(stderr);
1046oldbt_print_to(
void *data,
VALUE file,
int lineno,
VALUE name)
1057 (*arg->iter)(arg->output, str);
1067 parg.output = output;
1068 arg.func = oldbt_print_to;
1070 backtrace_each(GET_EC(),
1080 return rb_ec_backtrace_str_ary(GET_EC(), BACKTRACE_START, ALL_BACKTRACE_LINES);
1092 rb_scan_args(argc, argv,
"02", &level, &vn);
1094 if (argc == 2 &&
NIL_P(vn)) argc--;
1098 lev = lev_default + lev_plus;
1099 n = ALL_BACKTRACE_LINES;
1103 long beg, len, bt_size = backtrace_size(ec);
1111 n = ALL_BACKTRACE_LINES;
1116 lev = beg + lev_plus;
1139 return rb_ary_new();
1142 btval = rb_ec_partial_backtrace_object(ec, lev, n, &too_large, FALSE, FALSE);
1149 r = backtrace_to_str_ary(btval);
1152 r = backtrace_to_location_ary(btval);
1159thread_backtrace_to_ary(
int argc,
const VALUE *argv,
VALUE thval,
int to_str)
1163 if (target_th->to_kill || target_th->status == THREAD_KILLED)
1166 return ec_backtrace_to_ary(target_th->ec, argc, argv, 0, 0, to_str);
1170rb_vm_thread_backtrace(
int argc,
const VALUE *argv,
VALUE thval)
1172 return thread_backtrace_to_ary(argc, argv, thval, 1);
1176rb_vm_thread_backtrace_locations(
int argc,
const VALUE *argv,
VALUE thval)
1178 return thread_backtrace_to_ary(argc, argv, thval, 0);
1184 return ec_backtrace_to_ary(ec, argc, argv, 0, 0, 1);
1190 return ec_backtrace_to_ary(ec, argc, argv, 0, 0, 0);
1234 return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 1);
1260rb_f_caller_locations(
int argc,
VALUE *argv,
VALUE _)
1262 return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 0);
1273each_caller_location(
VALUE unused)
1275 rb_ec_partial_backtrace_object(GET_EC(), 2, ALL_BACKTRACE_LINES, NULL, FALSE, TRUE);
1281Init_vm_backtrace(
void)
1346 rb_define_method(rb_cBacktraceLocation,
"base_label", location_base_label_m, 0);
1348 rb_define_method(rb_cBacktraceLocation,
"absolute_path", location_absolute_path_m, 0);
1360RUBY_SYMBOL_EXPORT_BEGIN
1362RUBY_SYMBOL_EXPORT_END
1369 long backtrace_size;
1373 CALLER_BINDING_SELF,
1374 CALLER_BINDING_CLASS,
1375 CALLER_BINDING_BINDING,
1376 CALLER_BINDING_ISEQ,
1378 CALLER_BINDING_DEPTH,
1387collect_caller_bindings_init(
void *arg,
size_t size)
1396 if (rb_vm_control_frame_id_and_class(cfp, 0, 0, &klass)) {
1398 return RBASIC(klass)->klass;
1412 VM_ASSERT(RUBY_VM_END_CONTROL_FRAME(ec) >= cfp);
1413 return (
int)(RUBY_VM_END_CONTROL_FRAME(ec) - cfp);
1422 rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self);
1423 rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
1424 rb_ary_store(frame, CALLER_BINDING_BINDING, GC_GUARDED_PTR(cfp));
1425 rb_ary_store(frame, CALLER_BINDING_ISEQ, cfp->iseq ? (
VALUE)cfp->iseq :
Qnil);
1426 rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp));
1427 rb_ary_store(frame, CALLER_BINDING_DEPTH,
INT2FIX(frame_depth(data->ec, cfp)));
1429 rb_ary_push(data->ary, frame);
1438 rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self);
1439 rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
1440 rb_ary_store(frame, CALLER_BINDING_BINDING,
Qnil);
1441 rb_ary_store(frame, CALLER_BINDING_ISEQ,
Qnil);
1442 rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp));
1443 rb_ary_store(frame, CALLER_BINDING_DEPTH,
INT2FIX(frame_depth(data->ec, cfp)));
1445 rb_ary_push(data->ary, frame);
1458 collect_caller_bindings_init,
1459 collect_caller_bindings_iseq,
1460 collect_caller_bindings_cfunc,
1463 result = rb_ary_reverse(data.ary);
1467 VALUE entry = rb_ary_entry(result, i);
1468 VALUE cfp_val = rb_ary_entry(entry, CALLER_BINDING_BINDING);
1470 if (!
NIL_P(cfp_val)) {
1472 rb_ary_store(entry, CALLER_BINDING_BINDING, rb_vm_make_binding(ec, cfp));
1489 enum ruby_tag_type state;
1490 volatile VALUE MAYBE_UNUSED(result);
1493 rb_vm_stack_to_heap(ec);
1495 dbg_context.ec = ec;
1496 dbg_context.cfp = dbg_context.ec->cfp;
1497 dbg_context.backtrace = rb_ec_backtrace_location_ary(ec, BACKTRACE_START, ALL_BACKTRACE_LINES, FALSE);
1498 dbg_context.backtrace_size =
RARRAY_LEN(dbg_context.backtrace);
1499 dbg_context.contexts = collect_caller_bindings(ec);
1502 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1503 result = (*func)(&dbg_context, data);
1510 EC_JUMP_TAG(ec, state);
1519 if (index < 0 || index >= dc->backtrace_size) {
1522 return rb_ary_entry(dc->contexts, index);
1528 VALUE frame = frame_get(dc, index);
1529 return rb_ary_entry(frame, CALLER_BINDING_SELF);
1535 VALUE frame = frame_get(dc, index);
1536 return rb_ary_entry(frame, CALLER_BINDING_CLASS);
1542 VALUE frame = frame_get(dc, index);
1543 return rb_ary_entry(frame, CALLER_BINDING_BINDING);
1549 VALUE frame = frame_get(dc, index);
1550 VALUE iseq = rb_ary_entry(frame, CALLER_BINDING_ISEQ);
1558 VALUE frame = frame_get(dc, index);
1559 return rb_ary_entry(frame, CALLER_BINDING_DEPTH);
1566 return INT2FIX(frame_depth(ec, ec->cfp));
1572 return dc->backtrace;
1593 end_cfp = RUBY_VM_NEXT_CONTROL_FRAME(end_cfp);
1595 for (i=0; i<limit && cfp != end_cfp;) {
1596 if (VM_FRAME_RUBYFRAME_P(cfp) && cfp->pc != 0) {
1603 cme = rb_vm_frame_method_entry(cfp);
1604 if (cme && cme->def->type == VM_METHOD_TYPE_ISEQ) {
1605 buff[i] = (
VALUE)cme;
1608 buff[i] = (
VALUE)cfp->iseq;
1611 if (lines) lines[i] = calc_lineno(cfp->iseq, cfp->pc);
1616 cme = rb_vm_frame_method_entry(cfp);
1617 if (cme && cme->def->type == VM_METHOD_TYPE_CFUNC) {
1618 buff[i] = (
VALUE)cme;
1619 if (lines) lines[i] = 0;
1623 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
1630frame2iseq(
VALUE frame)
1632 if (
NIL_P(frame))
return NULL;
1634 if (RB_TYPE_P(frame,
T_IMEMO)) {
1635 switch (imemo_type(frame)) {
1641 switch (cme->def->type) {
1642 case VM_METHOD_TYPE_ISEQ:
1643 return cme->def->body.iseq.
iseqptr;
1652 rb_bug(
"frame2iseq: unreachable");
1658 const rb_iseq_t *iseq = frame2iseq(frame);
1659 return iseq ? rb_iseq_path(iseq) :
Qnil;
1665 if (
NIL_P(frame))
return NULL;
1667 if (RB_TYPE_P(frame,
T_IMEMO)) {
1668 switch (imemo_type(frame)) {
1672 switch (cme->def->type) {
1673 case VM_METHOD_TYPE_CFUNC:
1690 if (cframe(frame)) {
1694 rb_gc_register_mark_object(cfunc_str);
1698 const rb_iseq_t *iseq = frame2iseq(frame);
1699 return iseq ? rb_iseq_realpath(iseq) :
Qnil;
1705 const rb_iseq_t *iseq = frame2iseq(frame);
1706 return iseq ? rb_iseq_label(iseq) :
Qnil;
1712 const rb_iseq_t *iseq = frame2iseq(frame);
1713 return iseq ? rb_iseq_base_label(iseq) :
Qnil;
1719 const rb_iseq_t *iseq = frame2iseq(frame);
1720 return iseq ? rb_iseq_first_lineno(iseq) :
Qnil;
1724frame2klass(
VALUE frame)
1728 if (RB_TYPE_P(frame,
T_IMEMO)) {
1731 if (imemo_type(frame) == imemo_ment) {
1732 return cme->defined_class;
1741 VALUE klass = frame2klass(frame);
1743 if (klass && !
NIL_P(klass)) {
1745 klass =
RBASIC(klass)->klass;
1762 VALUE klass = frame2klass(frame);
1772 ID mid = cme->def->original_id;
1775 const rb_iseq_t *iseq = frame2iseq(frame);
1776 return iseq ? rb_iseq_method_name(iseq) :
Qnil;
1780qualified_method_name(
VALUE frame,
VALUE method_name)
1782 if (method_name !=
Qnil) {
1786 if (classpath !=
Qnil) {
1787 return rb_sprintf(
"%"PRIsVALUE
"%s%"PRIsVALUE,
1788 classpath, singleton_p ==
Qtrue ?
"." :
"#", method_name);
1804 return qualified_method_name(frame, method_name);
1812 ID mid = cme->def->original_id;
1813 VALUE method_name = id2str(mid);
1814 return qualified_method_name(frame, method_name);
1821 if (
NIL_P(qualified_method_name) || base_label == qualified_method_name) {
1825 long label_length = RSTRING_LEN(label);
1826 long base_label_length = RSTRING_LEN(base_label);
1827 int prefix_len =
rb_long2int(label_length - base_label_length);
1829 return rb_sprintf(
"%.*s%"PRIsVALUE, prefix_len, RSTRING_PTR(label), qualified_method_name);
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #mid.
int rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
Queries mysterious "frame"s of the given range.
VALUE rb_profile_frame_full_label(VALUE frame)
Identical to rb_profile_frame_label(), except it returns a qualified result.
VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index)
Queries the instruction sequence of the passed context's upper frame.
VALUE rb_debug_inspector_current_depth(void)
Return current frmae depth.
VALUE rb_profile_frame_method_name(VALUE frame)
Queries the name of the method of the passed frame.
VALUE rb_debug_inspector_frame_depth(const rb_debug_inspector_t *dc, long index)
Queries the depth of the passed context's upper frame.
VALUE rb_profile_frame_qualified_method_name(VALUE frame)
Identical to rb_profile_frame_method_name(), except it "qualifies" the return value with its defining...
VALUE rb_profile_frame_label(VALUE frame)
Queries human-readable "label" string.
VALUE rb_profile_frame_singleton_method_p(VALUE frame)
Queries if the method of the passed frame is a singleton class.
VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc)
Queries the backtrace object of the context.
VALUE rb_profile_frame_absolute_path(VALUE frame)
Identical to rb_profile_frame_path(), except it tries to expand the returning path.
VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data)
Prepares, executes, then cleans up a debug session.
VALUE rb_debug_inspector_frame_self_get(const rb_debug_inspector_t *dc, long index)
Queries the current receiver of the passed context's upper frame.
VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long index)
Queries the binding of the passed context's upper frame.
VALUE rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, long index)
Queries the current class of the passed context's upper frame.
VALUE rb_profile_frame_classpath(VALUE frame)
Queries the class path of the method that the passed frame represents.
VALUE rb_profile_frame_path(VALUE frame)
Queries the path of the passed backtrace.
VALUE rb_profile_frame_first_lineno(VALUE frame)
Queries the first line of the method of the passed frame pointer.
VALUE(* rb_debug_inspector_func_t)(const rb_debug_inspector_t *dc, void *data)
Type of the callback function passed to rb_debug_inspector_open().
VALUE rb_profile_frame_base_label(VALUE frame)
Identical to rb_profile_frame_label(), except it does not "qualify" the result.
VALUE rb_enc_sprintf(rb_encoding *enc, const char *fmt,...)
Identical to rb_sprintf(), except it additionally takes an encoding.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
void rb_undef_method(VALUE klass, const char *name)
Defines an undef of a method.
#define FL_SINGLETON
Old name of RUBY_FL_SINGLETON.
#define INT2FIX
Old name of RB_INT2FIX.
#define rb_str_cat2
Old name of rb_str_cat_cstr.
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
#define T_IMEMO
Old name of RUBY_T_IMEMO.
#define CLASS_OF
Old name of rb_class_of.
#define T_MODULE
Old name of RUBY_T_MODULE.
#define ZALLOC_N
Old name of RB_ZALLOC_N.
#define ASSUME
Old name of RBIMPL_ASSUME.
#define T_ICLASS
Old name of RUBY_T_ICLASS.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define Qtrue
Old name of RUBY_Qtrue.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define NIL_P
Old name of RB_NIL_P.
#define T_CLASS
Old name of RUBY_T_CLASS.
#define FL_TEST
Old name of RB_FL_TEST.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define rb_ary_new2
Old name of rb_ary_new_capa.
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Checks if the given object is of given kind.
void rb_bug(const char *fmt,...)
Interpreter panic switch.
VALUE rb_eArgError
ArgumentError exception.
VALUE rb_cArray
Array class.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_cThread
Thread class.
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Deconstructs a numerical range.
#define rb_str_new_literal(str)
Just another name of rb_str_new_lit.
VALUE rb_str_inspect(VALUE str)
Generates a "readable" version of the receiver.
#define rb_str_cat_cstr(buf, str)
Identical to rb_str_cat(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
VALUE rb_class_path(VALUE mod)
Identical to rb_mod_name(), except it returns #<Class: ...> style inspection for anonymous modules.
void rb_undef_alloc_func(VALUE klass)
Deletes the allocator function of a class.
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
VALUE rb_make_backtrace(void)
Creates the good old fashioned array-of-strings style backtrace info.
void rb_backtrace(void)
Prints the backtrace out to the standard error.
VALUE rb_sprintf(const char *fmt,...)
Ruby's extended sprintf(3).
VALUE rb_str_catf(VALUE dst, const char *fmt,...)
Identical to rb_sprintf(), except it renders the output to the specified object rather than creating ...
VALUE rb_yield(VALUE val)
Yields the block.
#define rb_long2int
Just another name of rb_long2int_inline.
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Marshal format compatibility layer.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define RARRAY_LEN
Just another name of rb_array_len.
#define RBASIC(obj)
Convenient casting macro.
#define RUBY_TYPED_DEFAULT_FREE
This is a value you can set to rb_data_type_struct::dfree.
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
const char * rb_class2name(VALUE klass)
Queries the name of the passed class.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
const rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
uintptr_t VALUE
Type that represents a Ruby object.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.