зеркало из https://github.com/github/ruby.git
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).
This commit is contained in:
Родитель
571d21fd4a
Коммит
67766cd55c
|
@ -206,6 +206,17 @@ typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *dc, void
|
|||
*/
|
||||
VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data);
|
||||
|
||||
/**
|
||||
* Queries the backtrace object of the context. This is as if you call
|
||||
* `caller_locations` at the point of debugger.
|
||||
*
|
||||
* @param[in] dc A debug context.
|
||||
* @return An array of `Thread::Backtrace::Location` which represents the
|
||||
* current point of execution at `dc`.
|
||||
|
||||
*/
|
||||
VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc);
|
||||
|
||||
/**
|
||||
* Queries the current receiver of the passed context's upper frame.
|
||||
*
|
||||
|
@ -250,15 +261,27 @@ VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long
|
|||
VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index);
|
||||
|
||||
/**
|
||||
* Queries the backtrace object of the context. This is as if you call
|
||||
* `caller_locations` at the point of debugger.
|
||||
* Queries the depth of the passed context's upper frame.
|
||||
*
|
||||
* @param[in] dc A debug context.
|
||||
* @return An array of `Thread::Backtrace::Location` which represents the
|
||||
* current point of execution at `dc`.
|
||||
|
||||
* Note that the depth is not same as the frame index because debug_inspector
|
||||
* skips some special frames but the depth counts all frames.
|
||||
*
|
||||
* @param[in] dc A debug context.
|
||||
* @param[in] index Index of the frame from top to bottom.
|
||||
* @exception rb_eArgError `index` out of range.
|
||||
* @retval The depth at `index`-th frame in Integer.
|
||||
*/
|
||||
VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc);
|
||||
VALUE rb_debug_inspector_frame_depth(const rb_debug_inspector_t *dc, long index);
|
||||
|
||||
// A macro to recognize `rb_debug_inspector_frame_depth()` is available or not
|
||||
#define RB_DEBUG_INSPECTOR_FRAME_DEPTH(dc, index) rb_debug_inspector_frame_depth(dc, index)
|
||||
|
||||
/**
|
||||
* Return current frmae depth.
|
||||
*
|
||||
* @retval The depth of the current frame in Integer.
|
||||
*/
|
||||
VALUE rb_debug_inspector_current_depth(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
@ -1541,6 +1552,20 @@ rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index)
|
|||
return RTEST(iseq) ? rb_iseqw_new((rb_iseq_t *)iseq) : Qnil;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче