ext/byebug/byebug.c in byebug-1.3.1 vs ext/byebug/byebug.c in byebug-1.4.0

- old
+ new

@@ -5,24 +5,23 @@ static VALUE tracing = Qfalse; static VALUE post_mortem = Qfalse; static VALUE debug = Qfalse; -static VALUE context; -static VALUE catchpoints; -static VALUE breakpoints; +static VALUE context = Qnil; +static VALUE catchpoints = Qnil; +static VALUE breakpoints = Qnil; -static VALUE tpLine; -static VALUE tpCall; -static VALUE tpCCall; -static VALUE tpReturn; -static VALUE tpCReturn; -static VALUE tpRaise; +static VALUE tpLine = Qnil; +static VALUE tpCall = Qnil; +static VALUE tpCCall = Qnil; +static VALUE tpReturn = Qnil; +static VALUE tpCReturn = Qnil; +static VALUE tpRaise = Qnil; static VALUE -tp_inspect(VALUE trace_point) { - rb_trace_arg_t *trace_arg = rb_tracearg_from_tracepoint(trace_point); +tp_inspect(rb_trace_arg_t *trace_arg) { if (trace_arg) { VALUE event = rb_tracearg_event(trace_arg); if (ID2SYM(rb_intern("line")) == event || ID2SYM(rb_intern("specified_line")) == event) { @@ -53,238 +52,287 @@ static VALUE Byebug_context(VALUE self) { if (context == Qnil) { - context = Context_create(); + context = context_create(); } return context; } static void -cleanup(debug_context_t *context) +cleanup(debug_context_t *dc) { - context->stop_reason = CTX_STOP_NONE; + dc->stop_reason = CTX_STOP_NONE; } -static int -check_start_processing(debug_context_t *context) +static void +save_current_position(debug_context_t *dc, VALUE file, VALUE line) { - /* ignore a skipped section of code */ - if(CTX_FL_TEST(context, CTX_FL_SKIPPED)) { - cleanup(context); - return 0; - } - return 1; + dc->last_file = file; + dc->last_line = line; + CTX_FL_UNSET(dc, CTX_FL_ENABLE_BKPT); + CTX_FL_UNSET(dc, CTX_FL_FORCE_MOVE); } -static inline void -load_frame_info(VALUE trace_point, VALUE *path, VALUE *lineno, VALUE *method_id, - VALUE *defined_class, VALUE *binding, - VALUE *self) +static VALUE +call_at(VALUE context_obj, debug_context_t *dc, ID mid, int argc, VALUE a0, + VALUE a1) { - rb_trace_point_t *tp; + struct call_with_inspection_data cwi; + VALUE argv[2]; - tp = rb_tracearg_from_tracepoint(trace_point); + argv[0] = a0; + argv[1] = a1; - *path = rb_tracearg_path(tp); - *lineno = rb_tracearg_lineno(tp); - *binding = rb_tracearg_binding(tp); - *self = rb_tracearg_self(tp); - *method_id = rb_tracearg_method_id(tp); - *defined_class = rb_tracearg_defined_class(tp); + cwi.dc = dc; + cwi.context_obj = context_obj; + cwi.id = mid; + cwi.argc = argc; + cwi.argv = &argv[0]; + + return call_with_debug_inspector(&cwi); } +static VALUE +call_at_line(VALUE context_obj, debug_context_t *dc, VALUE file, VALUE line) +{ + save_current_position(dc, file, line); + return call_at(context_obj, dc, rb_intern("at_line"), 2, file, line); +} + +static VALUE +call_at_tracing(VALUE context_obj, debug_context_t *dc, VALUE file, VALUE line) +{ + return call_at(context_obj, dc, rb_intern("at_tracing"), 2, file, line); +} + +static VALUE +call_at_breakpoint(VALUE context_obj, debug_context_t *dc, VALUE breakpoint) +{ + dc->stop_reason = CTX_STOP_BREAKPOINT; + return call_at(context_obj, dc, rb_intern("at_breakpoint"), 1, breakpoint, 0); +} + +static VALUE +call_at_catchpoint(VALUE context_obj, debug_context_t *dc, VALUE exp) +{ + dc->stop_reason = CTX_STOP_CATCHPOINT; + return call_at(context_obj, dc, rb_intern("at_catchpoint"), 1, exp, 0); +} + static void -call_at_line(debug_context_t *context, VALUE context_obj, - VALUE path, VALUE lineno) +call_at_line_check(VALUE context_obj, debug_context_t *dc, + VALUE breakpoint, VALUE file, VALUE line) { - CTX_FL_UNSET(context, CTX_FL_ENABLE_BKPT); - CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE); - context->last_file = RSTRING_PTR(path); - context->last_line = FIX2INT(lineno); - rb_funcall(context_obj, rb_intern("at_line"), 2, path, lineno); + dc->stop_reason = CTX_STOP_STEP; + + if (breakpoint != Qnil) + call_at_breakpoint(context_obj, dc, breakpoint); + + reset_stepping_stop_points(dc); + call_at_line(context_obj, dc, file, line); } -#define EVENT_SETUP \ - VALUE path, lineno, method_id, defined_class, binding, self; \ - VALUE context_obj; \ - debug_context_t *context; \ - context_obj = Byebug_context(mByebug); \ - Data_Get_Struct(context_obj, debug_context_t, context); \ - if (!check_start_processing(context)) return; \ - load_frame_info(trace_point, &path, &lineno, &method_id, &defined_class, \ - &binding, &self); \ - if (debug == Qtrue) \ - printf("%s (stack_size: %d)\n", \ - RSTRING_PTR(tp_inspect(trace_point)), context->stack_size); \ +#define EVENT_SETUP \ + rb_trace_arg_t *trace_arg = rb_tracearg_from_tracepoint(trace_point); \ + VALUE context_obj; \ + debug_context_t *dc; \ + context_obj = Byebug_context(mByebug); \ + Data_Get_Struct(context_obj, debug_context_t, dc); \ + if (debug == Qtrue) \ + printf("%s (stack_size: %d)\n", \ + RSTRING_PTR(tp_inspect(trace_arg)), dc->stack_size); \ +#define EVENT_COMMON() \ + if (trace_common(trace_arg, dc) == 0) { return; } + +static int +trace_common(rb_trace_arg_t *trace_arg, debug_context_t *dc) +{ + /* ignore a skipped section of code */ + if (CTX_FL_TEST(dc, CTX_FL_SKIPPED)) + { + cleanup(dc); + return 0; + } + + /* Many events per line, but only *one* breakpoint */ + if (dc->last_line != rb_tracearg_lineno(trace_arg) || + dc->last_file != rb_tracearg_path(trace_arg)) + { + CTX_FL_SET(dc, CTX_FL_ENABLE_BKPT); + } + + return 1; +} + static void process_line_event(VALUE trace_point, void *data) { EVENT_SETUP; - VALUE breakpoint; + VALUE breakpoint = Qnil; + VALUE file = rb_tracearg_path(trace_arg); + VALUE line = rb_tracearg_lineno(trace_arg); + VALUE binding = rb_tracearg_binding(trace_arg); int moved = 0; - if (context->stack_size == 0) - push_frame(context, RSTRING_PTR(path), FIX2INT(lineno), method_id, - defined_class, binding, self); - else - update_frame(context->stack, RSTRING_PTR(path), FIX2INT(lineno), method_id, - defined_class, binding, self); + EVENT_COMMON(); - if (context->last_line != FIX2INT(lineno) || context->last_file == NULL || - strcmp(context->last_file, RSTRING_PTR(path))) + if (dc->stack_size == 0) dc->stack_size++; + + if (dc->last_line != rb_tracearg_lineno(trace_arg) || + dc->last_file != rb_tracearg_path(trace_arg)) { - CTX_FL_SET(context, CTX_FL_ENABLE_BKPT); moved = 1; } if (RTEST(tracing)) - rb_funcall(context_obj, rb_intern("at_tracing"), 2, path, lineno); + call_at_tracing(context_obj, dc, file, line); - if (context->dest_frame == -1 || context->stack_size == context->dest_frame) + if (moved || !CTX_FL_TEST(dc, CTX_FL_FORCE_MOVE)) { - if (moved || !CTX_FL_TEST(context, CTX_FL_FORCE_MOVE)) + dc->steps = dc->steps <= 0 ? -1 : dc->steps - 1; + if (dc->stack_size <= dc->dest_frame) { - context->steps = context->steps <= 0 ? -1 : context->steps - 1; - context->lines = context->lines <= 0 ? -1 : context->lines - 1; + dc->lines = dc->lines <= 0 ? -1 : dc->lines - 1; + dc->dest_frame = dc->stack_size; } } - else if (context->stack_size < context->dest_frame) - { - context->steps = 0; - } - if (context->steps == 0 || context->lines == 0) + if (dc->steps == 0 || dc->lines == 0 || + (CTX_FL_TEST(dc, CTX_FL_ENABLE_BKPT) && + (!NIL_P( + breakpoint = find_breakpoint_by_pos(breakpoints, file, line, binding))))) { - context->stop_reason = CTX_STOP_STEP; - reset_stepping_stop_points(context); - call_at_line(context, context_obj, path, lineno); + call_at_line_check(context_obj, dc, breakpoint, file, line); } - else if (CTX_FL_TEST(context, CTX_FL_ENABLE_BKPT)) - { - breakpoint = find_breakpoint_by_pos(breakpoints, path, lineno, binding); - if (breakpoint != Qnil) - { - context->stop_reason = CTX_STOP_BREAKPOINT; - reset_stepping_stop_points(context); - rb_funcall(context_obj, rb_intern("at_breakpoint"), 1, breakpoint); - call_at_line(context, context_obj, path, lineno); - } - } - cleanup(context); + cleanup(dc); } static void process_c_return_event(VALUE trace_point, void *data) { EVENT_SETUP; + if (dc->stack_size > 0) dc->stack_size--; + EVENT_COMMON(); - pop_frame(context); - - cleanup(context); + cleanup(dc); } static void process_return_event(VALUE trace_point, void *data) { EVENT_SETUP; + if (dc->stack_size > 0) dc->stack_size--; + EVENT_COMMON(); - if (context->stack_size == context->stop_frame) + if (dc->stack_size + 1 == dc->stop_frame) { - context->steps = 1; - context->stop_frame = -1; + dc->steps = 1; + dc->stop_frame = -1; } - pop_frame(context); - cleanup(context); + cleanup(dc); } static void process_c_call_event(VALUE trace_point, void *data) { EVENT_SETUP; + dc->stack_size++; + EVENT_COMMON(); - push_frame(context, RSTRING_PTR(path), FIX2INT(lineno), method_id, - defined_class, binding, self); - cleanup(context); + cleanup(dc); } static void process_call_event(VALUE trace_point, void *data) { EVENT_SETUP; - VALUE breakpoint; + dc->stack_size++; + EVENT_COMMON(); - push_frame(context, RSTRING_PTR(path), FIX2INT(lineno), method_id, - defined_class, binding, self); + VALUE breakpoint = Qnil; + VALUE klass = rb_tracearg_defined_class(trace_arg); + VALUE mid = SYM2ID(rb_tracearg_method_id(trace_arg)); + VALUE binding = rb_tracearg_binding(trace_arg); + VALUE self = rb_tracearg_self(trace_arg); + VALUE file = rb_tracearg_path(trace_arg); + VALUE line = rb_tracearg_lineno(trace_arg); - breakpoint = find_breakpoint_by_method(breakpoints, defined_class, - SYM2ID(method_id), - binding, self); + breakpoint = + find_breakpoint_by_method(breakpoints, klass, mid, binding, self); if (breakpoint != Qnil) { - context->stop_reason = CTX_STOP_BREAKPOINT; - rb_funcall(context_obj, rb_intern("at_breakpoint"), 1, breakpoint); - call_at_line(context, context_obj, path, lineno); + call_at_breakpoint(context_obj, dc, breakpoint); + call_at_line(context_obj, dc, file, line); } - cleanup(context); + cleanup(dc); } static void process_raise_event(VALUE trace_point, void *data) { - EVENT_SETUP; + EVENT_SETUP VALUE expn_class, aclass; VALUE err = rb_errinfo(); VALUE ancestors; int i; + debug_context_t *new_dc; - update_frame(context->stack, RSTRING_PTR(path), FIX2INT(lineno), method_id, - defined_class, binding, self); + EVENT_COMMON(); - if (post_mortem == Qtrue && self) + VALUE binding = rb_tracearg_binding(trace_arg); + VALUE path = rb_tracearg_path(trace_arg); + VALUE lineno = rb_tracearg_lineno(trace_arg); + + if (post_mortem == Qtrue) { - VALUE binding = rb_binding_new(); - rb_ivar_set(rb_errinfo(), rb_intern("@__debug_file"), path); - rb_ivar_set(rb_errinfo(), rb_intern("@__debug_line"), lineno); - rb_ivar_set(rb_errinfo(), rb_intern("@__debug_binding"), binding); - rb_ivar_set(rb_errinfo(), rb_intern("@__debug_context"), Context_dup(context)); + context = context_dup(dc); + rb_ivar_set(err, rb_intern("@__debug_file") , path); + rb_ivar_set(err, rb_intern("@__debug_line") , lineno); + rb_ivar_set(err, rb_intern("@__debug_binding"), binding); + rb_ivar_set(err, rb_intern("@__debug_context"), context); + + Data_Get_Struct(context, debug_context_t, new_dc); + rb_debug_inspector_open(context_backtrace_set, (void *)new_dc); } expn_class = rb_obj_class(err); - if (catchpoints == Qnil || context->stack_size == 0 || - CTX_FL_TEST(context, CTX_FL_CATCHING) || - RHASH_TBL(catchpoints)->num_entries == 0) { - cleanup(context); + if (catchpoints == Qnil || dc->stack_size == 0 || + CTX_FL_TEST(dc, CTX_FL_CATCHING) || + RHASH_TBL(catchpoints)->num_entries == 0) + { + cleanup(dc); return; } ancestors = rb_mod_ancestors(expn_class); - for (i = 0; i < RARRAY_LEN(ancestors); i++) { + for (i = 0; i < RARRAY_LEN(ancestors); i++) + { VALUE mod_name; VALUE hit_count; aclass = rb_ary_entry(ancestors, i); mod_name = rb_mod_name(aclass); hit_count = rb_hash_aref(catchpoints, mod_name); - if (hit_count != Qnil) { - /* increment exception */ + /* increment exception */ + if (hit_count != Qnil) + { rb_hash_aset(catchpoints, mod_name, INT2FIX(FIX2INT(hit_count) + 1)); - context->stop_reason = CTX_STOP_CATCHPOINT; - rb_funcall(context_obj, rb_intern("at_catchpoint"), 1, rb_errinfo()); - call_at_line(context, context_obj, path, lineno); + call_at_catchpoint(context_obj, dc, err); + call_at_line(context_obj, dc, path, lineno); break; } } - cleanup(context); + cleanup(dc); } static VALUE Byebug_setup_tracepoints(VALUE self) { @@ -328,38 +376,21 @@ } static VALUE Byebug_remove_tracepoints(VALUE self) { + rb_tracepoint_disable(tpRaise); + rb_tracepoint_disable(tpCReturn); + rb_tracepoint_disable(tpReturn); + rb_tracepoint_disable(tpCCall); + rb_tracepoint_disable(tpCall); + rb_tracepoint_disable(tpLine); + context = Qnil; breakpoints = Qnil; catchpoints = Qnil; - if (tpLine != Qnil) { - rb_tracepoint_disable(tpLine); - tpLine = Qnil; - } - if (tpCall != Qnil) { - rb_tracepoint_disable(tpCall); - tpCall = Qnil; - } - if (tpCCall != Qnil) { - rb_tracepoint_disable(tpCCall); - tpCCall = Qnil; - } - if (tpReturn != Qnil) { - rb_tracepoint_disable(tpReturn); - tpReturn = Qnil; - } - if (tpCReturn != Qnil) { - rb_tracepoint_disable(tpCReturn); - tpCReturn = Qnil; - } - if (tpRaise != Qnil) { - rb_tracepoint_disable(tpRaise); - tpRaise = Qnil; - } return Qnil; } #define BYEBUG_STARTED (catchpoints != Qnil) static VALUE @@ -369,77 +400,79 @@ } static VALUE Byebug_stop(VALUE self) { - if (BYEBUG_STARTED) - { - Byebug_remove_tracepoints(self); - return Qfalse; - } - return Qtrue; + if (BYEBUG_STARTED) + { + Byebug_remove_tracepoints(self); + return Qfalse; + } + return Qtrue; } static VALUE Byebug_start(VALUE self) { - VALUE result; + VALUE result; - if (BYEBUG_STARTED) - result = Qfalse; - else - { - Byebug_setup_tracepoints(self); - result = Qtrue; - } + if (BYEBUG_STARTED) + result = Qfalse; + else + { + Byebug_setup_tracepoints(self); + result = Qtrue; + } - if (rb_block_given_p()) - rb_ensure(rb_yield, self, Byebug_stop, self); + if (rb_block_given_p()) + rb_ensure(rb_yield, self, Byebug_stop, self); - return result; + return result; } static VALUE set_current_skipped_status(VALUE status) { VALUE context_obj; - debug_context_t *context; + debug_context_t *dc; context_obj = Byebug_context(mByebug); - Data_Get_Struct(context_obj, debug_context_t, context); + Data_Get_Struct(context_obj, debug_context_t, dc); if (status) - CTX_FL_SET(context, CTX_FL_SKIPPED); + CTX_FL_SET(dc, CTX_FL_SKIPPED); else - CTX_FL_UNSET(context, CTX_FL_SKIPPED); + CTX_FL_UNSET(dc, CTX_FL_SKIPPED); return Qnil; } static VALUE Byebug_load(int argc, VALUE *argv, VALUE self) { VALUE file, stop, context_obj; - debug_context_t *context; + debug_context_t *dc; int state = 0; if (rb_scan_args(argc, argv, "11", &file, &stop) == 1) { stop = Qfalse; } Byebug_start(self); context_obj = Byebug_context(self); - Data_Get_Struct(context_obj, debug_context_t, context); - context->stack_size = 0; - if (RTEST(stop)) context->steps = 1; + Data_Get_Struct(context_obj, debug_context_t, dc); + if (RTEST(stop)) dc->steps = 1; + /* Resetting stack size */ + dc->stack_size = 0; + /* Initializing $0 to the script's path */ ruby_script(RSTRING_PTR(file)); rb_load_protect(file, 0, &state); if (0 != state) { VALUE errinfo = rb_errinfo(); - reset_stepping_stop_points(context); + reset_stepping_stop_points(dc); rb_set_errinfo(Qnil); return errinfo; } /* We should run all at_exit handler's in order to provide, for instance, a