Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@
#define DEFAULT_FUNCS_SIZE 64
#define DEFAULT_INCLUSIONS_SIZE 16

/* Arena compaction bitmask flags for selective memory reclamation */
#define COMPACT_ARENA_BLOCK 0x01 /* BLOCK_ARENA - variables/blocks */
#define COMPACT_ARENA_INSN 0x02 /* INSN_ARENA - instructions */
#define COMPACT_ARENA_BB 0x04 /* BB_ARENA - basic blocks */
#define COMPACT_ARENA_HASHMAP 0x08 /* HASHMAP_ARENA - hash nodes */
#define COMPACT_ARENA_GENERAL 0x10 /* GENERAL_ARENA - misc allocations */
#define COMPACT_ARENA_ALL 0x1F /* All arenas */

/* Common arena compaction combinations for different compilation phases */
#define COMPACT_PHASE_PARSING (COMPACT_ARENA_BLOCK | COMPACT_ARENA_GENERAL)
#define COMPACT_PHASE_SSA (COMPACT_ARENA_INSN | COMPACT_ARENA_BB)
#define COMPACT_PHASE_BACKEND (COMPACT_ARENA_BB | COMPACT_ARENA_GENERAL)

#define ELF_START 0x10000
#define PTR_SIZE 4

Expand Down
95 changes: 92 additions & 3 deletions src/globals.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,6 @@ bb_traversal_args_t *arena_alloc_traversal_args(void)
return arena_calloc(GENERAL_ARENA, 1, sizeof(bb_traversal_args_t));
}

/* Free the given arena and all its blocks.
* @arena: The arena to free. Must not be NULL.
*/
void arena_free(arena_t *arena)
{
arena_block_t *block = arena->head, *next;
Expand Down Expand Up @@ -1146,6 +1143,98 @@ void global_init(void)
/* Forward declaration for lexer cleanup */
void lexer_cleanup(void);

/* Free empty trailing blocks from an arena safely.
* This only frees blocks that come after the last used block,
* ensuring no pointers are invalidated.
*
* @arena: The arena to compact.
* Return: Bytes freed.
*/
int arena_free_trailing_blocks(arena_t *arena)
{
if (!arena || !arena->head)
return 0;

/* Find the last block with actual allocations */
arena_block_t *last_used = NULL;
arena_block_t *block;

for (block = arena->head; block; block = block->next) {
if (block->offset > 0)
last_used = block;
}

/* If no blocks are used, keep just the head */
if (!last_used)
last_used = arena->head;

/* Free all blocks after last_used */
int freed = 0;
if (last_used->next) {
block = last_used->next;
last_used->next = NULL;

while (block) {
arena_block_t *next = block->next;
freed += block->capacity;
arena->total_bytes -= block->capacity;
arena_block_free(block);
block = next;
}
}

return freed;
}

/* Compact all arenas to reduce memory usage after compilation phases.
* This safely frees only trailing empty blocks without invalidating pointers.
*
* Return: Total bytes freed across all arenas.
*/
int compact_all_arenas(void)
{
int total_saved = 0;

/* Free trailing blocks from each arena */
total_saved += arena_free_trailing_blocks(BLOCK_ARENA);
total_saved += arena_free_trailing_blocks(INSN_ARENA);
total_saved += arena_free_trailing_blocks(BB_ARENA);
total_saved += arena_free_trailing_blocks(HASHMAP_ARENA);
total_saved += arena_free_trailing_blocks(GENERAL_ARENA);

return total_saved;
}

/* Compact specific arenas based on compilation phase.
* Different phases have different memory usage patterns.
*
* @phase_mask: Bitmask using COMPACT_ARENA_* defines
* to indicate which arenas to compact.
*
* Return: Total bytes freed.
*/
int compact_arenas_selective(int phase_mask)
{
int total_saved = 0;

if (phase_mask & COMPACT_ARENA_BLOCK)
total_saved += arena_free_trailing_blocks(BLOCK_ARENA);

if (phase_mask & COMPACT_ARENA_INSN)
total_saved += arena_free_trailing_blocks(INSN_ARENA);

if (phase_mask & COMPACT_ARENA_BB)
total_saved += arena_free_trailing_blocks(BB_ARENA);

if (phase_mask & COMPACT_ARENA_HASHMAP)
total_saved += arena_free_trailing_blocks(HASHMAP_ARENA);

if (phase_mask & COMPACT_ARENA_GENERAL)
total_saved += arena_free_trailing_blocks(GENERAL_ARENA);

return total_saved;
}

void global_release(void)
{
/* Cleanup lexer hashmaps */
Expand Down
16 changes: 16 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ int main(int argc, char *argv[])
/* load and parse source code into IR */
parse(in);

/* Compact arenas after parsing to free temporary parse structures */
compact_all_arenas();

ssa_build();

/* dump first phase IR */
Expand All @@ -98,12 +101,22 @@ int main(int argc, char *argv[])
/* SSA-based optimization */
optimize();

/* Compact arenas after SSA optimization to free temporary SSA structures */
compact_all_arenas();

/* SSA-based liveness analyses */
liveness_analysis();

/* Compact after liveness analysis - mainly traversal args in GENERAL_ARENA
*/
compact_arenas_selective(COMPACT_ARENA_GENERAL);

/* allocate register from IR */
reg_alloc();

/* Compact after register allocation - mainly INSN and BB arenas */
compact_arenas_selective(COMPACT_ARENA_INSN | COMPACT_ARENA_BB);

peephole();

/* Apply arch-specific IR tweaks before final codegen */
Expand All @@ -112,6 +125,9 @@ int main(int argc, char *argv[])
/* flatten CFG to linear instruction */
cfg_flatten();

/* Compact after CFG flattening - BB and GENERAL no longer needed */
compact_arenas_selective(COMPACT_ARENA_BB | COMPACT_ARENA_GENERAL);

/* dump second phase IR */
if (dump_ir)
dump_ph2_ir();
Expand Down