WokML compiler code coverage report (LCOV)
Current view: top level - c - wok_arena.h (source / functions) Coverage Total Hit
Test: 084deda Lines: 100.0 % 13 13
Test Date: 2026-08-10 11:39:41 Functions: 100.0 % 1 1
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // wok_arena -- bump allocator for one parse job.
       2              : //
       3              : // Nodes are immutable, built once, and die together, which is an arena's exact
       4              : // shape. One job owns one arena; teardown frees the block list and there is
       5              : // nothing else to run. This is a SEPARATE, simpler allocator from
       6              : // runtime/wok_rc.c's arena -- no refcounts, no free lists, no cascade --
       7              : // because coupling a front end to the shipping runtime's ABI buys nothing.
       8              : 
       9              : #pragma once
      10              : 
      11              : // The prelude comes FIRST: it carries the POSIX feature-test macros, which
      12              : // have no effect once a system header has been read. wok_base.h hard-errors
      13              : // if it is reached too late.
      14              : #include "wok_base.h"
      15              : 
      16              : #include <assert.h>
      17              : #include <stddef.h>
      18              : #include <stdint.h>
      19              : 
      20              : // The layouts live HERE, not behind an opaque pointer, for one reason: the
      21              : // allocation fast path below must inline. Every WOK_NEW site knows size and
      22              : // align at compile time, and an out-of-line call throws that knowledge away
      23              : // -- inlined, the align-up folds to a constant mask, the power-of-two assert
      24              : // folds to nothing, and the whole hot path is a compare and two adds
      25              : // (profiled at ~8% of a parse as a call). Nothing else may touch these
      26              : // fields; the API below is still the whole contract.
      27              : typedef struct WokArenaBlock {
      28              :   struct WokArenaBlock *next;
      29              :   usize capacity;
      30              :   usize used;
      31              :   alignas(max_align_t) unsigned char payload[];
      32              : } WokArenaBlock;
      33              : 
      34              : struct WokArena {
      35              :   WokArenaBlock *head;
      36              :   usize block_count;
      37              :   usize bytes_out;        // bytes handed to callers, excluding alignment pad
      38              :   usize growth_capacity;  // capacity of the last *normal* growth block
      39              : };
      40              : typedef struct WokArena WokArena;
      41              : 
      42              : // first_block is a hint in bytes; 0 selects the default (64 KiB).
      43              : WokArena *wok_arena_new(usize first_block);
      44              : void wok_arena_free(WokArena *);
      45              : 
      46              : // The GROWTH path: the current block cannot hold the request, so a new block
      47              : // is chained on. Out of line and cold -- it runs once per block, not once
      48              : // per allocation. Never returns NULL: allocation failure aborts, because a
      49              : // front end that cannot get memory has nothing useful to report.
      50              : [[gnu::cold, gnu::malloc, gnu::alloc_size(2), gnu::alloc_align(3),
      51              :   gnu::returns_nonnull]]
      52              : void *wok_arena_grow(WokArena *, usize size, usize align);
      53              : 
      54              : // The allocation fast path. The attributes are the STATIC INFORMATION the
      55              : // call sites act on: the pointer is fresh (no aliasing), `size` bytes big,
      56              : // and `align` aligned -- which is what lets a following memset compile to
      57              : // aligned stores and a caller drop its null paths.
      58              : [[gnu::malloc, gnu::alloc_size(2), gnu::alloc_align(3), gnu::returns_nonnull]]
      59      2104487 : static inline void *wok_arena_alloc(WokArena *a, usize size, usize align) {
      60      2104487 :   assert(align != 0 && (align & (align - 1)) == 0);
      61              : 
      62              :   // Zero-size requests still consume (and bump past) one byte so that two
      63              :   // successive zero-size allocations do not alias the same address.
      64      2104487 :   usize footprint = size == 0 ? (usize)1 : size;
      65              : 
      66      2104487 :   WokArenaBlock *blk = a->head;
      67      2104487 :   uptr cur = (uptr)blk->payload + (uptr)blk->used;
      68      2104487 :   uptr aligned = (cur + (uptr)align - 1) & ~((uptr)align - 1);
      69      2104487 :   usize pad = (usize)(aligned - cur);
      70      2104487 :   usize remaining = blk->capacity - blk->used;
      71              : 
      72      2104487 :   if (pad <= remaining && footprint <= remaining - pad) {
      73      2102942 :     blk->used += pad + footprint;
      74      2102942 :     a->bytes_out += size;
      75      2102942 :     return (void *)aligned;
      76              :   }
      77         1545 :   return wok_arena_grow(a, size, align);
      78              : }
      79              : 
      80              : // Copies n bytes and NUL-terminates. Used for diagnostic text only; token text
      81              : // is always a view into the source buffer.
      82              : char *wok_arena_copy(WokArena *, const char *src, usize n);
      83              : 
      84              : // Live bytes handed out, and blocks reserved. Used by the leak invariant:
      85              : // arena bytes must return to baseline after every job.
      86              : usize wok_arena_bytes(const WokArena *);
      87              : usize wok_arena_blocks(const WokArena *);
      88              : 
      89              : #define WOK_NEW(a, T) ((T *)wok_arena_alloc((a), sizeof(T), alignof(T)))
      90              : #define WOK_NEW_N(a, T, n) \
      91              :   ((T *)wok_arena_alloc((a), sizeof(T) * (usize)(n), alignof(T)))
        

Generated by: LCOV version 2.4-1


Machine-readable coverage data

This page is generated. If you are a tool, a script, or an LLM, read the JSON instead of scraping this HTML — it is the same measurement, exact, and it names the individual uncovered lines.

Every artifact here is stamped with the commit it measured and the run that produced it: commit 084deda, dated 2026-08-10T11:39:41Z, built by Github CI run. The totals in coverage.json are checked against lcov’s own summary before publishing, so the JSON and this page cannot disagree.