@@ -326,9 +326,6 @@ bb_traversal_args_t *arena_alloc_traversal_args(void)
326326 return arena_calloc (GENERAL_ARENA , 1 , sizeof (bb_traversal_args_t ));
327327}
328328
329- /* Free the given arena and all its blocks.
330- * @arena: The arena to free. Must not be NULL.
331- */
332329void arena_free (arena_t * arena )
333330{
334331 arena_block_t * block = arena -> head , * next ;
@@ -1134,6 +1131,108 @@ void global_init(void)
11341131/* Forward declaration for lexer cleanup */
11351132void lexer_cleanup (void );
11361133
1134+ /* Free empty trailing blocks from an arena safely.
1135+ * This only frees blocks that come after the last used block,
1136+ * ensuring no pointers are invalidated.
1137+ *
1138+ * @arena: The arena to compact.
1139+ * Return: Bytes freed.
1140+ */
1141+ int arena_free_trailing_blocks (arena_t * arena )
1142+ {
1143+ if (!arena || !arena -> head )
1144+ return 0 ;
1145+
1146+ /* Find the last block with actual allocations */
1147+ arena_block_t * last_used = NULL ;
1148+ arena_block_t * block ;
1149+
1150+ for (block = arena -> head ; block ; block = block -> next ) {
1151+ if (block -> offset > 0 )
1152+ last_used = block ;
1153+ }
1154+
1155+ /* If no blocks are used, keep just the head */
1156+ if (!last_used )
1157+ last_used = arena -> head ;
1158+
1159+ /* Free all blocks after last_used */
1160+ int freed = 0 ;
1161+ if (last_used -> next ) {
1162+ block = last_used -> next ;
1163+ last_used -> next = NULL ;
1164+
1165+ while (block ) {
1166+ arena_block_t * next = block -> next ;
1167+ freed += block -> capacity ;
1168+ arena -> total_bytes -= block -> capacity ;
1169+ arena_block_free (block );
1170+ block = next ;
1171+ }
1172+ }
1173+
1174+ return freed ;
1175+ }
1176+
1177+ /* Compact all arenas to reduce memory usage after compilation phases.
1178+ * This safely frees only trailing empty blocks without invalidating pointers.
1179+ *
1180+ * Return: Total bytes freed across all arenas.
1181+ */
1182+ int compact_all_arenas (void )
1183+ {
1184+ int total_saved = 0 ;
1185+ int saved ;
1186+
1187+ /* Free trailing blocks from each arena */
1188+ saved = arena_free_trailing_blocks (BLOCK_ARENA );
1189+ total_saved += saved ;
1190+
1191+ saved = arena_free_trailing_blocks (INSN_ARENA );
1192+ total_saved += saved ;
1193+
1194+ saved = arena_free_trailing_blocks (BB_ARENA );
1195+ total_saved += saved ;
1196+
1197+ saved = arena_free_trailing_blocks (HASHMAP_ARENA );
1198+ total_saved += saved ;
1199+
1200+ saved = arena_free_trailing_blocks (GENERAL_ARENA );
1201+ total_saved += saved ;
1202+
1203+ return total_saved ;
1204+ }
1205+
1206+ /* Compact specific arenas based on compilation phase.
1207+ * Different phases have different memory usage patterns.
1208+ *
1209+ * @phase_mask: Bitmask using COMPACT_ARENA_* defines
1210+ * to indicate which arenas to compact.
1211+ *
1212+ * Return: Total bytes freed.
1213+ */
1214+ int compact_arenas_selective (int phase_mask )
1215+ {
1216+ int total_saved = 0 ;
1217+
1218+ if (phase_mask & COMPACT_ARENA_BLOCK )
1219+ total_saved += arena_free_trailing_blocks (BLOCK_ARENA );
1220+
1221+ if (phase_mask & COMPACT_ARENA_INSN )
1222+ total_saved += arena_free_trailing_blocks (INSN_ARENA );
1223+
1224+ if (phase_mask & COMPACT_ARENA_BB )
1225+ total_saved += arena_free_trailing_blocks (BB_ARENA );
1226+
1227+ if (phase_mask & COMPACT_ARENA_HASHMAP )
1228+ total_saved += arena_free_trailing_blocks (HASHMAP_ARENA );
1229+
1230+ if (phase_mask & COMPACT_ARENA_GENERAL )
1231+ total_saved += arena_free_trailing_blocks (GENERAL_ARENA );
1232+
1233+ return total_saved ;
1234+ }
1235+
11371236void global_release (void )
11381237{
11391238 /* Cleanup lexer hashmaps */
0 commit comments