Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
debug.c
Go to the documentation of this file.
1 #include <string.h>
2 #include "mruby.h"
3 #include "mruby/irep.h"
4 #include "mruby/debug.h"
5 
7 get_file(mrb_irep_debug_info *info, uint32_t pc)
8 {
10  int32_t count;
11 
12  if(pc >= info->pc_count) { return NULL; }
13  // get upper bound
14  ret = info->files;
15  count = info->flen;
16  while (count > 0) {
17  int32_t step = count / 2;
18  mrb_irep_debug_info_file **it = ret + step;
19  if (!(pc < (*it)->start_pos)) {
20  ret = it + 1;
21  count -= step + 1;
22  } else { count = step; }
23  }
24 
25  --ret;
26 
27  // check returning file exists inside debug info
28  mrb_assert(info->files <= ret && ret < (info->files + info->flen));
29  // check pc is within the range of returning file
30  mrb_assert((*ret)->start_pos <= pc &&
31  pc < (((ret + 1 - info->files) < info->flen)
32  ? (*(ret+1))->start_pos : info->pc_count));
33 
34  return *ret;
35 }
36 
38 select_line_type(const uint16_t *lines, size_t lines_len)
39 {
40  size_t line_count = 0;
41  int prev_line = -1;
42  size_t i;
43  for (i = 0; i < lines_len; ++i) {
44  if (lines[i] != prev_line) {
45  ++line_count;
46  }
47  }
48  return (sizeof(uint16_t) * lines_len) <= (sizeof(mrb_irep_debug_info_line) * line_count)
50 }
51 
52 char const*
53 mrb_debug_get_filename(mrb_irep *irep, uint32_t pc)
54 {
55  if (irep && pc < irep->ilen) {
56  mrb_irep_debug_info_file* f = NULL;
57  if (!irep->debug_info) { return irep->filename; }
58  else if ((f = get_file(irep->debug_info, pc))) {
59  return f->filename;
60  }
61  }
62  return NULL;
63 }
64 
65 int32_t
66 mrb_debug_get_line(mrb_irep *irep, uint32_t pc)
67 {
68  if (irep && pc < irep->ilen) {
69  mrb_irep_debug_info_file* f = NULL;
70  if (!irep->debug_info) {
71  return irep->lines? irep->lines[pc] : -1;
72  }
73  else if ((f = get_file(irep->debug_info, pc))) {
74  switch(f->line_type) {
75  case mrb_debug_line_ary:
76  mrb_assert(f->start_pos <= pc && pc < (f->start_pos + f->line_entry_count));
77  return f->line_ary[pc - f->start_pos];
78 
80  // get upper bound
82  uint32_t count = f->line_entry_count;
83  while (count > 0) {
84  int32_t step = count / 2;
85  mrb_irep_debug_info_line *it = ret + step;
86  if (!(pc < it->start_pos)) {
87  ret = it + 1;
88  count -= step + 1;
89  } else { count = step; }
90  }
91 
92  --ret;
93 
94  // check line entry pointer range
95  mrb_assert(f->line_flat_map <= ret && ret < (f->line_flat_map + f->line_entry_count));
96  // check pc range
97  mrb_assert(ret->start_pos <= pc &&
98  pc < (((ret + 1 - f->line_flat_map) < f->line_entry_count)
99  ? (ret+1)->start_pos : irep->debug_info->pc_count));
100 
101  return ret->line;
102  }
103  }
104  }
105  }
106  return -1;
107 }
108 
111 {
112  static const mrb_irep_debug_info initial = { 0, 0, NULL };
113  mrb_irep_debug_info *ret;
114 
115  mrb_assert(!irep->debug_info);
116  ret = (mrb_irep_debug_info *)mrb_malloc(mrb, sizeof(*ret));
117  *ret = initial;
118  irep->debug_info = ret;
119  return ret;
120 }
121 
124  uint32_t start_pos, uint32_t end_pos)
125 {
126  mrb_irep_debug_info *info;
128  uint32_t file_pc_count;
129  size_t fn_len;
130  size_t len;
131  uint32_t i;
132 
133  if (!irep->debug_info) { return NULL; }
134 
135  mrb_assert(irep->filename);
136  mrb_assert(irep->lines);
137 
138  info = irep->debug_info;
139 
140  if (info->flen > 0 && strcmp(irep->filename, info->files[info->flen - 1]->filename) == 0) {
141  return NULL;
142  }
143 
144  ret = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*ret));
145  info->files =
147  ? mrb_realloc(mrb, info->files, sizeof(mrb_irep_debug_info_file*) * (info->flen + 1))
148  : mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file*));
149  info->files[info->flen++] = ret;
150 
151  file_pc_count = end_pos - start_pos;
152 
153  ret->start_pos = start_pos;
154  info->pc_count = end_pos;
155 
156  fn_len = strlen(irep->filename);
157  ret->filename_sym = mrb_intern2(mrb, irep->filename, fn_len);
158  len = 0;
159  ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len);
160 
161  ret->line_type = select_line_type(irep->lines + start_pos, end_pos - start_pos);
162  ret->line_ptr = NULL;
163 
164  switch(ret->line_type) {
165  case mrb_debug_line_ary:
166  ret->line_entry_count = file_pc_count;
167  ret->line_ary = mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count);
168  for(i = 0; i < file_pc_count; ++i) {
169  ret->line_ary[i] = irep->lines[start_pos + i];
170  }
171  break;
172 
174  uint16_t prev_line = 0;
176  ret->line_flat_map = mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1);
177  ret->line_entry_count = 0;
178  for(i = 0; i < file_pc_count; ++i) {
179  if(irep->lines[start_pos + i] == prev_line) { continue; }
180 
181  ret->line_flat_map = mrb_realloc(
182  mrb, ret->line_flat_map,
183  sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1));
184  m.start_pos = start_pos + i;
185  m.line = irep->lines[start_pos + i];
186  ret->line_flat_map[ret->line_entry_count] = m;
187 
188  // update
189  ++ret->line_entry_count;
190  prev_line = irep->lines[start_pos + i];
191  }
192  } break;
193 
194  default: mrb_assert(0); break;
195  }
196 
197  return ret;
198 }
199 
200 void
202 {
203  uint32_t i;
204 
205  if(!d) { return; }
206 
207  for(i = 0; i < d->flen; ++i) {
208  mrb_assert(d->files[i]);
209  mrb_free(mrb, d->files[i]->line_ptr);
210  mrb_free(mrb, d->files[i]);
211  }
212  mrb_free(mrb, d->files);
213  mrb_free(mrb, d);
214 }