summaryrefslogtreecommitdiffhomepage
path: root/src/debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug.c')
-rw-r--r--src/debug.c217
1 files changed, 123 insertions, 94 deletions
diff --git a/src/debug.c b/src/debug.c
index ea1aa1ddc..e570e8068 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -1,9 +1,9 @@
#include <string.h>
-#include "mruby.h"
-#include "mruby/irep.h"
-#include "mruby/debug.h"
+#include <mruby.h>
+#include <mruby/irep.h>
+#include <mruby/debug.h>
-static mrb_irep_debug_info_file *
+static mrb_irep_debug_info_file*
get_file(mrb_irep_debug_info *info, uint32_t pc)
{
mrb_irep_debug_info_file **ret;
@@ -19,7 +19,8 @@ get_file(mrb_irep_debug_info *info, uint32_t pc)
if (!(pc < (*it)->start_pos)) {
ret = it + 1;
count -= step + 1;
- } else { count = step; }
+ }
+ else { count = step; }
}
--ret;
@@ -34,41 +35,68 @@ get_file(mrb_irep_debug_info *info, uint32_t pc)
return *ret;
}
-static mrb_debug_line_type
-select_line_type(const uint16_t *lines, size_t lines_len)
+size_t
+mrb_packed_int_len(uint32_t num)
{
- size_t line_count = 0;
- int prev_line = -1;
- size_t i;
- for (i = 0; i < lines_len; ++i) {
- if (lines[i] != prev_line) {
- ++line_count;
- }
- }
- return (sizeof(uint16_t) * lines_len) <= (sizeof(mrb_irep_debug_info_line) * line_count)
- ? mrb_debug_line_ary : mrb_debug_line_flat_map;
+ size_t llen = 0;
+
+ do {
+ llen++;
+ } while (num >>= 7);
+ return llen;
}
-char const*
-mrb_debug_get_filename(mrb_irep *irep, uint32_t pc)
+size_t
+mrb_packed_int_encode(uint32_t num, uint8_t *p, uint8_t *pend)
+{
+ size_t llen = 0;
+
+ do {
+ uint8_t byte = num & 0x7f;
+ num >>= 7;
+ if (num != 0) byte |= 0x80;
+ if (p < pend) *p++ = byte;
+ llen++;
+ } while (num != 0);
+
+ return llen;
+}
+
+uint32_t
+mrb_packed_int_decode(uint8_t *p, uint8_t **newpos)
+{
+ size_t i = 0, shift = 0;
+ uint32_t n = 0;
+
+ do {
+ n |= ((uint32_t)(p[i] & 0x7f)) << shift;
+ i++;
+ shift += 7;
+ } while (shift < sizeof(uint32_t) * 8 && (p[i - 1] & 0x80));
+ if (newpos) *newpos = p + i;
+ return n;
+}
+
+MRB_API char const*
+mrb_debug_get_filename(mrb_state *mrb, const mrb_irep *irep, uint32_t pc)
{
if (irep && pc < irep->ilen) {
mrb_irep_debug_info_file* f = NULL;
- if (!irep->debug_info) { return irep->filename; }
+ if (!irep->debug_info) return NULL;
else if ((f = get_file(irep->debug_info, pc))) {
- return f->filename;
+ return mrb_sym_name_len(mrb, f->filename_sym, NULL);
}
}
return NULL;
}
-int32_t
-mrb_debug_get_line(mrb_irep *irep, uint32_t pc)
+MRB_API int32_t
+mrb_debug_get_line(mrb_state *mrb, const mrb_irep *irep, uint32_t pc)
{
if (irep && pc < irep->ilen) {
mrb_irep_debug_info_file* f = NULL;
if (!irep->debug_info) {
- return irep->lines? irep->lines[pc] : -1;
+ return -1;
}
else if ((f = get_file(irep->debug_info, pc))) {
switch (f->line_type) {
@@ -86,7 +114,8 @@ mrb_debug_get_line(mrb_irep *irep, uint32_t pc)
if (!(pc < it->start_pos)) {
ret = it + 1;
count -= step + 1;
- } else { count = step; }
+ }
+ else { count = step; }
}
--ret;
@@ -100,13 +129,26 @@ mrb_debug_get_line(mrb_irep *irep, uint32_t pc)
return ret->line;
}
+
+ case mrb_debug_line_packed_map: {
+ uint8_t *p = f->lines.packed_map;
+ uint8_t *pend = p + f->line_entry_count;
+ uint32_t pos = 0, line = 0, line_diff;
+ while (p < pend) {
+ pos += mrb_packed_int_decode(p, &p);
+ line_diff = mrb_packed_int_decode(p, &p);
+ if (pc < pos) break;
+ line += line_diff;
+ }
+ return line;
+ }
}
}
}
return -1;
}
-mrb_irep_debug_info *
+MRB_API mrb_irep_debug_info*
mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep)
{
static const mrb_irep_debug_info initial = { 0, 0, NULL };
@@ -119,97 +161,84 @@ mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep)
return ret;
}
-mrb_irep_debug_info_file *
-mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep,
+MRB_API mrb_irep_debug_info_file*
+mrb_debug_info_append_file(mrb_state *mrb, mrb_irep_debug_info *d,
+ const char *filename, uint16_t *lines,
uint32_t start_pos, uint32_t end_pos)
{
- mrb_irep_debug_info *info;
- mrb_irep_debug_info_file *ret;
+ mrb_irep_debug_info_file *f;
uint32_t file_pc_count;
size_t fn_len;
- mrb_int len;
uint32_t i;
- if (!irep->debug_info) { return NULL; }
+ if (!d) return NULL;
+ if (start_pos == end_pos) return NULL;
- mrb_assert(irep->filename);
- mrb_assert(irep->lines);
+ mrb_assert(filename);
+ mrb_assert(lines);
- info = irep->debug_info;
-
- if (info->flen > 0 && strcmp(irep->filename, info->files[info->flen - 1]->filename) == 0) {
- return NULL;
+ if (d->flen > 0) {
+ const char *fn = mrb_sym_name_len(mrb, d->files[d->flen - 1]->filename_sym, NULL);
+ if (strcmp(filename, fn) == 0)
+ return NULL;
}
- ret = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*ret));
- info->files =
- (mrb_irep_debug_info_file**)(
- info->files
- ? mrb_realloc(mrb, info->files, sizeof(mrb_irep_debug_info_file*) * (info->flen + 1))
- : mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file*)));
- info->files[info->flen++] = ret;
+ f = (mrb_irep_debug_info_file*)mrb_malloc(mrb, sizeof(*f));
+ d->files = (mrb_irep_debug_info_file**)mrb_realloc(mrb, d->files, sizeof(mrb_irep_debug_info_file*) * (d->flen + 1));
+ d->files[d->flen++] = f;
file_pc_count = end_pos - start_pos;
- ret->start_pos = start_pos;
- info->pc_count = end_pos;
-
- fn_len = strlen(irep->filename);
- ret->filename_sym = mrb_intern(mrb, irep->filename, fn_len);
- len = 0;
- ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len);
-
- ret->line_type = select_line_type(irep->lines + start_pos, end_pos - start_pos);
- ret->lines.ptr = NULL;
-
- switch (ret->line_type) {
- case mrb_debug_line_ary:
- ret->line_entry_count = file_pc_count;
- ret->lines.ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count);
- for (i = 0; i < file_pc_count; ++i) {
- ret->lines.ary[i] = irep->lines[start_pos + i];
- }
- break;
-
- case mrb_debug_line_flat_map: {
- uint16_t prev_line = 0;
- mrb_irep_debug_info_line m;
- ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1);
- ret->line_entry_count = 0;
- for (i = 0; i < file_pc_count; ++i) {
- if (irep->lines[start_pos + i] == prev_line) { continue; }
-
- ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_realloc(
- mrb, ret->lines.flat_map,
- sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1));
- m.start_pos = start_pos + i;
- m.line = irep->lines[start_pos + i];
- ret->lines.flat_map[ret->line_entry_count] = m;
-
- /* update */
- ++ret->line_entry_count;
- prev_line = irep->lines[start_pos + i];
- }
- } break;
-
- default: mrb_assert(0); break;
+ f->start_pos = start_pos;
+ d->pc_count = end_pos;
+
+ fn_len = strlen(filename);
+ f->filename_sym = mrb_intern(mrb, filename, fn_len);
+ f->line_type = mrb_debug_line_packed_map;
+ f->lines.ptr = NULL;
+
+ uint16_t prev_line = 0;
+ uint32_t prev_pc = 0;
+ size_t packed_size = 0;
+ uint8_t *p, *pend;
+
+ for (i = 0; i < file_pc_count; ++i) {
+ if (lines[start_pos + i] == prev_line) continue;
+ packed_size += mrb_packed_int_len(start_pos+i-prev_pc);
+ prev_pc = start_pos+i;
+ packed_size += mrb_packed_int_len(lines[start_pos+i]-prev_line);
+ prev_line = lines[start_pos + i];
+ }
+ p = f->lines.packed_map = (uint8_t*)mrb_malloc(mrb, packed_size);
+ pend = p + packed_size;
+ prev_line = 0; prev_pc = 0;
+ for (i = 0; i < file_pc_count; ++i) {
+ if (lines[start_pos + i] == prev_line) continue;
+ p += mrb_packed_int_encode(start_pos+i-prev_pc, p, pend);
+ prev_pc = start_pos + i;
+ p += mrb_packed_int_encode(lines[start_pos + i]-prev_line, p, pend);
+ prev_line = lines[start_pos + i];
}
+ f->line_entry_count = (uint32_t)packed_size;
- return ret;
+ return f;
}
-void
+MRB_API void
mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d)
{
uint32_t i;
if (!d) { return; }
- for (i = 0; i < d->flen; ++i) {
- mrb_assert(d->files[i]);
- mrb_free(mrb, d->files[i]->lines.ptr);
- mrb_free(mrb, d->files[i]);
+ if (d->files) {
+ for (i = 0; i < d->flen; ++i) {
+ if (d->files[i]) {
+ mrb_free(mrb, d->files[i]->lines.ptr);
+ mrb_free(mrb, d->files[i]);
+ }
+ }
+ mrb_free(mrb, d->files);
}
- mrb_free(mrb, d->files);
mrb_free(mrb, d);
}