* include/ruby/debug.h: add rb_debug_inspector_* APIs.
* vm_backtrace.c: ditto. * common.mk: add dpendency from vm_backtrace.o to include/ruby/debug.h. * proc.c (rb_binding_new_with_cfp): constify. * vm.c (rb_vm_get_ruby_level_next_cfp): consitify. * vm_core.h, vm_trace.c: move decls. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
07b10cd59f
commit
585ac7f1a2
15
ChangeLog
15
ChangeLog
@ -1,3 +1,18 @@
|
|||||||
|
Thu Nov 29 15:59:55 2012 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
|
* include/ruby/debug.h: add rb_debug_inspector_* APIs.
|
||||||
|
|
||||||
|
* vm_backtrace.c: ditto.
|
||||||
|
|
||||||
|
* common.mk: add dpendency from vm_backtrace.o to
|
||||||
|
include/ruby/debug.h.
|
||||||
|
|
||||||
|
* proc.c (rb_binding_new_with_cfp): constify.
|
||||||
|
|
||||||
|
* vm.c (rb_vm_get_ruby_level_next_cfp): consitify.
|
||||||
|
|
||||||
|
* vm_core.h, vm_trace.c: move decls.
|
||||||
|
|
||||||
Thu Nov 29 15:56:14 2012 NARUSE, Yui <naruse@ruby-lang.org>
|
Thu Nov 29 15:56:14 2012 NARUSE, Yui <naruse@ruby-lang.org>
|
||||||
|
|
||||||
* lib/rdoc/test_case.rb (RDoc::TestCase#verbose_capture_io):
|
* lib/rdoc/test_case.rb (RDoc::TestCase#verbose_capture_io):
|
||||||
|
@ -774,7 +774,7 @@ debug.$(OBJEXT): {$(VPATH)}debug.c $(RUBY_H_INCLUDES) \
|
|||||||
id.$(OBJEXT): {$(VPATH)}id.c $(RUBY_H_INCLUDES) $(ID_H_INCLUDES) {$(VPATH)}vm_opts.h
|
id.$(OBJEXT): {$(VPATH)}id.c $(RUBY_H_INCLUDES) $(ID_H_INCLUDES) {$(VPATH)}vm_opts.h
|
||||||
vm_backtrace.$(OBJEXT): {$(VPATH)}vm_backtrace.c \
|
vm_backtrace.$(OBJEXT): {$(VPATH)}vm_backtrace.c \
|
||||||
$(VM_CORE_H_INCLUDES) $(RUBY_H_INCLUDES) $(ENCODING_H_INCLUDES) \
|
$(VM_CORE_H_INCLUDES) $(RUBY_H_INCLUDES) $(ENCODING_H_INCLUDES) \
|
||||||
{$(VPATH)}internal.h {$(VPATH)}iseq.h
|
{$(VPATH)}internal.h {$(VPATH)}iseq.h {$(VPATH)}debug.h
|
||||||
vm_trace.$(OBJEXT): {$(VPATH)}vm_trace.c $(ENCODING_H_INCLUDES) \
|
vm_trace.$(OBJEXT): {$(VPATH)}vm_trace.c $(ENCODING_H_INCLUDES) \
|
||||||
$(VM_CORE_H_INCLUDES) $(RUBY_H_INCLUDES) {$(VPATH)}debug.h \
|
$(VM_CORE_H_INCLUDES) $(RUBY_H_INCLUDES) {$(VPATH)}debug.h \
|
||||||
{$(VPATH)}internal.h
|
{$(VPATH)}internal.h
|
||||||
|
@ -26,6 +26,16 @@ extern "C" {
|
|||||||
/* Note: This file contains experimental APIs. */
|
/* Note: This file contains experimental APIs. */
|
||||||
/* APIs can be replaced at Ruby 2.0.1 or later */
|
/* APIs can be replaced at Ruby 2.0.1 or later */
|
||||||
|
|
||||||
|
/* debug inspector APIs */
|
||||||
|
typedef struct rb_debug_inspector_struct rb_debug_inspector_t;
|
||||||
|
typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *, void *);
|
||||||
|
|
||||||
|
VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data);
|
||||||
|
VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, int index);
|
||||||
|
VALUE rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, int index);
|
||||||
|
VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, int index);
|
||||||
|
VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc);
|
||||||
|
|
||||||
/* Old style set_trace_func APIs */
|
/* Old style set_trace_func APIs */
|
||||||
|
|
||||||
void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data);
|
void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data);
|
||||||
@ -55,7 +65,7 @@ VALUE rb_tracearg_self(struct rb_trace_arg_struct *trace_arg);
|
|||||||
VALUE rb_tracearg_return_value(struct rb_trace_arg_struct *trace_arg);
|
VALUE rb_tracearg_return_value(struct rb_trace_arg_struct *trace_arg);
|
||||||
VALUE rb_tracearg_raised_exception(struct rb_trace_arg_struct *trace_arg);
|
VALUE rb_tracearg_raised_exception(struct rb_trace_arg_struct *trace_arg);
|
||||||
|
|
||||||
/* undocumented advanced APIs */
|
/* undocumented advanced tracing APIs */
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RUBY_EVENT_HOOK_FLAG_SAFE = 0x01,
|
RUBY_EVENT_HOOK_FLAG_SAFE = 0x01,
|
||||||
|
2
proc.c
2
proc.c
@ -310,7 +310,7 @@ binding_clone(VALUE self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_binding_new_with_cfp(rb_thread_t *th, rb_control_frame_t *src_cfp)
|
rb_binding_new_with_cfp(rb_thread_t *th, const rb_control_frame_t *src_cfp)
|
||||||
{
|
{
|
||||||
rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, src_cfp);
|
rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, src_cfp);
|
||||||
VALUE bindval = binding_alloc(rb_cBinding);
|
VALUE bindval = binding_alloc(rb_cBinding);
|
||||||
|
4
vm.c
4
vm.c
@ -186,11 +186,11 @@ vm_set_main_stack(rb_thread_t *th, VALUE iseqval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rb_control_frame_t *
|
rb_control_frame_t *
|
||||||
rb_vm_get_ruby_level_next_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
|
rb_vm_get_ruby_level_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp)
|
||||||
{
|
{
|
||||||
while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
|
while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
|
||||||
if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
||||||
return cfp;
|
return (rb_control_frame_t *)cfp;
|
||||||
}
|
}
|
||||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||||
}
|
}
|
||||||
|
156
vm_backtrace.c
156
vm_backtrace.c
@ -11,9 +11,11 @@
|
|||||||
|
|
||||||
#include "ruby/ruby.h"
|
#include "ruby/ruby.h"
|
||||||
#include "ruby/encoding.h"
|
#include "ruby/encoding.h"
|
||||||
|
#include "ruby/debug.h"
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "vm_core.h"
|
#include "vm_core.h"
|
||||||
|
#include "eval_intern.h"
|
||||||
#include "iseq.h"
|
#include "iseq.h"
|
||||||
|
|
||||||
static VALUE rb_cBacktrace;
|
static VALUE rb_cBacktrace;
|
||||||
@ -358,8 +360,8 @@ backtrace_alloc(VALUE klass)
|
|||||||
static void
|
static void
|
||||||
backtrace_each(rb_thread_t *th,
|
backtrace_each(rb_thread_t *th,
|
||||||
void (*init)(void *arg, size_t size),
|
void (*init)(void *arg, size_t size),
|
||||||
void (*iter_iseq)(void *arg, const rb_iseq_t *iseq, const VALUE *pc),
|
void (*iter_iseq)(void *arg, const rb_control_frame_t *cfp),
|
||||||
void (*iter_cfunc)(void *arg, ID mid),
|
void (*iter_cfunc)(void *arg, const rb_control_frame_t *cfp, ID mid),
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
rb_control_frame_t *last_cfp = th->cfp;
|
rb_control_frame_t *last_cfp = th->cfp;
|
||||||
@ -395,13 +397,13 @@ backtrace_each(rb_thread_t *th,
|
|||||||
/* fprintf(stderr, "cfp: %d\n", (rb_control_frame_t *)(th->stack + th->stack_size) - cfp); */
|
/* fprintf(stderr, "cfp: %d\n", (rb_control_frame_t *)(th->stack + th->stack_size) - cfp); */
|
||||||
if (cfp->iseq) {
|
if (cfp->iseq) {
|
||||||
if (cfp->pc) {
|
if (cfp->pc) {
|
||||||
iter_iseq(arg, cfp->iseq, cfp->pc);
|
iter_iseq(arg, cfp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (RUBYVM_CFUNC_FRAME_P(cfp)) {
|
else if (RUBYVM_CFUNC_FRAME_P(cfp)) {
|
||||||
ID mid = cfp->me->def ? cfp->me->def->original_id : cfp->me->called_id;
|
ID mid = cfp->me->def ? cfp->me->def->original_id : cfp->me->called_id;
|
||||||
|
|
||||||
iter_cfunc(arg, mid);
|
iter_cfunc(arg, cfp, mid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,8 +425,10 @@ bt_init(void *ptr, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bt_iter_iseq(void *ptr, const rb_iseq_t *iseq, const VALUE *pc)
|
bt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
|
||||||
{
|
{
|
||||||
|
const rb_iseq_t *iseq = cfp->iseq;
|
||||||
|
const VALUE *pc = cfp->pc;
|
||||||
struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
|
struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
|
||||||
rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++];
|
rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++];
|
||||||
loc->type = LOCATION_TYPE_ISEQ;
|
loc->type = LOCATION_TYPE_ISEQ;
|
||||||
@ -434,7 +438,7 @@ bt_iter_iseq(void *ptr, const rb_iseq_t *iseq, const VALUE *pc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bt_iter_cfunc(void *ptr, ID mid)
|
bt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
|
||||||
{
|
{
|
||||||
struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
|
struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
|
||||||
rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++];
|
rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++];
|
||||||
@ -599,8 +603,10 @@ oldbt_init(void *ptr, size_t dmy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
oldbt_iter_iseq(void *ptr, const rb_iseq_t *iseq, const VALUE *pc)
|
oldbt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
|
||||||
{
|
{
|
||||||
|
const rb_iseq_t *iseq = cfp->iseq;
|
||||||
|
const VALUE *pc = cfp->pc;
|
||||||
struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
|
struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
|
||||||
VALUE file = arg->filename = iseq->location.path;
|
VALUE file = arg->filename = iseq->location.path;
|
||||||
VALUE name = iseq->location.label;
|
VALUE name = iseq->location.label;
|
||||||
@ -610,7 +616,7 @@ oldbt_iter_iseq(void *ptr, const rb_iseq_t *iseq, const VALUE *pc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
oldbt_iter_cfunc(void *ptr, ID mid)
|
oldbt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
|
||||||
{
|
{
|
||||||
struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
|
struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
|
||||||
VALUE file = arg->filename;
|
VALUE file = arg->filename;
|
||||||
@ -846,3 +852,137 @@ Init_vm_backtrace(void)
|
|||||||
rb_define_global_function("caller", rb_f_caller, -1);
|
rb_define_global_function("caller", rb_f_caller, -1);
|
||||||
rb_define_global_function("caller_locations", rb_f_caller_locations, -1);
|
rb_define_global_function("caller_locations", rb_f_caller_locations, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* debugger API */
|
||||||
|
|
||||||
|
#if defined __GNUC__ && __GNUC__ >= 4
|
||||||
|
#pragma GCC visibility push(default)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __GNUC__ && __GNUC__ >= 4
|
||||||
|
#pragma GCC visibility pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct rb_debug_inspector_struct {
|
||||||
|
rb_thread_t *th;
|
||||||
|
rb_control_frame_t *cfp;
|
||||||
|
VALUE backtrace;
|
||||||
|
VALUE contexts; /* [[klass, binding, iseq, cfp], ...] */
|
||||||
|
int backtrace_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct collect_caller_bindings_data {
|
||||||
|
rb_thread_t *th;
|
||||||
|
VALUE ary;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
collect_caller_bindings_init(void *arg, size_t size)
|
||||||
|
{
|
||||||
|
/* */
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
rb_ary_push(data->ary,
|
||||||
|
rb_ary_new3(4,
|
||||||
|
cfp->klass,
|
||||||
|
rb_binding_new_with_cfp(data->th, cfp),
|
||||||
|
cfp->iseq ? cfp->iseq->self : Qnil,
|
||||||
|
GC_GUARDED_PTR(cfp)));
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
rb_ary_push(data->ary, rb_ary_new3(2, cfp->klass, Qnil));
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
collect_caller_bindings(rb_thread_t *th)
|
||||||
|
{
|
||||||
|
struct collect_caller_bindings_data data;
|
||||||
|
data.ary = rb_ary_new();
|
||||||
|
data.th = th;
|
||||||
|
backtrace_each(th,
|
||||||
|
collect_caller_bindings_init,
|
||||||
|
collect_caller_bindings_iseq,
|
||||||
|
collect_caller_bindings_cfunc,
|
||||||
|
&data);
|
||||||
|
return rb_ary_reverse(data.ary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that the passed `rb_debug_inspector_t' will be disabled
|
||||||
|
* after `rb_debug_inspector_open'.
|
||||||
|
*/
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data)
|
||||||
|
{
|
||||||
|
rb_debug_inspector_t dbg_context;
|
||||||
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
int state;
|
||||||
|
VALUE result;
|
||||||
|
|
||||||
|
dbg_context.th = th;
|
||||||
|
dbg_context.cfp = dbg_context.th->cfp;
|
||||||
|
dbg_context.backtrace = vm_backtrace_location_ary(th, 0, 0);
|
||||||
|
dbg_context.backtrace_size = RARRAY_LEN(dbg_context.backtrace);
|
||||||
|
dbg_context.contexts = collect_caller_bindings(th);
|
||||||
|
|
||||||
|
TH_PUSH_TAG(th);
|
||||||
|
if ((state = EXEC_TAG()) == 0) {
|
||||||
|
result = (*func)(&dbg_context, data);
|
||||||
|
}
|
||||||
|
TH_POP_TAG();
|
||||||
|
|
||||||
|
/* invalidate bindings? */
|
||||||
|
|
||||||
|
|
||||||
|
if (state) {
|
||||||
|
JUMP_TAG(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
frame_get(const rb_debug_inspector_t *dc, int index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= dc->backtrace_size) {
|
||||||
|
rb_raise(rb_eArgError, "no such frame");
|
||||||
|
}
|
||||||
|
return rb_ary_entry(dc->contexts, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, int index)
|
||||||
|
{
|
||||||
|
VALUE frame = frame_get(dc, index);
|
||||||
|
return rb_ary_entry(frame, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, int index)
|
||||||
|
{
|
||||||
|
VALUE frame = frame_get(dc, index);
|
||||||
|
return rb_ary_entry(frame, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, int index)
|
||||||
|
{
|
||||||
|
VALUE frame = frame_get(dc, index);
|
||||||
|
return rb_ary_entry(frame, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc)
|
||||||
|
{
|
||||||
|
return dc->backtrace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -793,6 +793,7 @@ VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc,
|
|||||||
int argc, const VALUE *argv, const rb_block_t *blockptr);
|
int argc, const VALUE *argv, const rb_block_t *blockptr);
|
||||||
VALUE rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass);
|
VALUE rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass);
|
||||||
VALUE rb_vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp);
|
VALUE rb_vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp);
|
||||||
|
VALUE rb_binding_new_with_cfp(rb_thread_t *th, const rb_control_frame_t *src_cfp);
|
||||||
void rb_vm_inc_const_missing_count(void);
|
void rb_vm_inc_const_missing_count(void);
|
||||||
void rb_vm_gvl_destroy(rb_vm_t *vm);
|
void rb_vm_gvl_destroy(rb_vm_t *vm);
|
||||||
VALUE rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc,
|
VALUE rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc,
|
||||||
@ -808,7 +809,7 @@ void rb_thread_wakeup_timer_thread(void);
|
|||||||
|
|
||||||
int ruby_thread_has_gvl_p(void);
|
int ruby_thread_has_gvl_p(void);
|
||||||
typedef int rb_backtrace_iter_func(void *, VALUE, int, VALUE);
|
typedef int rb_backtrace_iter_func(void *, VALUE, int, VALUE);
|
||||||
rb_control_frame_t *rb_vm_get_ruby_level_next_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
|
rb_control_frame_t *rb_vm_get_ruby_level_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp);
|
||||||
int rb_vm_get_sourceline(const rb_control_frame_t *);
|
int rb_vm_get_sourceline(const rb_control_frame_t *);
|
||||||
VALUE rb_name_err_mesg_new(VALUE obj, VALUE mesg, VALUE recv, VALUE method);
|
VALUE rb_name_err_mesg_new(VALUE obj, VALUE mesg, VALUE recv, VALUE method);
|
||||||
void rb_vm_stack_to_heap(rb_thread_t *th);
|
void rb_vm_stack_to_heap(rb_thread_t *th);
|
||||||
|
@ -644,9 +644,7 @@ rb_tracearg_event(rb_trace_arg_t *trace_arg)
|
|||||||
return ID2SYM(get_event_id(trace_arg->event));
|
return ID2SYM(get_event_id(trace_arg->event));
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_control_frame_t *rb_vm_get_ruby_level_next_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
|
|
||||||
int rb_vm_control_frame_id_and_class(rb_control_frame_t *cfp, ID *idp, VALUE *klassp);
|
int rb_vm_control_frame_id_and_class(rb_control_frame_t *cfp, ID *idp, VALUE *klassp);
|
||||||
VALUE rb_binding_new_with_cfp(rb_thread_t *th, rb_control_frame_t *src_cfp);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_path_and_lineno(rb_trace_arg_t *trace_arg)
|
fill_path_and_lineno(rb_trace_arg_t *trace_arg)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user