Created
April 22, 2019 14:13
-
-
Save ujihisa/da58a98a909a7a1be1db5e2050ec0552 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ d | |
diff --git a/vm_backtrace.c b/vm_backtrace.c | |
index bb01983a7c..de7b961174 100644 | |
--- a/vm_backtrace.c | |
+++ b/vm_backtrace.c | |
@@ -47,6 +47,28 @@ calc_lineno(const rb_iseq_t *iseq, const VALUE *pc) | |
return rb_iseq_line_no(iseq, pos); | |
} | |
+inline static int | |
+calc_column(const rb_iseq_t *iseq, const VALUE *pc) | |
+{ | |
+ size_t pos = (size_t)(pc - iseq->body->iseq_encoded); | |
+ if (LIKELY(pos)) { | |
+ /* use pos-1 because PC points next instruction at the beginning of instruction */ | |
+ pos--; | |
+ } | |
+#if VMDEBUG && defined(HAVE_BUILTIN___BUILTIN_TRAP) | |
+ else { | |
+ /* SDR() is not possible; that causes infinite loop. */ | |
+ rb_print_backtrace(); | |
+ __builtin_trap(); | |
+ } | |
+#endif | |
+ int beg_pos_lineno, beg_pos_column, end_pos_lineno, end_pos_column; | |
+ const rb_code_location_t *loc = &iseq->body->location.code_location; | |
+ printf("\n(%d, %d, %d, %d)\n", loc->beg_pos.lineno, loc->beg_pos.column, loc->end_pos.lineno, loc->end_pos.column); | |
+ rb_iseq_code_location(iseq, &beg_pos_lineno, &beg_pos_column, &end_pos_lineno, &end_pos_column); | |
+ return beg_pos_lineno; | |
+} | |
+ | |
int | |
rb_vm_get_sourceline(const rb_control_frame_t *cfp) | |
{ | |
@@ -80,6 +102,10 @@ typedef struct rb_backtrace_location_struct { | |
const VALUE *pc; | |
int lineno; | |
} lineno; | |
+ union { | |
+ const VALUE *pc; | |
+ int column; | |
+ } column; | |
} iseq; | |
struct { | |
ID mid; | |
@@ -156,6 +182,27 @@ location_lineno(rb_backtrace_location_t *loc) | |
} | |
} | |
+static int | |
+location_column(rb_backtrace_location_t *loc) | |
+{ | |
+ switch (loc->type) { | |
+ case LOCATION_TYPE_ISEQ: | |
+ loc->type = LOCATION_TYPE_ISEQ_CALCED; | |
+ return (loc->body.iseq.column.column = calc_column(loc->body.iseq.iseq, loc->body.iseq.column.pc)); | |
+ case LOCATION_TYPE_ISEQ_CALCED: | |
+ return loc->body.iseq.column.column; | |
+ case LOCATION_TYPE_CFUNC: | |
+ if (loc->body.cfunc.prev_loc) { | |
+ return location_column(loc->body.cfunc.prev_loc); | |
+ } | |
+ return 0; | |
+ default: | |
+ rb_bug("location_column: unreachable"); | |
+ UNREACHABLE; | |
+ } | |
+} | |
+ | |
+ | |
/* | |
* Returns the line number of this frame. | |
* | |
@@ -170,6 +217,20 @@ location_lineno_m(VALUE self) | |
return INT2FIX(location_lineno(location_ptr(self))); | |
} | |
+/* | |
+ * Returns the column number of this frame. | |
+ * | |
+ * For example, using +caller_locations.rb+ from Thread::Backtrace::Location | |
+ * | |
+ * loc = c(0..1).first | |
+ * loc.column #=> 2 | |
+ */ | |
+static VALUE | |
+location_column_m(VALUE self) | |
+{ | |
+ return INT2FIX(location_column(location_ptr(self))); | |
+} | |
+ | |
static VALUE | |
location_label(rb_backtrace_location_t *loc) | |
{ | |
@@ -517,6 +578,7 @@ bt_iter_iseq(void *ptr, const rb_control_frame_t *cfp) | |
loc->type = LOCATION_TYPE_ISEQ; | |
loc->body.iseq.iseq = iseq; | |
loc->body.iseq.lineno.pc = pc; | |
+ loc->body.iseq.column.pc = pc; | |
arg->prev_loc = loc; | |
} | |
@@ -1078,6 +1140,7 @@ Init_vm_backtrace(void) | |
rb_undef_alloc_func(rb_cBacktraceLocation); | |
rb_undef_method(CLASS_OF(rb_cBacktraceLocation), "new"); | |
rb_define_method(rb_cBacktraceLocation, "lineno", location_lineno_m, 0); | |
+ rb_define_method(rb_cBacktraceLocation, "column", location_column_m, 0); | |
rb_define_method(rb_cBacktraceLocation, "label", location_label_m, 0); | |
rb_define_method(rb_cBacktraceLocation, "base_label", location_base_label_m, 0); | |
rb_define_method(rb_cBacktraceLocation, "path", location_path_m, 0); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment