44 * Replaces fixed-size TSNode stack[] arrays that silently drop AST subtrees
55 * when the stack overflows (GitHub issue #199).
66 *
7- * Uses the arena allocator for zero-fragmentation growth: old blocks are
8- * abandoned (freed when the arena is destroyed at end of file extraction).
9- * Initial capacity matches the previous fixed caps so small files allocate
10- * no extra memory.
7+ * The common capacity lives inline in the traversal's own stack frame. Only an
8+ * unusually broad AST spills into the result arena. Call-site capacities
9+ * historically mirrored fixed stack limits (usually 512, sometimes 4096), so
10+ * allocating every traversal there made temporary work survive with durable
11+ * extraction results across the whole repository. Inline storage preserves the
12+ * same traversal order and geometric growth without that lifetime inversion.
1113 */
1214#ifndef CBM_EXTRACT_NODE_STACK_H
1315#define CBM_EXTRACT_NODE_STACK_H
@@ -20,19 +22,24 @@ typedef struct {
2022 TSNode * items ;
2123 int count ;
2224 int cap ;
25+ TSNode inline_items [128 ];
2326} TSNodeStack ;
2427
25- /* Initialize a stack with the given initial capacity, arena-allocated. */
28+ enum { TS_NSTACK_INLINE_CAP = 128 };
29+
30+ /* Initialize with inline storage; arena is used only if the stack spills. */
2631static inline void ts_nstack_init (TSNodeStack * s , CBMArena * arena , int initial_cap ) {
27- s -> items = (TSNode * )cbm_arena_alloc (arena , (size_t )initial_cap * sizeof (TSNode ));
32+ (void )arena ;
33+ (void )initial_cap ;
34+ s -> items = s -> inline_items ;
2835 s -> count = 0 ;
29- s -> cap = s -> items ? initial_cap : 0 ;
36+ s -> cap = TS_NSTACK_INLINE_CAP ;
3037}
3138
3239/* Push a node onto the stack, growing 2x if needed. */
3340static inline void ts_nstack_push (TSNodeStack * s , CBMArena * arena , TSNode node ) {
3441 if (s -> count >= s -> cap ) {
35- int new_cap = s -> cap ? s -> cap * 2 : 512 ;
42+ int new_cap = s -> cap ? s -> cap * 2 : TS_NSTACK_INLINE_CAP ;
3643 TSNode * new_items = (TSNode * )cbm_arena_alloc (arena , (size_t )new_cap * sizeof (TSNode ));
3744 if (!new_items )
3845 return ; /* OOM: best-effort, stop growing */
0 commit comments