diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-07-06 09:33:53 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-07-06 09:33:53 +0900 |
| commit | 718a9ceb6ee16d5581d99ea6b66624ad98782a32 (patch) | |
| tree | c42c8d792b5ac64bb4ccd4a9b1353e7ea2ac8553 /src/backtrace.c | |
| parent | 542f0f7b161e6bcd551c4fa52a8f71463a17aa3e (diff) | |
| download | mruby-718a9ceb6ee16d5581d99ea6b66624ad98782a32.tar.gz mruby-718a9ceb6ee16d5581d99ea6b66624ad98782a32.zip | |
Reduce allocation size of backtrace arrays.
Diffstat (limited to 'src/backtrace.c')
| -rw-r--r-- | src/backtrace.c | 60 |
1 files changed, 46 insertions, 14 deletions
diff --git a/src/backtrace.c b/src/backtrace.c index d3e8d636f..f04395597 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -93,6 +93,20 @@ print_backtrace(mrb_state *mrb, mrb_value backtrace) } } +static int +packed_bt_len(struct backtrace_location *bt, int n) +{ + int len = 0; + int i; + + for (i=0; i<n; i++) { + if (!bt[i].filename && !bt[i].lineno && !bt[i].method_id) + continue; + len++; + } + return len; +} + static void print_packed_backtrace(mrb_state *mrb, mrb_value packed) { @@ -102,11 +116,10 @@ print_packed_backtrace(mrb_state *mrb, mrb_value packed) int ai = mrb_gc_arena_save(mrb); bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, packed, &bt_type); - if (bt == NULL) { - mrb_raise(mrb, E_RUNTIME_ERROR, "broken backtrace"); - } + if (bt == NULL) return; n = (mrb_int)RDATA(packed)->flags; + if (packed_bt_len(bt, n) == 0) return; fprintf(stream, "trace:\n"); for (i = 0; i<n; i++) { struct backtrace_location *entry = &bt[n-i-1]; @@ -156,14 +169,29 @@ mrb_print_backtrace(mrb_state *mrb) #endif static void +count_backtrace_i(mrb_state *mrb, + int i, + struct backtrace_location *loc, + void *data) +{ + int *lenp = (int*)data; + + if (loc->filename == NULL) return; + (*lenp)++; +} + +static void pack_backtrace_i(mrb_state *mrb, int i, struct backtrace_location *loc, void *data) { - struct backtrace_location *entry = (struct backtrace_location*)data; + struct backtrace_location **pptr = (struct backtrace_location**)data; + struct backtrace_location *ptr = *pptr; - entry[i] = *loc; + if (loc->filename == NULL) return; + *ptr = *loc; + *pptr = ptr+1; } static mrb_value @@ -171,14 +199,17 @@ packed_backtrace(mrb_state *mrb) { struct RData *backtrace; ptrdiff_t ciidx = mrb->c->ci - mrb->c->cibase; - mrb_int len = (ciidx+1)*sizeof(struct backtrace_location); + int len = 0; + int size; void *ptr; - ptr = mrb_malloc(mrb, len); - memset(ptr, 0, len); + each_backtrace(mrb, ciidx, mrb->c->ci->pc, count_backtrace_i, &len); + size = len * sizeof(struct backtrace_location); + ptr = mrb_malloc(mrb, size); + memset(ptr, 0, size); backtrace = mrb_data_object_alloc(mrb, NULL, ptr, &bt_type); - backtrace->flags = (unsigned int)ciidx+1; - each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, ptr); + backtrace->flags = (unsigned int)len; + each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, &ptr); return mrb_obj_value(backtrace); } @@ -200,12 +231,13 @@ mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace) mrb_int n, i; int ai; - if (mrb_nil_p(backtrace)) return mrb_ary_new_capa(mrb, 0); + if (mrb_nil_p(backtrace)) { + empty_backtrace: + return mrb_ary_new_capa(mrb, 0); + } if (mrb_array_p(backtrace)) return backtrace; bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, backtrace, &bt_type); - if (bt == NULL) { - mrb_raise(mrb, E_RUNTIME_ERROR, "broken backtrace"); - } + if (bt == NULL) goto empty_backtrace; n = (mrb_int)RDATA(backtrace)->flags; backtrace = mrb_ary_new_capa(mrb, n); ai = mrb_gc_arena_save(mrb); |
