WokML compiler code coverage report (LCOV)
Current view: top level - c - wok_arena.c (source / functions) Coverage Total Hit
Test: 084deda Lines: 91.4 % 58 53
Test Date: 2026-08-10 11:39:41 Functions: 66.7 % 9 6
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // wok_arena -- bump allocator implementation. See wok_arena.h for the
       2              : // contract: one growable list of malloc'd blocks, no frees of individual
       3              : // allocations, teardown frees the whole list at once. The allocation fast
       4              : // path is inline in the header; this file owns creation, growth and
       5              : // teardown.
       6              : 
       7              : #include "wok_arena.h"
       8              : 
       9              : #include <stdbool.h>
      10              : #include <stdio.h>
      11              : #include <stdlib.h>
      12              : #include <string.h>
      13              : 
      14              : #define WOK_ARENA_DEFAULT_BLOCK ((usize)(64u * 1024u))
      15              : #define WOK_ARENA_MAX_GROWTH ((usize)(8u * 1024u * 1024u))
      16              : 
      17            0 : [[noreturn]] static void wok_arena_oom(void) {
      18            0 :   (void)fprintf(stderr, "wok: out of memory allocating arena block\n");
      19            0 :   abort();
      20              : }
      21              : 
      22        80513 : static WokArenaBlock *wok_arena_new_block(usize capacity) {
      23        80513 :   WokArenaBlock *blk = (WokArenaBlock *)malloc(sizeof(WokArenaBlock) + capacity);
      24        80513 :   if (blk == nullptr) wok_arena_oom();
      25        80513 :   blk->next = nullptr;
      26        80513 :   blk->capacity = capacity;
      27        80513 :   blk->used = 0;
      28        80513 :   return blk;
      29              : }
      30              : 
      31         1545 : static uptr wok_align_up(uptr value, usize align) {
      32         1545 :   uptr a = (uptr)align;
      33         1545 :   return (value + a - (uptr)1) & ~(a - (uptr)1);
      34              : }
      35              : 
      36        78968 : WokArena *wok_arena_new(usize first_block) {
      37        78968 :   usize cap = first_block != 0 ? first_block : WOK_ARENA_DEFAULT_BLOCK;
      38              : 
      39        78968 :   WokArena *a = (WokArena *)malloc(sizeof(WokArena));
      40        78968 :   if (a == nullptr) wok_arena_oom();
      41              : 
      42        78968 :   a->head = wok_arena_new_block(cap);
      43        78968 :   a->block_count = 1;
      44        78968 :   a->bytes_out = 0;
      45        78968 :   a->growth_capacity = cap;
      46        78968 :   return a;
      47              : }
      48              : 
      49        78968 : void wok_arena_free(WokArena *a) {
      50        78968 :   if (a == nullptr) return;
      51              : 
      52        78968 :   WokArenaBlock *blk = a->head;
      53       159481 :   while (blk != nullptr) {
      54        80513 :     WokArenaBlock *next = blk->next;
      55        80513 :     free(blk);
      56        80513 :     blk = next;
      57              :   }
      58        78968 :   free(a);
      59              : }
      60              : 
      61         1545 : void *wok_arena_grow(WokArena *a, usize size, usize align) {
      62         1545 :   usize footprint = size == 0 ? (usize)1 : size;
      63              : 
      64              :   // `needed` is a safe upper bound on what a fresh block must hold, since a
      65              :   // brand new block's payload is already max-aligned and align worst-case
      66              :   // slop is bounded by `align` itself.
      67         1545 :   usize needed = footprint + align;
      68         1545 :   bool dedicated = needed > WOK_ARENA_MAX_GROWTH;
      69         1545 :   usize new_cap;
      70         1545 :   if (dedicated) {
      71              :     new_cap = needed;
      72              :   } else {
      73         1545 :     usize doubled = a->growth_capacity > WOK_ARENA_MAX_GROWTH / 2
      74              :                           ? WOK_ARENA_MAX_GROWTH
      75         1545 :                           : a->growth_capacity * 2;
      76         1545 :     new_cap = doubled > needed ? doubled : needed;
      77         1545 :     if (new_cap > WOK_ARENA_MAX_GROWTH) new_cap = WOK_ARENA_MAX_GROWTH;
      78              :   }
      79              : 
      80         1545 :   WokArenaBlock *nb = wok_arena_new_block(new_cap);
      81         1545 :   nb->next = a->head;
      82         1545 :   a->head = nb;
      83         1545 :   a->block_count += 1;
      84         1545 :   if (!dedicated) a->growth_capacity = new_cap;
      85              : 
      86         1545 :   uptr nbase = (uptr)nb->payload;
      87         1545 :   uptr naligned = wok_align_up(nbase, align);
      88         1545 :   usize npad = (usize)(naligned - nbase);
      89         1545 :   nb->used = npad + footprint;
      90         1545 :   a->bytes_out += size;
      91         1545 :   return (void *)naligned;
      92              : }
      93              : 
      94       107024 : char *wok_arena_copy(WokArena *a, const char *src, usize n) {
      95       107024 :   char *dst = (char *)wok_arena_alloc(a, n + 1, alignof(char));
      96       107024 :   memcpy(dst, src, n);
      97       107024 :   dst[n] = '\0';
      98       107024 :   return dst;
      99              : }
     100              : 
     101            0 : usize wok_arena_bytes(const WokArena *a) { return a->bytes_out; }
     102              : 
     103            0 : usize wok_arena_blocks(const WokArena *a) { return a->block_count; }
        

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.