@@ -331,9 +331,6 @@ bb_traversal_args_t *arena_alloc_traversal_args(void)
331
331
return arena_calloc (GENERAL_ARENA , 1 , sizeof (bb_traversal_args_t ));
332
332
}
333
333
334
- /* Free the given arena and all its blocks.
335
- * @arena: The arena to free. Must not be NULL.
336
- */
337
334
void arena_free (arena_t * arena )
338
335
{
339
336
arena_block_t * block = arena -> head , * next ;
@@ -1146,6 +1143,98 @@ void global_init(void)
1146
1143
/* Forward declaration for lexer cleanup */
1147
1144
void lexer_cleanup (void );
1148
1145
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
+
1149
1238
void global_release (void )
1150
1239
{
1151
1240
/* Cleanup lexer hashmaps */
0 commit comments