Skip to content

Commit 39acce4

Browse files
committed
Reduce memory footprint of line refs
Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent 4a6e5a9 commit 39acce4

File tree

3 files changed

+88
-44
lines changed

3 files changed

+88
-44
lines changed

src/libAtomVM/module.c

Lines changed: 77 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ static void module_add_label(Module *mod, int index, const uint8_t *ptr);
5757
static enum ModuleLoadResult module_build_imported_functions_table(Module *this_module, uint8_t *table_data, GlobalContext *glb);
5858
static void module_parse_line_table(Module *mod, const uint8_t *data, size_t len);
5959

60+
struct LineRefOffset
61+
{
62+
struct ListHead head;
63+
unsigned int offset;
64+
};
65+
6066
#define IMPL_CODE_LOADER 1
6167
#include "opcodesswitch.h"
6268
#undef TRACE
@@ -276,7 +282,6 @@ Module *module_new_from_iff_binary(GlobalContext *global, const void *iff_binary
276282
}
277283

278284
module_parse_line_table(mod, beam_file + offsets[LINT] + 8, sizes[LINT]);
279-
list_init(&mod->line_ref_offsets);
280285

281286
if (offsets[LITT]) {
282287
#ifdef WITH_ZLIB
@@ -305,7 +310,40 @@ Module *module_new_from_iff_binary(GlobalContext *global, const void *iff_binary
305310
mod->free_literals_data = 0;
306311
}
307312

308-
mod->end_instruction_ii = read_core_chunk(mod);
313+
struct ListHead line_refs;
314+
list_init(&line_refs);
315+
mod->end_instruction_ii = read_core_chunk(mod, &line_refs);
316+
317+
// Create the list of offsets if the module has line informations.
318+
if (mod->line_refs_table != NULL) {
319+
// Compute the size of the list
320+
size_t num_offsets = 0;
321+
struct ListHead *item = line_refs.next;
322+
while (item != &line_refs) {
323+
num_offsets++;
324+
item = item->next;
325+
}
326+
mod->line_refs_offsets = malloc(num_offsets * sizeof(unsigned int));
327+
if (IS_NULL_PTR(mod->line_refs_offsets)) {
328+
fprintf(stderr, "Warning: Unable to allocate space for line refs offset, module has %zu offsets. Line information in stacktraces may be missing\n", num_offsets);
329+
} else {
330+
size_t index = 0;
331+
item = line_refs.next;
332+
while (item != &line_refs) {
333+
struct LineRefOffset *offset = CONTAINER_OF(item, struct LineRefOffset, head);
334+
mod->line_refs_offsets[index] = offset->offset;
335+
index++;
336+
item = item->next;
337+
}
338+
mod->line_refs_offsets_count = num_offsets;
339+
}
340+
}
341+
// Empty the list
342+
while (!list_is_empty(&line_refs)) {
343+
struct ListHead *item = line_refs.next;
344+
list_remove(item);
345+
free(item);
346+
}
309347

310348
return mod;
311349
}
@@ -316,6 +354,7 @@ COLD_FUNC void module_destroy(Module *module)
316354
free(module->imported_funcs);
317355
free(module->literals_table);
318356
free(module->local_atoms_to_global_table);
357+
free(module->line_refs_offsets);
319358
if (module->free_literals_data) {
320359
free(module->literals_data);
321360
}
@@ -697,19 +736,28 @@ static void module_parse_line_table(Module *mod, const uint8_t *data, size_t len
697736
}
698737
}
699738

700-
void module_insert_line_ref_offset(Module *mod, int line_ref, int offset)
739+
void module_insert_line_ref_offset(Module *mod, struct ListHead *line_refs, uint32_t line_ref, int offset)
701740
{
702741
if (IS_NULL_PTR(mod->line_refs_table) || line_ref == 0) {
703742
return;
704743
}
705744
struct LineRefOffset *ref_offset = malloc(sizeof(struct LineRefOffset));
706745
if (IS_NULL_PTR(ref_offset)) {
707-
fprintf(stderr, "Warning: Unable to allocate space for line ref offset. Line information in stacktraces may be missing\n");
746+
size_t num_refs = 0;
747+
// Empty the list
748+
while (!list_is_empty(line_refs)) {
749+
struct ListHead *item = line_refs->next;
750+
list_remove(item);
751+
free(item);
752+
num_refs++;
753+
}
754+
fprintf(stderr, "Warning: Unable to allocate space for an additional line ref offset (we had %zu). Line information in stacktraces may be missing\n", num_refs);
755+
// Give up having line numbers for this module.
756+
mod->line_refs_table = NULL;
708757
return;
709758
}
710-
ref_offset->line_ref = line_ref;
711759
ref_offset->offset = offset;
712-
list_append(&mod->line_ref_offsets, &ref_offset->head);
760+
list_append(line_refs, &ref_offset->head);
713761
}
714762

715763
static bool module_find_line_ref(Module *mod, uint16_t line_ref, uint32_t *line, size_t *filename_len, const uint8_t **filename)
@@ -723,30 +771,30 @@ static bool module_find_line_ref(Module *mod, uint16_t line_ref, uint32_t *line,
723771

724772
bool module_find_line(Module *mod, unsigned int offset, uint32_t *line, size_t *filename_len, const uint8_t **filename)
725773
{
726-
int i = 0;
727-
struct LineRefOffset *head = GET_LIST_ENTRY(&mod->line_ref_offsets, struct LineRefOffset, head);
728-
struct ListHead *item;
729-
LIST_FOR_EACH (item, &mod->line_ref_offsets) {
730-
struct LineRefOffset *ref_offset = GET_LIST_ENTRY(item, struct LineRefOffset, head);
731-
732-
if (offset == ref_offset->offset) {
733-
return module_find_line_ref(mod, ref_offset->line_ref, line, filename_len, filename);
734-
} else if (i == 0 && offset < ref_offset->offset) {
774+
size_t i;
775+
unsigned int ref_offset;
776+
uint32_t line_ref;
777+
const uint8_t *ref_pc;
778+
if (IS_NULL_PTR(mod->line_refs_offsets)) {
779+
return false;
780+
}
781+
for (i = 0; i < mod->line_refs_offsets_count; i++) {
782+
ref_offset = mod->line_refs_offsets[i];
783+
if (offset == ref_offset) {
784+
ref_pc = &mod->code->code[ref_offset];
785+
DECODE_LITERAL(line_ref, ref_pc);
786+
return module_find_line_ref(mod, line_ref, line, filename_len, filename);
787+
} else if (i == 0 && offset < ref_offset) {
735788
return false;
736-
} else {
737-
738-
struct LineRefOffset *prev_ref_offset = GET_LIST_ENTRY(ref_offset->head.prev, struct LineRefOffset, head);
739-
if (prev_ref_offset->offset <= offset && offset < ref_offset->offset) {
740-
return module_find_line_ref(mod, prev_ref_offset->line_ref, line, filename_len, filename);
741-
}
742-
743-
struct LineRefOffset *next_ref_offset = GET_LIST_ENTRY(ref_offset->head.next, struct LineRefOffset, head);
744-
if (next_ref_offset == head && ref_offset->offset <= offset) {
745-
return module_find_line_ref(mod, ref_offset->line_ref, line, filename_len, filename);
746-
}
789+
} else if (offset < ref_offset) {
790+
ref_offset = mod->line_refs_offsets[i - 1];
791+
ref_pc = &mod->code->code[ref_offset];
792+
DECODE_LITERAL(line_ref, ref_pc);
793+
return module_find_line_ref(mod, line_ref, line, filename_len, filename);
747794
}
748-
749-
++i;
750795
}
751-
return false;
796+
ref_offset = mod->line_refs_offsets[i - 1];
797+
ref_pc = &mod->code->code[ref_offset];
798+
DECODE_LITERAL(line_ref, ref_pc);
799+
return module_find_line_ref(mod, line_ref, line, filename_len, filename);
752800
}

src/libAtomVM/module.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,6 @@ struct ModuleFilename
8888
size_t len;
8989
};
9090

91-
struct LineRefOffset
92-
{
93-
struct ListHead head;
94-
unsigned int offset;
95-
uint16_t line_ref;
96-
};
97-
9891
struct Module
9992
{
10093
#ifdef ENABLE_ADVANCED_TRACE
@@ -113,7 +106,8 @@ struct Module
113106
size_t locations_count;
114107
const uint8_t *locations_table;
115108

116-
struct ListHead line_ref_offsets;
109+
unsigned int *line_refs_offsets;
110+
size_t line_refs_offsets_count;
117111

118112
const struct ExportedFunction **imported_funcs;
119113

@@ -390,10 +384,11 @@ bool module_get_function_from_label(Module *this_module, int label, AtomString *
390384
* is a no-op.
391385
*
392386
* @param mod the module
387+
* @param line_refs the list of line references to append to
393388
* @param line_ref the line reference (index)
394389
* @param offset the instruction offset at which the line instruction occurred.
395390
*/
396-
void module_insert_line_ref_offset(Module *mod, int line_ref, int offset);
391+
void module_insert_line_ref_offset(Module *mod, struct ListHead *line_refs, uint32_t line_ref, int offset);
397392

398393
/*
399394
* @brief Find the latest line reference (index) before or at which the instruction offset

src/libAtomVM/opcodesswitch.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,9 +1809,9 @@ static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString f
18091809
#endif
18101810

18111811
#ifdef IMPL_CODE_LOADER
1812-
int read_core_chunk0(Module *mod);
1812+
int read_core_chunk0(Module *mod, struct ListHead *line_refs);
18131813

1814-
int read_core_chunk(Module *mod)
1814+
int read_core_chunk(Module *mod, struct ListHead *line_refs)
18151815
#else
18161816
#ifdef IMPL_EXECUTE_LOOP
18171817
int context_execute_loop(Context *ctx, Module *mod, const char *function_name, int arity)
@@ -1848,7 +1848,7 @@ static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString f
18481848
#endif
18491849

18501850
#ifdef IMPL_CODE_LOADER
1851-
return read_core_chunk0(mod);
1851+
return read_core_chunk0(mod, line_refs);
18521852
#endif
18531853
#ifdef IMPL_EXECUTE_LOOP
18541854
// This process is the first scheduler process
@@ -1860,7 +1860,7 @@ static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString f
18601860
}
18611861

18621862
#ifdef IMPL_CODE_LOADER
1863-
int read_core_chunk0(Module *mod)
1863+
int read_core_chunk0(Module *mod, struct ListHead *line_refs)
18641864
#else
18651865
#ifdef IMPL_EXECUTE_LOOP
18661866
HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
@@ -5675,15 +5675,16 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
56755675

56765676
case OP_LINE: {
56775677
#ifdef IMPL_CODE_LOADER
5678-
const uint8_t *saved_pc = pc -1;
5678+
unsigned int offset = pc - code;
56795679
#endif
56805680
uint32_t line_number;
5681+
// This decode increments pc and ensures we can decode it
56815682
DECODE_LITERAL(line_number, pc);
56825683

56835684
TRACE("line/1: %i\n", line_number);
56845685

56855686
#ifdef IMPL_CODE_LOADER
5686-
module_insert_line_ref_offset(mod, line_number, saved_pc - code);
5687+
module_insert_line_ref_offset(mod, line_refs, line_number, offset);
56875688
#endif
56885689
break;
56895690
}

0 commit comments

Comments
 (0)