Skip to content

Commit b09e0e5

Browse files
authored
Merge pull request #255 from sysprog21/arena-compaction
Implement arena memory compaction
2 parents 48d2b1a + ddecbd2 commit b09e0e5

File tree

3 files changed

+121
-3
lines changed

3 files changed

+121
-3
lines changed

src/defs.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,19 @@
4747
#define DEFAULT_FUNCS_SIZE 64
4848
#define DEFAULT_INCLUSIONS_SIZE 16
4949

50+
/* Arena compaction bitmask flags for selective memory reclamation */
51+
#define COMPACT_ARENA_BLOCK 0x01 /* BLOCK_ARENA - variables/blocks */
52+
#define COMPACT_ARENA_INSN 0x02 /* INSN_ARENA - instructions */
53+
#define COMPACT_ARENA_BB 0x04 /* BB_ARENA - basic blocks */
54+
#define COMPACT_ARENA_HASHMAP 0x08 /* HASHMAP_ARENA - hash nodes */
55+
#define COMPACT_ARENA_GENERAL 0x10 /* GENERAL_ARENA - misc allocations */
56+
#define COMPACT_ARENA_ALL 0x1F /* All arenas */
57+
58+
/* Common arena compaction combinations for different compilation phases */
59+
#define COMPACT_PHASE_PARSING (COMPACT_ARENA_BLOCK | COMPACT_ARENA_GENERAL)
60+
#define COMPACT_PHASE_SSA (COMPACT_ARENA_INSN | COMPACT_ARENA_BB)
61+
#define COMPACT_PHASE_BACKEND (COMPACT_ARENA_BB | COMPACT_ARENA_GENERAL)
62+
5063
#define ELF_START 0x10000
5164
#define PTR_SIZE 4
5265

src/globals.c

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,6 @@ bb_traversal_args_t *arena_alloc_traversal_args(void)
331331
return arena_calloc(GENERAL_ARENA, 1, sizeof(bb_traversal_args_t));
332332
}
333333

334-
/* Free the given arena and all its blocks.
335-
* @arena: The arena to free. Must not be NULL.
336-
*/
337334
void arena_free(arena_t *arena)
338335
{
339336
arena_block_t *block = arena->head, *next;
@@ -1146,6 +1143,98 @@ void global_init(void)
11461143
/* Forward declaration for lexer cleanup */
11471144
void lexer_cleanup(void);
11481145

1146+
/* Free empty trailing blocks from an arena safely.
1147+
* This only frees blocks that come after the last used block,
1148+
* ensuring no pointers are invalidated.
1149+
*
1150+
* @arena: The arena to compact.
1151+
* Return: Bytes freed.
1152+
*/
1153+
int arena_free_trailing_blocks(arena_t *arena)
1154+
{
1155+
if (!arena || !arena->head)
1156+
return 0;
1157+
1158+
/* Find the last block with actual allocations */
1159+
arena_block_t *last_used = NULL;
1160+
arena_block_t *block;
1161+
1162+
for (block = arena->head; block; block = block->next) {
1163+
if (block->offset > 0)
1164+
last_used = block;
1165+
}
1166+
1167+
/* If no blocks are used, keep just the head */
1168+
if (!last_used)
1169+
last_used = arena->head;
1170+
1171+
/* Free all blocks after last_used */
1172+
int freed = 0;
1173+
if (last_used->next) {
1174+
block = last_used->next;
1175+
last_used->next = NULL;
1176+
1177+
while (block) {
1178+
arena_block_t *next = block->next;
1179+
freed += block->capacity;
1180+
arena->total_bytes -= block->capacity;
1181+
arena_block_free(block);
1182+
block = next;
1183+
}
1184+
}
1185+
1186+
return freed;
1187+
}
1188+
1189+
/* Compact all arenas to reduce memory usage after compilation phases.
1190+
* This safely frees only trailing empty blocks without invalidating pointers.
1191+
*
1192+
* Return: Total bytes freed across all arenas.
1193+
*/
1194+
int compact_all_arenas(void)
1195+
{
1196+
int total_saved = 0;
1197+
1198+
/* Free trailing blocks from each arena */
1199+
total_saved += arena_free_trailing_blocks(BLOCK_ARENA);
1200+
total_saved += arena_free_trailing_blocks(INSN_ARENA);
1201+
total_saved += arena_free_trailing_blocks(BB_ARENA);
1202+
total_saved += arena_free_trailing_blocks(HASHMAP_ARENA);
1203+
total_saved += arena_free_trailing_blocks(GENERAL_ARENA);
1204+
1205+
return total_saved;
1206+
}
1207+
1208+
/* Compact specific arenas based on compilation phase.
1209+
* Different phases have different memory usage patterns.
1210+
*
1211+
* @phase_mask: Bitmask using COMPACT_ARENA_* defines
1212+
* to indicate which arenas to compact.
1213+
*
1214+
* Return: Total bytes freed.
1215+
*/
1216+
int compact_arenas_selective(int phase_mask)
1217+
{
1218+
int total_saved = 0;
1219+
1220+
if (phase_mask & COMPACT_ARENA_BLOCK)
1221+
total_saved += arena_free_trailing_blocks(BLOCK_ARENA);
1222+
1223+
if (phase_mask & COMPACT_ARENA_INSN)
1224+
total_saved += arena_free_trailing_blocks(INSN_ARENA);
1225+
1226+
if (phase_mask & COMPACT_ARENA_BB)
1227+
total_saved += arena_free_trailing_blocks(BB_ARENA);
1228+
1229+
if (phase_mask & COMPACT_ARENA_HASHMAP)
1230+
total_saved += arena_free_trailing_blocks(HASHMAP_ARENA);
1231+
1232+
if (phase_mask & COMPACT_ARENA_GENERAL)
1233+
total_saved += arena_free_trailing_blocks(GENERAL_ARENA);
1234+
1235+
return total_saved;
1236+
}
1237+
11491238
void global_release(void)
11501239
{
11511240
/* Cleanup lexer hashmaps */

src/main.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ int main(int argc, char *argv[])
8989
/* load and parse source code into IR */
9090
parse(in);
9191

92+
/* Compact arenas after parsing to free temporary parse structures */
93+
compact_all_arenas();
94+
9295
ssa_build();
9396

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

104+
/* Compact arenas after SSA optimization to free temporary SSA structures */
105+
compact_all_arenas();
106+
101107
/* SSA-based liveness analyses */
102108
liveness_analysis();
103109

110+
/* Compact after liveness analysis - mainly traversal args in GENERAL_ARENA
111+
*/
112+
compact_arenas_selective(COMPACT_ARENA_GENERAL);
113+
104114
/* allocate register from IR */
105115
reg_alloc();
106116

117+
/* Compact after register allocation - mainly INSN and BB arenas */
118+
compact_arenas_selective(COMPACT_ARENA_INSN | COMPACT_ARENA_BB);
119+
107120
peephole();
108121

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

128+
/* Compact after CFG flattening - BB and GENERAL no longer needed */
129+
compact_arenas_selective(COMPACT_ARENA_BB | COMPACT_ARENA_GENERAL);
130+
115131
/* dump second phase IR */
116132
if (dump_ir)
117133
dump_ph2_ir();

0 commit comments

Comments
 (0)