12#include "eval_intern.h"
14#include "internal/class.h"
15#include "internal/error.h"
16#include "internal/object.h"
17#include "internal/vm.h"
24static VALUE rb_cBacktrace;
25static VALUE rb_cBacktraceLocation;
30 VALUE str = rb_id2str(
id);
31 if (!str)
return Qnil;
34#define rb_id2str(id) id2str(id)
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 = ISEQ_BODY(iseq)->location.node_id;
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;
60#if SIZEOF_PTRDIFF_T > SIZEOF_INT
61 VM_ASSERT(n <= (ptrdiff_t)UINT_MAX);
63 VM_ASSERT((
unsigned int)n <= ISEQ_BODY(iseq)->iseq_size);
70#if VMDEBUG && defined(HAVE_BUILTIN___BUILTIN_TRAP)
73 rb_print_backtrace(stderr);
77 if (lineno) *lineno = rb_iseq_line_no(iseq, pos);
78#ifdef USE_ISEQ_NODE_ID
79 if (node_id) *node_id = rb_iseq_node_id(iseq, pos);
89 if (calc_pos(iseq, pc, &lineno, NULL))
return lineno;
93#ifdef USE_ISEQ_NODE_ID
98 if (calc_pos(iseq, pc, NULL, &node_id))
return node_id;
106 if (VM_FRAME_RUBYFRAME_P(cfp) && CFP_ISEQ(cfp)) {
108 int line = calc_lineno(iseq, CFP_PC(cfp));
113 return ISEQ_BODY(iseq)->location.first_lineno;
133location_mark(
void *ptr)
136 rb_gc_mark_movable(vfi->btobj);
140location_ref_update(
void *ptr)
143 vfi->btobj = rb_gc_location(vfi->btobj);
149 rb_gc_mark((
VALUE)fi->cme);
150 if (fi->iseq) rb_gc_mark_movable((
VALUE)fi->iseq);
165rb_frame_info_p(
VALUE obj)
167 return rb_typeddata_is_kind_of(obj, &location_data_type);
171location_ptr(
VALUE locobj)
182 return calc_lineno(loc->iseq, loc->pc);
196location_lineno_m(
VALUE self)
198 return INT2FIX(location_lineno(location_ptr(self)));
201VALUE rb_mod_name0(
VALUE klass,
bool *permanent);
208 if (RCLASS_SINGLETON_P(owner)) {
209 VALUE v = RCLASS_ATTACHED_OBJECT(owner);
211 v = rb_mod_name0(v, &permanent);
212 if (permanent && !
NIL_P(v)) {
213 return rb_sprintf(
"%"PRIsVALUE
".%"PRIsVALUE, v, name);
218 owner = rb_mod_name0(owner, &permanent);
219 if (permanent && !
NIL_P(owner)) {
220 return rb_sprintf(
"%"PRIsVALUE
"#%"PRIsVALUE, owner, name);
231 switch (ISEQ_BODY(iseq)->
type) {
233 case ISEQ_TYPE_CLASS:
235 return ISEQ_BODY(iseq)->location.label;
236 case ISEQ_TYPE_METHOD:
237 return rb_gen_method_name(owner, ISEQ_BODY(iseq)->location.label);
238 case ISEQ_TYPE_BLOCK:
239 case ISEQ_TYPE_PLAIN: {
242 if (ISEQ_BODY(orig_iseq)->parent_iseq != 0) {
243 while (ISEQ_BODY(orig_iseq)->local_iseq != iseq) {
244 if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_BLOCK) {
247 iseq = ISEQ_BODY(iseq)->parent_iseq;
251 return rb_sprintf(
"block in %"PRIsVALUE, calculate_iseq_label(owner, iseq));
254 return rb_sprintf(
"block (%d levels) in %"PRIsVALUE, level, calculate_iseq_label(owner, iseq));
257 case ISEQ_TYPE_RESCUE:
258 case ISEQ_TYPE_ENSURE:
260 iseq = ISEQ_BODY(iseq)->parent_iseq;
263 rb_bug(
"calculate_iseq_label: unreachable");
268is_internal_location(
const rb_iseq_t *iseq)
270 static const char prefix[] =
"<internal:";
271 const size_t prefix_len =
sizeof(prefix) - 1;
272 VALUE file = rb_iseq_path(iseq);
273 return strncmp(prefix, RSTRING_PTR(file), prefix_len) == 0;
280 if (!loc->cme)
return false;
282 switch (loc->cme->def->type) {
283 case VM_METHOD_TYPE_CFUNC:
285 case VM_METHOD_TYPE_ISEQ:
286 return is_internal_location(loc->cme->def->body.iseq.
iseqptr);
295 if (location_cfunc_p(loc)) {
296 return rb_gen_method_name(loc->cme->owner, rb_id2str(loc->cme->def->original_id));
301 owner = loc->cme->owner;
303 return calculate_iseq_label(owner, loc->iseq);
333location_label_m(
VALUE self)
335 return location_label(location_ptr(self));
341 if (location_cfunc_p(loc)) {
342 return rb_id2str(loc->cme->def->original_id);
345 return ISEQ_BODY(loc->iseq)->location.base_label;
373location_base_label_m(
VALUE self)
375 return location_base_label(location_ptr(self));
395location_path_m(
VALUE self)
397 const rb_iseq_t *iseq = location_iseq(location_ptr(self));
398 return iseq ? rb_iseq_path(iseq) :
Qnil;
401#ifdef USE_ISEQ_NODE_ID
406 return calc_node_id(loc->iseq, loc->pc);
413rb_get_node_id_from_frame_info(
VALUE obj)
415#ifdef USE_ISEQ_NODE_ID
417 return location_node_id(loc);
424rb_get_iseq_from_frame_info(
VALUE obj)
427 const rb_iseq_t *iseq = location_iseq(loc);
435 return rb_iseq_realpath(loc->iseq);
447location_absolute_path_m(
VALUE self)
449 return location_realpath(location_ptr(self));
453location_format(
VALUE file,
int lineno,
VALUE name)
457 rb_str_catf(s,
":%d", lineno);
464 rb_str_catf(s,
"'%s'", RSTRING_PTR(name));
476 if (location_cfunc_p(loc)) {
477 if (loc->iseq && loc->pc) {
478 file = rb_iseq_path(loc->iseq);
479 lineno = calc_lineno(loc->iseq, loc->pc);
482 file = GET_VM()->progname;
485 name = rb_gen_method_name(loc->cme->owner, rb_id2str(loc->cme->def->original_id));
488 file = rb_iseq_path(loc->iseq);
489 lineno = calc_lineno(loc->iseq, loc->pc);
491 owner = loc->cme->owner;
493 name = calculate_iseq_label(owner, loc->iseq);
496 return location_format(file, lineno, name);
503location_to_str_m(
VALUE self)
505 return location_to_str(location_ptr(self));
513location_inspect_m(
VALUE self)
526backtrace_mark(
void *ptr)
529 size_t i, s = bt->backtrace_size;
531 for (i=0; i<s; i++) {
532 location_mark_entry(&bt->backtrace[i]);
534 rb_gc_mark_movable(bt->strary);
535 rb_gc_mark_movable(bt->locary);
548backtrace_update(
void *ptr)
551 size_t i, s = bt->backtrace_size;
553 for (i=0; i<s; i++) {
554 location_update_entry(&bt->backtrace[i]);
556 bt->strary = rb_gc_location(bt->strary);
557 bt->locary = rb_gc_location(bt->locary);
575rb_backtrace_p(
VALUE obj)
577 return rb_typeddata_is_kind_of(obj, &backtrace_data_type);
584 VALUE btobj = rb_data_typed_object_zalloc(rb_cBacktrace, memsize, &backtrace_data_type);
596 if (start_cfp == NULL) {
601 RUBY_VM_NEXT_CONTROL_FRAME(
602 RUBY_VM_NEXT_CONTROL_FRAME(start_cfp));
604 if (start_cfp < last_cfp) {
608 return start_cfp - last_cfp + 1;
614 enum rb_iseq_type
type = ISEQ_BODY(CFP_ISEQ(cfp))->type;
615 return type == ISEQ_TYPE_RESCUE ||
type == ISEQ_TYPE_ENSURE;
621 for (; backpatch_counter > 0; backpatch_counter--, loc--) {
632 for (; num_frames > 0; num_frames--, loc++) {
633 rb_yield(location_create(loc, (
void *)btobj));
638rb_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)
646 unsigned long backpatch_counter = 0;
647 bool skip_next_frame = FALSE;
650 if (end_cfp == NULL) {
654 end_cfp = RUBY_VM_NEXT_CONTROL_FRAME(end_cfp);
666 size = end_cfp - cfp + 1;
670 else if (num_frames < 0 || num_frames > size) {
675 btobj = backtrace_alloc_capa(num_frames, &bt);
677 bt->backtrace_size = 0;
678 if (num_frames == 0) {
679 if (start_too_large) *start_too_large = 0;
683 for (; cfp != end_cfp && (bt->backtrace_size < num_frames); cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) {
686 if (start_frame > 0) {
690 bool internal = is_internal_location(CFP_ISEQ(cfp));
691 if (skip_internal && internal)
continue;
692 if (!skip_next_frame) {
694 const VALUE *pc = CFP_PC(cfp);
695 if (internal && backpatch_counter > 0) {
697 bt->backtrace_size -= backpatch_counter;
698 backpatch_counter = 0;
700 loc = &bt->backtrace[bt->backtrace_size++];
701 RB_OBJ_WRITE(btobj, &loc->cme, rb_vm_frame_method_entry(cfp));
713 if ((VM_FRAME_TYPE(cfp) & VM_FRAME_MAGIC_MASK) == VM_FRAME_MAGIC_DUMMY) {
719 bt_backpatch_loc(backpatch_counter, loc-1, iseq, pc);
721 bt_yield_loc(loc - backpatch_counter, backpatch_counter+1, btobj);
723 backpatch_counter = 0;
726 skip_next_frame = is_rescue_or_ensure_frame(cfp);
731 VM_ASSERT(RUBYVM_CFUNC_FRAME_P(cfp));
732 if (start_frame > 0) {
736 loc = &bt->backtrace[bt->backtrace_size++];
737 RB_OBJ_WRITE(btobj, &loc->cme, rb_vm_frame_method_entry(cfp));
747 if (backpatch_counter > 0) {
748 for (; cfp != end_cfp; cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) {
749 if (CFP_ISEQ(cfp) && CFP_PC(cfp) && !(skip_internal && is_internal_location(CFP_ISEQ(cfp)))) {
750 VM_ASSERT(!skip_next_frame);
751 bt_backpatch_loc(backpatch_counter, loc, CFP_ISEQ(cfp), CFP_PC(cfp));
754 bt_yield_loc(loc - backpatch_counter, backpatch_counter, btobj);
761 if (start_too_large) *start_too_large = (start_frame > 0 ? -1 : 0);
768 return rb_ec_partial_backtrace_object(ec, RUBY_BACKTRACE_START, RUBY_ALL_BACKTRACE_LINES, NULL, FALSE, FALSE);
779 for (i=0; i<bt->backtrace_size; i++) {
790 return location_to_str(loc);
794backtrace_to_str_ary(
VALUE self)
799 r = backtrace_collect(bt, location_to_str_dmyarg, 0);
805rb_backtrace_to_str_ary(
VALUE self)
811 RB_OBJ_WRITE(self, &bt->strary, backtrace_to_str_ary(self));
830backtrace_to_location_ary(
VALUE self)
835 r = backtrace_collect(bt, location_create, (
void *)self);
841rb_backtrace_to_location_ary(
VALUE self)
847 RB_OBJ_WRITE(self, &bt->locary, backtrace_to_location_ary(self));
853rb_location_ary_to_backtrace(
VALUE ary)
861 VALUE btobj = backtrace_alloc_capa(num_frames, &new_backtrace);
863 for (
long index = 0; index <
RARRAY_LEN(ary); index++) {
866 if (!rb_frame_info_p(locobj)) {
874 RB_OBJ_WRITE(btobj, &dst_location->cme, src_vloc->loc->cme);
875 RB_OBJ_WRITE(btobj, &dst_location->iseq, src_vloc->loc->iseq);
876 dst_location->pc = src_vloc->loc->pc;
878 new_backtrace->backtrace_size++;
887backtrace_dump_data(
VALUE self)
889 VALUE str = rb_backtrace_to_str_ary(self);
953backtrace_limit(
VALUE self)
955 return LONG2NUM(rb_backtrace_length_limit);
960backtrace_clone(
VALUE self)
966 VALUE clone = backtrace_alloc_capa(bt->backtrace_size, &other_bt);
968 rb_obj_clone_setup(self, clone,
Qfalse);
975backtrace_dup(
VALUE self)
984backtrace_initialize_copy(
VALUE self,
VALUE original)
992 bt->backtrace_size = original_bt->backtrace_size;
1001 return rb_backtrace_to_str_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL, FALSE, FALSE));
1007 return rb_backtrace_to_location_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL, skip_internal, FALSE));
1014 void (*init)(
void *arg,
size_t size),
1025 if (start_cfp == NULL) {
1041 RUBY_VM_NEXT_CONTROL_FRAME(
1042 RUBY_VM_NEXT_CONTROL_FRAME(start_cfp));
1044 if (start_cfp < last_cfp) {
1048 size = start_cfp - last_cfp + 1;
1054 for (i=0, cfp = start_cfp; i<size; i++, cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
1056 if (CFP_ISEQ(cfp)) {
1058 iter_iseq(arg, cfp);
1062 VM_ASSERT(RUBYVM_CFUNC_FRAME_P(cfp));
1064 ID mid = me->def->original_id;
1066 iter_cfunc(arg, cfp, mid);
1074 void (*func)(
void *data,
VALUE file,
int lineno,
VALUE name);
1079oldbt_init(
void *ptr,
size_t dmy)
1082 arg->filename = GET_VM()->progname;
1090 const VALUE *pc = CFP_PC(cfp);
1092 VALUE file = arg->filename = rb_iseq_path(iseq);
1093 VALUE name = ISEQ_BODY(iseq)->location.label;
1094 int lineno = arg->lineno = calc_lineno(iseq, pc);
1096 (arg->func)(arg->data, file, lineno, name);
1103 VALUE file = arg->filename;
1104 VALUE name = rb_id2str(mid);
1105 int lineno = arg->lineno;
1107 (arg->func)(arg->data, file, lineno, name);
1111oldbt_print(
void *data,
VALUE file,
int lineno,
VALUE name)
1116 fprintf(fp,
"\tfrom %s:%d:in unknown method\n",
1117 RSTRING_PTR(file), lineno);
1120 fprintf(fp,
"\tfrom %s:%d:in '%s'\n",
1121 RSTRING_PTR(file), lineno, RSTRING_PTR(name));
1126vm_backtrace_print(
FILE *fp)
1130 arg.func = oldbt_print;
1131 arg.data = (
void *)fp;
1132 backtrace_each(GET_EC(),
1145oldbt_bugreport(
void *arg,
VALUE file,
int line,
VALUE method)
1149 const char *filename =
NIL_P(file) ?
"ruby" : RSTRING_PTR(file);
1151 fprintf(fp,
"-- Ruby level backtrace information "
1152 "----------------------------------------\n");
1155 if (
NIL_P(method)) {
1156 fprintf(fp,
"%s:%d:in unknown method\n", filename, line);
1159 fprintf(fp,
"%s:%d:in '%s'\n", filename, line, RSTRING_PTR(method));
1164rb_backtrace_print_as_bugreport(
FILE *fp)
1169 arg.func = oldbt_bugreport;
1172 backtrace_each(GET_EC(),
1182 vm_backtrace_print(stderr);
1191oldbt_print_to(
void *data,
VALUE file,
int lineno,
VALUE name)
1194 VALUE str = rb_sprintf(
"\tfrom %"PRIsVALUE
":%d:in ", file, lineno);
1200 rb_str_catf(str,
" '%"PRIsVALUE
"'\n", name);
1202 (*arg->iter)(arg->output, str);
1212 parg.output = output;
1213 arg.func = oldbt_print_to;
1215 backtrace_each(GET_EC(),
1223rb_make_backtrace(
void)
1225 return rb_ec_backtrace_str_ary(GET_EC(), RUBY_BACKTRACE_START, RUBY_ALL_BACKTRACE_LINES);
1231 VALUE level, vn, opts;
1239 if (argc == 2 &&
NIL_P(vn)) argc--;
1243 lev = lev_default + lev_plus;
1244 n = RUBY_ALL_BACKTRACE_LINES;
1248 long beg,
len, bt_size = backtrace_size(ec);
1253 rb_raise(rb_eArgError,
"negative level (%ld)", lev);
1256 n = RUBY_ALL_BACKTRACE_LINES;
1261 lev = beg + lev_plus;
1271 rb_raise(rb_eArgError,
"negative level (%ld)", lev);
1274 rb_raise(rb_eArgError,
"negative size (%ld)", n);
1294 lev = ec_backtrace_range(ec, argc, argv, lev_default, lev_plus, &n);
1295 if (lev < 0)
return Qnil;
1301 btval = rb_ec_partial_backtrace_object(ec, lev, n, &too_large, FALSE, FALSE);
1308 r = backtrace_to_str_ary(btval);
1311 r = backtrace_to_location_ary(btval);
1318thread_backtrace_to_ary(
int argc,
const VALUE *argv,
VALUE thval,
int to_str)
1322 if (target_th->to_kill || target_th->status == THREAD_KILLED)
1325 return ec_backtrace_to_ary(target_th->ec, argc, argv, 0, 0, to_str);
1329rb_vm_thread_backtrace(
int argc,
const VALUE *argv,
VALUE thval)
1331 return thread_backtrace_to_ary(argc, argv, thval, 1);
1335rb_vm_thread_backtrace_locations(
int argc,
const VALUE *argv,
VALUE thval)
1337 return thread_backtrace_to_ary(argc, argv, thval, 0);
1343 return ec_backtrace_to_ary(ec, argc, argv, 0, 0, 1);
1349 return ec_backtrace_to_ary(ec, argc, argv, 0, 0, 0);
1393 return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 1);
1419rb_f_caller_locations(
int argc,
VALUE *argv,
VALUE _)
1421 return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 0);
1432each_caller_location(
int argc,
VALUE *argv,
VALUE _)
1435 long n, lev = ec_backtrace_range(ec, argc, argv, 1, 1, &n);
1436 if (lev >= 0 && n != 0) {
1437 rb_ec_partial_backtrace_object(ec, lev, n, NULL, FALSE, TRUE);
1443backtrace_no_allocator(
VALUE klass)
1452Init_vm_backtrace(
void)
1470 rb_define_method(rb_cBacktrace,
"initialize_copy", backtrace_initialize_copy, 1);
1524 rb_define_method(rb_cBacktraceLocation,
"base_label", location_base_label_m, 0);
1526 rb_define_method(rb_cBacktraceLocation,
"absolute_path", location_absolute_path_m, 0);
1538RUBY_SYMBOL_EXPORT_BEGIN
1540RUBY_SYMBOL_EXPORT_END
1546 VALUE raw_backtrace;
1550 CALLER_BINDING_SELF,
1551 CALLER_BINDING_CLASS,
1552 CALLER_BINDING_BINDING,
1553 CALLER_BINDING_ISEQ,
1556 CALLER_BINDING_DEPTH,
1567collect_caller_bindings_init(
void *arg,
size_t num_frames)
1570 data->btobj = backtrace_alloc_capa(num_frames, &data->bt);
1577 if (rb_vm_control_frame_id_and_class(cfp, 0, 0, &klass)) {
1579 return RBASIC(klass)->klass;
1593 VM_ASSERT(RUBY_VM_END_CONTROL_FRAME(ec) >= cfp);
1594 return (
int)(RUBY_VM_END_CONTROL_FRAME(ec) - cfp);
1605 rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
1606 rb_ary_store(frame, CALLER_BINDING_BINDING, GC_GUARDED_PTR(cfp));
1608 rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp));
1611 RB_OBJ_WRITE(data->btobj, &loc->cme, rb_vm_frame_method_entry(cfp));
1613 loc->pc = CFP_PC(cfp);
1614 VALUE vloc = location_create(loc, (
void *)data->btobj);
1629 rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
1632 rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp));
1635 RB_OBJ_WRITE(data->btobj, &loc->cme, rb_vm_frame_method_entry(cfp));
1638 VALUE vloc = location_create(loc, (
void *)data->btobj);
1656 collect_caller_bindings_init,
1657 collect_caller_bindings_iseq,
1658 collect_caller_bindings_cfunc,
1668 if (!
NIL_P(cfp_val)) {
1670 rb_ary_store(entry, CALLER_BINDING_BINDING, rb_vm_make_binding(ec, cfp));
1687 enum ruby_tag_type state;
1688 volatile VALUE MAYBE_UNUSED(result);
1692 rb_vm_stack_to_heap(ec);
1694 dbg_context.ec = ec;
1695 dbg_context.cfp = dbg_context.ec->cfp;
1696 dbg_context.contexts = collect_caller_bindings(ec);
1698 for (i=0; i<
RARRAY_LEN(dbg_context.contexts); i++) {
1704 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1705 result = (*func)(&dbg_context, data);
1712 EC_JUMP_TAG(ec, state);
1721 if (index < 0 || index >=
RARRAY_LEN(dc->contexts)) {
1722 rb_raise(rb_eArgError,
"no such frame");
1730 VALUE frame = frame_get(dc, index);
1737 VALUE frame = frame_get(dc, index);
1744 VALUE frame = frame_get(dc, index);
1751 VALUE frame = frame_get(dc, index);
1760 VALUE frame = frame_get(dc, index);
1768 return INT2FIX(frame_depth(ec, ec->cfp));
1774 return dc->raw_backtrace;
1795 end_cfp = RUBY_VM_NEXT_CONTROL_FRAME(end_cfp);
1797 for (i=0; i<limit && cfp != end_cfp; cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) {
1798 if (VM_FRAME_RUBYFRAME_P_UNCHECKED(cfp) && CFP_PC(cfp)) {
1805 cme = rb_vm_frame_method_entry_unchecked(cfp);
1807 if (cme && cme->def->type == VM_METHOD_TYPE_ISEQ) {
1808 buff[i] = (
VALUE)cme;
1811 buff[i] = (
VALUE)iseq;
1815 const VALUE *pc = CFP_PC(cfp);
1816 VALUE *iseq_encoded = ISEQ_BODY(iseq)->iseq_encoded;
1817 VALUE *pc_end = iseq_encoded + ISEQ_BODY(iseq)->iseq_size;
1828 if (cfp == top && (pc < iseq_encoded || pc > pc_end)) {
1832 lines[i] = calc_lineno(iseq, pc);
1839 cme = rb_vm_frame_method_entry_unchecked(cfp);
1840 if (cme && cme->def->type == VM_METHOD_TYPE_CFUNC) {
1845 buff[i] = (
VALUE)cme;
1846 if (lines) lines[i] = 0;
1866 return thread_profile_frames(ec, start, limit, buff, lines);
1873 return thread_profile_frames(th->ec, start, limit, buff, lines);
1877frame2iseq(
VALUE frame)
1879 if (
NIL_P(frame))
return NULL;
1882 switch (imemo_type(frame)) {
1888 switch (cme->def->type) {
1889 case VM_METHOD_TYPE_ISEQ:
1890 return cme->def->body.iseq.
iseqptr;
1899 rb_bug(
"frame2iseq: unreachable");
1905 const rb_iseq_t *iseq = frame2iseq(frame);
1906 return iseq ? rb_iseq_path(iseq) :
Qnil;
1912 if (
NIL_P(frame))
return NULL;
1915 switch (imemo_type(frame)) {
1919 switch (cme->def->type) {
1920 case VM_METHOD_TYPE_CFUNC:
1937 if (cframe(frame)) {
1941 rb_vm_register_global_object(cfunc_str);
1945 const rb_iseq_t *iseq = frame2iseq(frame);
1946 return iseq ? rb_iseq_realpath(iseq) :
Qnil;
1952 const rb_iseq_t *iseq = frame2iseq(frame);
1953 return iseq ? rb_iseq_label(iseq) :
Qnil;
1959 const rb_iseq_t *iseq = frame2iseq(frame);
1960 return iseq ? rb_iseq_base_label(iseq) :
Qnil;
1966 const rb_iseq_t *iseq = frame2iseq(frame);
1967 return iseq ? rb_iseq_first_lineno(iseq) :
Qnil;
1971frame2klass(
VALUE frame)
1978 if (imemo_type(frame) == imemo_ment) {
1979 return cme->defined_class;
1988 VALUE klass = frame2klass(frame);
1990 if (klass && !
NIL_P(klass)) {
1992 klass =
RBASIC(klass)->klass;
1994 else if (RCLASS_SINGLETON_P(klass)) {
1995 klass = RCLASS_ATTACHED_OBJECT(klass);
2009 VALUE klass = frame2klass(frame);
2011 return RBOOL(klass && !
NIL_P(klass) && RCLASS_SINGLETON_P(klass));
2019 ID mid = cme->def->original_id;
2022 const rb_iseq_t *iseq = frame2iseq(frame);
2023 return iseq ? rb_iseq_method_name(iseq) :
Qnil;
2027qualified_method_name(
VALUE frame,
VALUE method_name)
2029 if (method_name !=
Qnil) {
2033 if (classpath !=
Qnil) {
2034 return rb_sprintf(
"%"PRIsVALUE
"%s%"PRIsVALUE,
2035 classpath, singleton_p ==
Qtrue ?
"." :
"#", method_name);
2051 return qualified_method_name(frame, method_name);
2059 ID mid = cme->def->original_id;
2060 VALUE method_name = id2str(mid);
2061 return qualified_method_name(frame, method_name);
2068 if (
NIL_P(qualified_method_name) || base_label == qualified_method_name) {
2072 long label_length = RSTRING_LEN(label);
2073 long base_label_length = RSTRING_LEN(base_label);
2074 int prefix_len =
rb_long2int(label_length - base_label_length);
2076 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 frame 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.
int rb_profile_thread_frames(VALUE thread, int start, int limit, VALUE *buff, int *lines)
Queries mysterious "frame"s of the given range.
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.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define rb_str_cat2
Old name of rb_str_cat_cstr.
#define T_IMEMO
Old name of RUBY_T_IMEMO.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define CLASS_OF
Old name of rb_class_of.
#define T_MODULE
Old name of RUBY_T_MODULE.
#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 T_ARRAY
Old name of RUBY_T_ARRAY.
#define NIL_P
Old name of RB_NIL_P.
#define T_CLASS
Old name of RUBY_T_CLASS.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define rb_ary_new2
Old name of rb_ary_new_capa.
void rb_notimplement(void)
VALUE rb_cArray
Array class.
VALUE rb_cObject
Object class.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_cThread
Thread class.
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
VALUE rb_ary_reverse(VALUE ary)
Destructively reverses the passed array in-place.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
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_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.
void rb_backtrace(void)
Prints the backtrace out to the standard error.
int len
Length of the buffer.
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 MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#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 RARRAY_AREF(a, i)
#define RBASIC(obj)
Convenient casting macro.
#define RUBY_DEFAULT_FREE
This is a value you can set to RData::dfree.
#define RUBY_TYPED_DEFAULT_FREE
This is a value you can set to rb_data_type_struct::dfree.
#define RUBY_TYPED_FREE_IMMEDIATELY
Macros to see if each corresponding flag is defined.
#define TypedData_Get_Struct(obj, type, data_type, sval)
Obtains a C struct from inside of a wrapper Ruby object.
#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.
This is the struct that holds necessary info for a struct.
const rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.