summaryrefslogtreecommitdiff
path: root/vm_backtrace.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2022-11-25 11:51:35 +0900
committerKoichi Sasada <ko1@atdot.net>2022-11-25 14:01:36 +0900
commit67766cd55c3a05f9888c8e2b9e34051a44b3e3fc (patch)
treedb62bad59ad9c6040f7d1b13733d7d0bc2c384d9 /vm_backtrace.c
parent571d21fd4a2e877f49b4ff918832bda9a5e8f91c (diff)
downloadruby-67766cd55c3a05f9888c8e2b9e34051a44b3e3fc.tar.gz
add debug context APIs for debuggers (frame depth)
The following new debug context APIs are for implementing debugger's `next` (step over) and similar functionality. * `rb_debug_inspector_frame_depth(dc, index)` returns `index`-th frame's depth. * `rb_debug_inspector_current_depth()` returns current frame depth. The frame depth is not related to the frame index because debug context API skips some special frames but proposed `_depth()` APIs returns the count of all frames (raw depth).
Diffstat (limited to 'vm_backtrace.c')
-rw-r--r--vm_backtrace.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/vm_backtrace.c b/vm_backtrace.c
index 75546cd229..6e38224a91 100644
--- a/vm_backtrace.c
+++ b/vm_backtrace.c
@@ -1374,11 +1374,13 @@ enum {
CALLER_BINDING_CLASS,
CALLER_BINDING_BINDING,
CALLER_BINDING_ISEQ,
- CALLER_BINDING_CFP
+ CALLER_BINDING_CFP,
+ CALLER_BINDING_DEPTH,
};
struct collect_caller_bindings_data {
VALUE ary;
+ const rb_execution_context_t *ec;
};
static void
@@ -1404,17 +1406,25 @@ get_klass(const rb_control_frame_t *cfp)
}
}
+static int
+frame_depth(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
+{
+ VM_ASSERT(RUBY_VM_END_CONTROL_FRAME(ec) >= cfp);
+ return (int)(RUBY_VM_END_CONTROL_FRAME(ec) - cfp);
+}
+
static void
collect_caller_bindings_iseq(void *arg, const rb_control_frame_t *cfp)
{
struct collect_caller_bindings_data *data = (struct collect_caller_bindings_data *)arg;
- VALUE frame = rb_ary_new2(5);
+ VALUE frame = rb_ary_new2(6);
rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self);
rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
rb_ary_store(frame, CALLER_BINDING_BINDING, GC_GUARDED_PTR(cfp)); /* create later */
rb_ary_store(frame, CALLER_BINDING_ISEQ, cfp->iseq ? (VALUE)cfp->iseq : Qnil);
rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp));
+ rb_ary_store(frame, CALLER_BINDING_DEPTH, INT2FIX(frame_depth(data->ec, cfp)));
rb_ary_push(data->ary, frame);
}
@@ -1423,13 +1433,14 @@ static void
collect_caller_bindings_cfunc(void *arg, const rb_control_frame_t *cfp, ID mid)
{
struct collect_caller_bindings_data *data = (struct collect_caller_bindings_data *)arg;
- VALUE frame = rb_ary_new2(5);
+ VALUE frame = rb_ary_new2(6);
rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self);
rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
rb_ary_store(frame, CALLER_BINDING_BINDING, Qnil); /* not available */
rb_ary_store(frame, CALLER_BINDING_ISEQ, Qnil); /* not available */
rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp));
+ rb_ary_store(frame, CALLER_BINDING_DEPTH, INT2FIX(frame_depth(data->ec, cfp)));
rb_ary_push(data->ary, frame);
}
@@ -1437,11 +1448,11 @@ collect_caller_bindings_cfunc(void *arg, const rb_control_frame_t *cfp, ID mid)
static VALUE
collect_caller_bindings(const rb_execution_context_t *ec)
{
- struct collect_caller_bindings_data data;
- VALUE result;
int i;
-
- data.ary = rb_ary_new();
+ VALUE result;
+ struct collect_caller_bindings_data data = {
+ rb_ary_new(), ec
+ };
backtrace_each(ec,
collect_caller_bindings_init,
@@ -1542,6 +1553,20 @@ rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index)
}
VALUE
+rb_debug_inspector_frame_depth(const rb_debug_inspector_t *dc, long index)
+{
+ VALUE frame = frame_get(dc, index);
+ return rb_ary_entry(frame, CALLER_BINDING_DEPTH);
+}
+
+VALUE
+rb_debug_inspector_current_depth(void)
+{
+ rb_execution_context_t *ec = GET_EC();
+ return INT2FIX(frame_depth(ec, ec->cfp));
+}
+
+VALUE
rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc)
{
return dc->backtrace;