diff options
author | Koichi Sasada <[email protected]> | 2022-11-25 11:51:35 +0900 |
---|---|---|
committer | Koichi Sasada <[email protected]> | 2022-11-25 14:01:36 +0900 |
commit | 67766cd55c3a05f9888c8e2b9e34051a44b3e3fc (patch) | |
tree | db62bad59ad9c6040f7d1b13733d7d0bc2c384d9 /vm_backtrace.c | |
parent | 571d21fd4a2e877f49b4ff918832bda9a5e8f91c (diff) |
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).
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/6805
Diffstat (limited to 'vm_backtrace.c')
-rw-r--r-- | vm_backtrace.c | 39 |
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; |