From 718a9ceb6ee16d5581d99ea6b66624ad98782a32 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 6 Jul 2017 09:33:53 +0900 Subject: Reduce allocation size of backtrace arrays. --- src/backtrace.c | 60 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 14 deletions(-) (limited to 'src/backtrace.c') 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; iflags; + if (packed_bt_len(bt, n) == 0) return; fprintf(stream, "trace:\n"); for (i = 0; ifilename == 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); -- cgit v1.2.3