12#include "eval_intern.h" 
   14#include "internal/class.h" 
   15#include "internal/error.h" 
   16#include "internal/vm.h" 
   22static VALUE rb_cBacktrace;
 
   23static VALUE rb_cBacktraceLocation;
 
   28    VALUE str = rb_id2str(
id);
 
   29    if (!str) 
return Qnil;
 
   32#define rb_id2str(id) id2str(id) 
   35calc_pos(
const rb_iseq_t *iseq, 
const VALUE *pc, 
int *lineno, 
int *node_id)
 
   40        if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_TOP) {
 
   41            VM_ASSERT(! ISEQ_BODY(iseq)->local_table);
 
   42            VM_ASSERT(! ISEQ_BODY(iseq)->local_table_size);
 
   45        if (lineno) *lineno = ISEQ_BODY(iseq)->location.first_lineno;
 
   46#ifdef USE_ISEQ_NODE_ID 
   47        if (node_id) *node_id = ISEQ_BODY(iseq)->location.node_id;
 
   52        VM_ASSERT(ISEQ_BODY(iseq));
 
   53        VM_ASSERT(ISEQ_BODY(iseq)->iseq_encoded);
 
   54        VM_ASSERT(ISEQ_BODY(iseq)->iseq_size);
 
   56        ptrdiff_t n = pc - ISEQ_BODY(iseq)->iseq_encoded;
 
   58#if SIZEOF_PTRDIFF_T > SIZEOF_INT 
   59        VM_ASSERT(n <= (ptrdiff_t)UINT_MAX);
 
   61        VM_ASSERT((
unsigned int)n <= ISEQ_BODY(iseq)->iseq_size);
 
   68#if VMDEBUG && defined(HAVE_BUILTIN___BUILTIN_TRAP) 
   71            rb_print_backtrace(stderr);
 
   75        if (lineno) *lineno = rb_iseq_line_no(iseq, pos);
 
   76#ifdef USE_ISEQ_NODE_ID 
   77        if (node_id) *node_id = rb_iseq_node_id(iseq, pos);
 
   87    if (calc_pos(iseq, pc, &lineno, NULL)) 
return lineno;
 
   91#ifdef USE_ISEQ_NODE_ID 
   96    if (calc_pos(iseq, pc, NULL, &node_id)) 
return node_id;
 
  104    if (VM_FRAME_RUBYFRAME_P(cfp) && cfp->iseq) {
 
  106        int line = calc_lineno(iseq, cfp->pc);
 
  111            return ISEQ_BODY(iseq)->location.first_lineno;
 
  131location_mark(
void *ptr)
 
  134    rb_gc_mark_movable(vfi->btobj);
 
  138location_ref_update(
void *ptr)
 
  141    vfi->btobj = rb_gc_location(vfi->btobj);
 
  147    rb_gc_mark((
VALUE)fi->cme);
 
  148    if (fi->iseq) rb_gc_mark_movable((
VALUE)fi->iseq);
 
  159    0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
 
  163rb_frame_info_p(
VALUE obj)
 
  169location_ptr(
VALUE locobj)
 
  180        return calc_lineno(loc->iseq, loc->pc);
 
  194location_lineno_m(
VALUE self)
 
  196    return INT2FIX(location_lineno(location_ptr(self)));
 
  199VALUE rb_mod_name0(
VALUE klass, 
bool *permanent);
 
  206        if (RCLASS_SINGLETON_P(owner)) {
 
  207            VALUE v = RCLASS_ATTACHED_OBJECT(owner);
 
  209                v = rb_mod_name0(v, &permanent);
 
  210                if (permanent && !
NIL_P(v)) {
 
  211                    return rb_sprintf(
"%"PRIsVALUE
".%"PRIsVALUE, v, name);
 
  216            owner = rb_mod_name0(owner, &permanent);
 
  217            if (permanent && !
NIL_P(owner)) {
 
  218                return rb_sprintf(
"%"PRIsVALUE
"#%"PRIsVALUE, owner, name);
 
  229    switch (ISEQ_BODY(iseq)->
type) {
 
  231      case ISEQ_TYPE_CLASS:
 
  233        return ISEQ_BODY(iseq)->location.label;
 
  234      case ISEQ_TYPE_METHOD:
 
  235        return rb_gen_method_name(owner, ISEQ_BODY(iseq)->location.label);
 
  236      case ISEQ_TYPE_BLOCK:
 
  237      case ISEQ_TYPE_PLAIN: {
 
  240        if (ISEQ_BODY(orig_iseq)->parent_iseq != 0) {
 
  241            while (ISEQ_BODY(orig_iseq)->local_iseq != iseq) {
 
  242                if (ISEQ_BODY(iseq)->
type == ISEQ_TYPE_BLOCK) {
 
  245                iseq = ISEQ_BODY(iseq)->parent_iseq;
 
  249            return rb_sprintf(
"block in %"PRIsVALUE, calculate_iseq_label(owner, iseq));
 
  252            return rb_sprintf(
"block (%d levels) in %"PRIsVALUE, level, calculate_iseq_label(owner, iseq));
 
  255      case ISEQ_TYPE_RESCUE:
 
  256      case ISEQ_TYPE_ENSURE:
 
  258        iseq = ISEQ_BODY(iseq)->parent_iseq;
 
  261        rb_bug(
"calculate_iseq_label: unreachable");
 
  266is_internal_location(
const rb_iseq_t *iseq)
 
  268    static const char prefix[] = 
"<internal:";
 
  269    const size_t prefix_len = 
sizeof(prefix) - 1;
 
  270    VALUE file = rb_iseq_path(iseq);
 
  271    return strncmp(prefix, RSTRING_PTR(file), prefix_len) == 0;
 
  278    if (!loc->cme) 
return false;
 
  280    switch (loc->cme->def->type) {
 
  281      case VM_METHOD_TYPE_CFUNC:
 
  283      case VM_METHOD_TYPE_ISEQ:
 
  284        return is_internal_location(loc->cme->def->body.iseq.
iseqptr);
 
  293    if (location_cfunc_p(loc)) {
 
  294        return rb_gen_method_name(loc->cme->owner, rb_id2str(loc->cme->def->original_id));
 
  299            owner = loc->cme->owner;
 
  301        return calculate_iseq_label(owner, loc->iseq);
 
  331location_label_m(
VALUE self)
 
  333    return location_label(location_ptr(self));
 
  339    if (location_cfunc_p(loc)) {
 
  340        return rb_id2str(loc->cme->def->original_id);
 
  343    return ISEQ_BODY(loc->iseq)->location.base_label;
 
  371location_base_label_m(
VALUE self)
 
  373    return location_base_label(location_ptr(self));
 
  393location_path_m(
VALUE self)
 
  395    const rb_iseq_t *iseq = location_iseq(location_ptr(self));
 
  396    return iseq ? rb_iseq_path(iseq) : 
Qnil;
 
  399#ifdef USE_ISEQ_NODE_ID 
  404        return calc_node_id(loc->iseq, loc->pc);
 
  411rb_get_node_id_from_frame_info(
VALUE obj)
 
  413#ifdef USE_ISEQ_NODE_ID 
  415    return location_node_id(loc);
 
  422rb_get_iseq_from_frame_info(
VALUE obj)
 
  425    const rb_iseq_t *iseq = location_iseq(loc);
 
  433        return rb_iseq_realpath(loc->iseq);
 
  445location_absolute_path_m(
VALUE self)
 
  447    return location_realpath(location_ptr(self));
 
  451location_format(
VALUE file, 
int lineno, 
VALUE name)
 
  455        rb_str_catf(s, 
":%d", lineno);
 
  462        rb_str_catf(s, 
"'%s'", RSTRING_PTR(name));
 
  474    if (location_cfunc_p(loc)) {
 
  475        if (loc->iseq && loc->pc) {
 
  476            file = rb_iseq_path(loc->iseq);
 
  477            lineno = calc_lineno(loc->iseq, loc->pc);
 
  480            file = GET_VM()->progname;
 
  483        name = rb_gen_method_name(loc->cme->owner, rb_id2str(loc->cme->def->original_id));
 
  486        file = rb_iseq_path(loc->iseq);
 
  487        lineno = calc_lineno(loc->iseq, loc->pc);
 
  489            owner = loc->cme->owner;
 
  491        name = calculate_iseq_label(owner, loc->iseq);
 
  494    return location_format(file, lineno, name);
 
  501location_to_str_m(
VALUE self)
 
  503    return location_to_str(location_ptr(self));
 
  511location_inspect_m(
VALUE self)
 
  524backtrace_mark(
void *ptr)
 
  527    size_t i, s = bt->backtrace_size;
 
  529    for (i=0; i<s; i++) {
 
  530        location_mark_entry(&bt->backtrace[i]);
 
  532    rb_gc_mark_movable(bt->strary);
 
  533    rb_gc_mark_movable(bt->locary);
 
  546backtrace_update(
void *ptr)
 
  549    size_t i, s = bt->backtrace_size;
 
  551    for (i=0; i<s; i++) {
 
  552        location_update_entry(&bt->backtrace[i]);
 
  554    bt->strary = rb_gc_location(bt->strary);
 
  555    bt->locary = rb_gc_location(bt->locary);
 
  569    0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
 
  573rb_backtrace_p(
VALUE obj)
 
  579backtrace_alloc(
VALUE klass)
 
  590    VALUE btobj = rb_data_typed_object_zalloc(rb_cBacktrace, memsize, &backtrace_data_type);
 
  602    if (start_cfp == NULL) {
 
  607      RUBY_VM_NEXT_CONTROL_FRAME(
 
  608          RUBY_VM_NEXT_CONTROL_FRAME(start_cfp)); 
 
  610    if (start_cfp < last_cfp) {
 
  614    return start_cfp - last_cfp + 1;
 
  620    enum rb_iseq_type 
type = ISEQ_BODY(cfp->iseq)->type;
 
  621    return type == ISEQ_TYPE_RESCUE || 
type == ISEQ_TYPE_ENSURE;
 
  627    for (; backpatch_counter > 0; backpatch_counter--, loc--) {
 
  638    for (; num_frames > 0; num_frames--, loc++) {
 
  639        rb_yield(location_create(loc, (
void *)btobj));
 
  644rb_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)
 
  652    unsigned long backpatch_counter = 0;
 
  653    bool skip_next_frame = FALSE;
 
  656    if (end_cfp == NULL) {
 
  660        end_cfp = RUBY_VM_NEXT_CONTROL_FRAME(end_cfp);
 
  672        size = end_cfp - cfp + 1;
 
  676        else if (num_frames < 0 || num_frames > size) {
 
  681    btobj = backtrace_alloc_capa(num_frames, &bt);
 
  683    bt->backtrace_size = 0;
 
  684    if (num_frames == 0) {
 
  685        if (start_too_large) *start_too_large = 0;
 
  689    for (; cfp != end_cfp && (bt->backtrace_size < num_frames); cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) {
 
  692                if (start_frame > 0) {
 
  696                    bool internal = is_internal_location(cfp->iseq);
 
  697                    if (skip_internal && internal) 
continue;
 
  698                    if (!skip_next_frame) {
 
  700                        const VALUE *pc = cfp->pc;
 
  701                        if (internal && backpatch_counter > 0) {
 
  703                            bt->backtrace_size -= backpatch_counter;
 
  704                            backpatch_counter = 0;
 
  706                        loc = &bt->backtrace[bt->backtrace_size++];
 
  707                        RB_OBJ_WRITE(btobj, &loc->cme, rb_vm_frame_method_entry(cfp));
 
  719                            if ((VM_FRAME_TYPE(cfp) & VM_FRAME_MAGIC_MASK) == VM_FRAME_MAGIC_DUMMY) {
 
  725                            bt_backpatch_loc(backpatch_counter, loc-1, iseq, pc);
 
  727                                bt_yield_loc(loc - backpatch_counter, backpatch_counter+1, btobj);
 
  729                            backpatch_counter = 0;
 
  732                    skip_next_frame = is_rescue_or_ensure_frame(cfp);
 
  737            VM_ASSERT(RUBYVM_CFUNC_FRAME_P(cfp));
 
  738            if (start_frame > 0) {
 
  742                loc = &bt->backtrace[bt->backtrace_size++];
 
  743                RB_OBJ_WRITE(btobj, &loc->cme, rb_vm_frame_method_entry(cfp));
 
  753    if (backpatch_counter > 0) {
 
  754        for (; cfp != end_cfp; cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) {
 
  755            if (cfp->iseq && cfp->pc && !(skip_internal && is_internal_location(cfp->iseq))) {
 
  756                VM_ASSERT(!skip_next_frame); 
 
  757                bt_backpatch_loc(backpatch_counter, loc, cfp->iseq, cfp->pc);
 
  760                    bt_yield_loc(loc - backpatch_counter, backpatch_counter, btobj);
 
  767    if (start_too_large) *start_too_large = (start_frame > 0 ? -1 : 0);
 
  774    return rb_ec_partial_backtrace_object(ec, RUBY_BACKTRACE_START, RUBY_ALL_BACKTRACE_LINES, NULL, FALSE, FALSE);
 
  785    for (i=0; i<bt->backtrace_size; i++) {
 
  796    return location_to_str(loc);
 
  800backtrace_to_str_ary(
VALUE self)
 
  805    r = backtrace_collect(bt, location_to_str_dmyarg, 0);
 
  811rb_backtrace_to_str_ary(
VALUE self)
 
  817        RB_OBJ_WRITE(self, &bt->strary, backtrace_to_str_ary(self));
 
  836backtrace_to_location_ary(
VALUE self)
 
  841    r = backtrace_collect(bt, location_create, (
void *)self);
 
  847rb_backtrace_to_location_ary(
VALUE self)
 
  853        RB_OBJ_WRITE(self, &bt->locary, backtrace_to_location_ary(self));
 
  859rb_location_ary_to_backtrace(
VALUE ary)
 
  867    VALUE btobj = backtrace_alloc_capa(num_frames, &new_backtrace);
 
  869    for (
long index = 0; index < 
RARRAY_LEN(ary); index++) {
 
  872        if (!rb_frame_info_p(locobj)) {
 
  880        RB_OBJ_WRITE(btobj, &dst_location->cme, src_vloc->loc->cme);
 
  881        RB_OBJ_WRITE(btobj, &dst_location->iseq, src_vloc->loc->iseq);
 
  882        dst_location->pc = src_vloc->loc->pc;
 
  884        new_backtrace->backtrace_size++;
 
  893backtrace_dump_data(
VALUE self)
 
  895    VALUE str = rb_backtrace_to_str_ary(self);
 
  959backtrace_limit(
VALUE self)
 
  961    return LONG2NUM(rb_backtrace_length_limit);
 
  967    return rb_backtrace_to_str_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL, FALSE, FALSE));
 
  973    return rb_backtrace_to_location_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL, skip_internal, FALSE));
 
  980           void (*init)(
void *arg, 
size_t size),
 
  991    if (start_cfp == NULL) {
 
 1007      RUBY_VM_NEXT_CONTROL_FRAME(
 
 1008        RUBY_VM_NEXT_CONTROL_FRAME(start_cfp)); 
 
 1010    if (start_cfp < last_cfp) {
 
 1014        size = start_cfp - last_cfp + 1;
 
 1020    for (i=0, cfp = start_cfp; i<size; i++, cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
 
 1024                iter_iseq(arg, cfp);
 
 1028            VM_ASSERT(RUBYVM_CFUNC_FRAME_P(cfp));
 
 1030            ID mid = me->def->original_id;
 
 1032            iter_cfunc(arg, cfp, mid);
 
 1040    void (*func)(
void *data, 
VALUE file, 
int lineno, 
VALUE name);
 
 
 1045oldbt_init(
void *ptr, 
size_t dmy)
 
 1048    arg->filename = GET_VM()->progname;
 
 1056    const VALUE *pc = cfp->pc;
 
 1058    VALUE file = arg->filename = rb_iseq_path(iseq);
 
 1059    VALUE name = ISEQ_BODY(iseq)->location.label;
 
 1060    int lineno = arg->lineno = calc_lineno(iseq, pc);
 
 1062    (arg->func)(arg->data, file, lineno, name);
 
 1069    VALUE file = arg->filename;
 
 1070    VALUE name = rb_id2str(mid);
 
 1071    int lineno = arg->lineno;
 
 1073    (arg->func)(arg->data, file, lineno, name);
 
 1077oldbt_print(
void *data, 
VALUE file, 
int lineno, 
VALUE name)
 
 1082        fprintf(fp, 
"\tfrom %s:%d:in unknown method\n",
 
 1083                RSTRING_PTR(file), lineno);
 
 1086        fprintf(fp, 
"\tfrom %s:%d:in '%s'\n",
 
 1087                RSTRING_PTR(file), lineno, RSTRING_PTR(name));
 
 1092vm_backtrace_print(
FILE *fp)
 
 1096    arg.func = oldbt_print;
 
 1097    arg.data = (
void *)fp;
 
 1098    backtrace_each(GET_EC(),
 
 1111oldbt_bugreport(
void *arg, 
VALUE file, 
int line, 
VALUE method)
 
 1115    const char *filename = 
NIL_P(file) ? 
"ruby" : RSTRING_PTR(file);
 
 1117        fprintf(fp, 
"-- Ruby level backtrace information " 
 1118                "----------------------------------------\n");
 
 1121    if (
NIL_P(method)) {
 
 1122        fprintf(fp, 
"%s:%d:in unknown method\n", filename, line);
 
 1125        fprintf(fp, 
"%s:%d:in '%s'\n", filename, line, RSTRING_PTR(method));
 
 1130rb_backtrace_print_as_bugreport(
FILE *fp)
 
 1135    arg.func = oldbt_bugreport;
 
 1138    backtrace_each(GET_EC(),
 
 1148    vm_backtrace_print(stderr);
 
 
 1157oldbt_print_to(
void *data, 
VALUE file, 
int lineno, 
VALUE name)
 
 1160    VALUE str = rb_sprintf(
"\tfrom %"PRIsVALUE
":%d:in ", file, lineno);
 
 1166        rb_str_catf(str, 
" '%"PRIsVALUE
"'\n", name);
 
 1168    (*arg->iter)(arg->output, str);
 
 1178    parg.output = output;
 
 1179    arg.func = oldbt_print_to;
 
 1181    backtrace_each(GET_EC(),
 
 1189rb_make_backtrace(
void)
 
 1191    return rb_ec_backtrace_str_ary(GET_EC(), RUBY_BACKTRACE_START, RUBY_ALL_BACKTRACE_LINES);
 
 
 1197    VALUE level, vn, opts;
 
 1205    if (argc == 2 && 
NIL_P(vn)) argc--;
 
 1209        lev = lev_default + lev_plus;
 
 1210        n = RUBY_ALL_BACKTRACE_LINES;
 
 1214            long beg, 
len, bt_size = backtrace_size(ec);
 
 1219                    rb_raise(rb_eArgError, 
"negative level (%ld)", lev);
 
 1222                n = RUBY_ALL_BACKTRACE_LINES;
 
 1227                lev = beg + lev_plus;
 
 1237            rb_raise(rb_eArgError, 
"negative level (%ld)", lev);
 
 1240            rb_raise(rb_eArgError, 
"negative size (%ld)", n);
 
 1260    lev = ec_backtrace_range(ec, argc, argv, lev_default, lev_plus, &n);
 
 1261    if (lev < 0) 
return Qnil;
 
 1267    btval = rb_ec_partial_backtrace_object(ec, lev, n, &too_large, FALSE, FALSE);
 
 1274        r = backtrace_to_str_ary(btval);
 
 1277        r = backtrace_to_location_ary(btval);
 
 1284thread_backtrace_to_ary(
int argc, 
const VALUE *argv, 
VALUE thval, 
int to_str)
 
 1288    if (target_th->to_kill || target_th->status == THREAD_KILLED)
 
 1291    return ec_backtrace_to_ary(target_th->ec, argc, argv, 0, 0, to_str);
 
 1295rb_vm_thread_backtrace(
int argc, 
const VALUE *argv, 
VALUE thval)
 
 1297    return thread_backtrace_to_ary(argc, argv, thval, 1);
 
 1301rb_vm_thread_backtrace_locations(
int argc, 
const VALUE *argv, 
VALUE thval)
 
 1303    return thread_backtrace_to_ary(argc, argv, thval, 0);
 
 1309    return ec_backtrace_to_ary(ec, argc, argv, 0, 0, 1);
 
 1315    return ec_backtrace_to_ary(ec, argc, argv, 0, 0, 0);
 
 1359    return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 1);
 
 1385rb_f_caller_locations(
int argc, 
VALUE *argv, 
VALUE _)
 
 1387    return ec_backtrace_to_ary(GET_EC(), argc, argv, 1, 1, 0);
 
 1398each_caller_location(
int argc, 
VALUE *argv, 
VALUE _)
 
 1401    long n, lev = ec_backtrace_range(ec, argc, argv, 1, 1, &n);
 
 1402    if (lev >= 0 && n != 0) {
 
 1403        rb_ec_partial_backtrace_object(ec, lev, n, NULL, FALSE, TRUE);
 
 1410Init_vm_backtrace(
void)
 
 1475    rb_define_method(rb_cBacktraceLocation, 
"base_label", location_base_label_m, 0);
 
 1477    rb_define_method(rb_cBacktraceLocation, 
"absolute_path", location_absolute_path_m, 0);
 
 1489RUBY_SYMBOL_EXPORT_BEGIN
 
 1491RUBY_SYMBOL_EXPORT_END
 
 1497    VALUE raw_backtrace;
 
 
 1501    CALLER_BINDING_SELF,
 
 1502    CALLER_BINDING_CLASS,
 
 1503    CALLER_BINDING_BINDING,
 
 1504    CALLER_BINDING_ISEQ,
 
 1507    CALLER_BINDING_DEPTH,
 
 1518collect_caller_bindings_init(
void *arg, 
size_t num_frames)
 
 1521    data->btobj = backtrace_alloc_capa(num_frames, &data->bt);
 
 1528    if (rb_vm_control_frame_id_and_class(cfp, 0, 0, &klass)) {
 
 1530            return RBASIC(klass)->klass;
 
 1544    VM_ASSERT(RUBY_VM_END_CONTROL_FRAME(ec) >= cfp);
 
 1545    return (
int)(RUBY_VM_END_CONTROL_FRAME(ec) - cfp);
 
 1555    rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
 
 1556    rb_ary_store(frame, CALLER_BINDING_BINDING, GC_GUARDED_PTR(cfp)); 
 
 1558    rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp));
 
 1561    RB_OBJ_WRITE(data->btobj, &loc->cme, rb_vm_frame_method_entry(cfp));
 
 1564    VALUE vloc = location_create(loc, (
void *)data->btobj);
 
 1579    rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
 
 1582    rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp));
 
 1585    RB_OBJ_WRITE(data->btobj, &loc->cme, rb_vm_frame_method_entry(cfp));
 
 1588    VALUE vloc = location_create(loc, (
void *)data->btobj);
 
 1606                   collect_caller_bindings_init,
 
 1607                   collect_caller_bindings_iseq,
 
 1608                   collect_caller_bindings_cfunc,
 
 1618        if (!
NIL_P(cfp_val)) {
 
 1620            rb_ary_store(entry, CALLER_BINDING_BINDING, rb_vm_make_binding(ec, cfp));
 
 1637    enum ruby_tag_type state;
 
 1638    volatile VALUE MAYBE_UNUSED(result);
 
 1642    rb_vm_stack_to_heap(ec);
 
 1644    dbg_context.ec = ec;
 
 1645    dbg_context.cfp = dbg_context.ec->cfp;
 
 1646    dbg_context.contexts = collect_caller_bindings(ec);
 
 1648    for (i=0; i<
RARRAY_LEN(dbg_context.contexts); i++) {
 
 1654    if ((state = EC_EXEC_TAG()) == TAG_NONE) {
 
 1655        result = (*func)(&dbg_context, data);
 
 1662        EC_JUMP_TAG(ec, state);
 
 
 1671    if (index < 0 || index >= 
RARRAY_LEN(dc->contexts)) {
 
 1672        rb_raise(rb_eArgError, 
"no such frame");
 
 1680    VALUE frame = frame_get(dc, index);
 
 
 1687    VALUE frame = frame_get(dc, index);
 
 
 1694    VALUE frame = frame_get(dc, index);
 
 
 1701    VALUE frame = frame_get(dc, index);
 
 
 1710    VALUE frame = frame_get(dc, index);
 
 
 1718    return INT2FIX(frame_depth(ec, ec->cfp));
 
 
 1724    return dc->raw_backtrace;
 
 
 1745    end_cfp = RUBY_VM_NEXT_CONTROL_FRAME(end_cfp);
 
 1747    for (i=0; i<limit && cfp != end_cfp; cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) {
 
 1748        if (VM_FRAME_RUBYFRAME_P_UNCHECKED(cfp) && cfp->pc != 0) {
 
 1755            cme = rb_vm_frame_method_entry_unchecked(cfp);
 
 1756            if (cme && cme->def->type == VM_METHOD_TYPE_ISEQ) {
 
 1757                buff[i] = (
VALUE)cme;
 
 1760                buff[i] = (
VALUE)cfp->iseq;
 
 1764                const VALUE *pc = cfp->pc;
 
 1765                VALUE *iseq_encoded = ISEQ_BODY(cfp->iseq)->iseq_encoded;
 
 1766                VALUE *pc_end = iseq_encoded + ISEQ_BODY(cfp->iseq)->iseq_size;
 
 1777                if (cfp == top && (pc < iseq_encoded || pc > pc_end)) {
 
 1781                    lines[i] = calc_lineno(cfp->iseq, pc);
 
 1788            cme = rb_vm_frame_method_entry_unchecked(cfp);
 
 1789            if (cme && cme->def->type == VM_METHOD_TYPE_CFUNC) {
 
 1794                buff[i] = (
VALUE)cme;
 
 1795                if (lines) lines[i] = 0;
 
 1815    return thread_profile_frames(ec, start, limit, buff, lines);
 
 
 1822    return thread_profile_frames(th->ec, start, limit, buff, lines);
 
 
 1826frame2iseq(
VALUE frame)
 
 1828    if (
NIL_P(frame)) 
return NULL;
 
 1831        switch (imemo_type(frame)) {
 
 1837                switch (cme->def->type) {
 
 1838                  case VM_METHOD_TYPE_ISEQ:
 
 1839                    return cme->def->body.iseq.
iseqptr;
 
 1848    rb_bug(
"frame2iseq: unreachable");
 
 1854    const rb_iseq_t *iseq = frame2iseq(frame);
 
 1855    return iseq ? rb_iseq_path(iseq) : 
Qnil;
 
 
 1861    if (
NIL_P(frame)) 
return NULL;
 
 1864        switch (imemo_type(frame)) {
 
 1868                switch (cme->def->type) {
 
 1869                  case VM_METHOD_TYPE_CFUNC:
 
 1886    if (cframe(frame)) {
 
 1890            rb_vm_register_global_object(cfunc_str);
 
 1894    const rb_iseq_t *iseq = frame2iseq(frame);
 
 1895    return iseq ? rb_iseq_realpath(iseq) : 
Qnil;
 
 
 1901    const rb_iseq_t *iseq = frame2iseq(frame);
 
 1902    return iseq ? rb_iseq_label(iseq) : 
Qnil;
 
 
 1908    const rb_iseq_t *iseq = frame2iseq(frame);
 
 1909    return iseq ? rb_iseq_base_label(iseq) : 
Qnil;
 
 
 1915    const rb_iseq_t *iseq = frame2iseq(frame);
 
 1916    return iseq ? rb_iseq_first_lineno(iseq) : 
Qnil;
 
 
 1920frame2klass(
VALUE frame)
 
 1927        if (imemo_type(frame) == imemo_ment) {
 
 1928            return cme->defined_class;
 
 1937    VALUE klass = frame2klass(frame);
 
 1939    if (klass && !
NIL_P(klass)) {
 
 1941            klass = 
RBASIC(klass)->klass;
 
 1943        else if (RCLASS_SINGLETON_P(klass)) {
 
 1944            klass = RCLASS_ATTACHED_OBJECT(klass);
 
 
 1958    VALUE klass = frame2klass(frame);
 
 1960    return RBOOL(klass && !
NIL_P(klass) && RCLASS_SINGLETON_P(klass));
 
 
 1968        ID mid = cme->def->original_id;
 
 1971    const rb_iseq_t *iseq = frame2iseq(frame);
 
 1972    return iseq ? rb_iseq_method_name(iseq) : 
Qnil;
 
 
 1976qualified_method_name(
VALUE frame, 
VALUE method_name)
 
 1978    if (method_name != 
Qnil) {
 
 1982        if (classpath != 
Qnil) {
 
 1983            return rb_sprintf(
"%"PRIsVALUE
"%s%"PRIsVALUE,
 
 1984                              classpath, singleton_p == 
Qtrue ? 
"." : 
"#", method_name);
 
 2000    return qualified_method_name(frame, method_name);
 
 
 2008        ID mid = cme->def->original_id;
 
 2009        VALUE method_name = id2str(mid);
 
 2010        return qualified_method_name(frame, method_name);
 
 2017    if (
NIL_P(qualified_method_name) || base_label == qualified_method_name) {
 
 2021        long label_length = RSTRING_LEN(label);
 
 2022        long base_label_length = RSTRING_LEN(base_label);
 
 2023        int prefix_len = 
rb_long2int(label_length - base_label_length);
 
 2025        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.
 
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 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.
 
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Checks if the given object is of given kind.
 
VALUE rb_cArray
Array 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 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 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.