packages feed

nova-nix-0.1.9.0: cbits/nn_arena.c

/*
 * nn_arena.c — Batch StablePtr collection from the thunk arena.
 *
 * Iterates all thunks via nn_thunk_count/nn_thunk_get and identifies
 * payloads that are Haskell StablePtrs (as opposed to inline scalar
 * values or C pointers).
 *
 * After M6 bytecode integration, PENDING thunks store (bc_idx,
 * StablePtr Env) — the bc_idx replaces the Expr, but the Env stays
 * as a StablePtr for knot-tying laziness.
 *
 * StablePtr sources:
 *   1. PENDING/BLACKHOLE: payload = StablePtr Env (all pending thunks)
 *   2. COMPUTED with val_tag == NN_VALUE_PTR: StablePtr NixValue
 *
 * All other COMPUTED payloads (inline scalars, C pointers) are NOT
 * StablePtrs and must NOT be freed.
 */

#include "nn_arena.h"
#include "nn_attrset.h"
#include "nn_thunk.h"

#include <stddef.h>

uint32_t
nn_arena_stableptr_count(void)
{
    uint32_t total = nn_thunk_count();
    uint32_t count = 0;
    uint32_t i;

    for (i = 0; i < total; i++) {
        nn_thunk_t *t = nn_thunk_get(i);
        if (!t) continue;

        uint8_t state = nn_thunk_state(t);
        if (state == NN_THUNK_PENDING || state == NN_THUNK_BLACKHOLE) {
            void *p = nn_thunk_payload(t);
            if (p) count++;
        } else if (state == NN_THUNK_COMPUTED) {
            uint8_t vtag = nn_thunk_value_tag(t);
            if (vtag == NN_VALUE_PTR) {
                void *p = nn_thunk_payload(t);
                if (p) count++;
            }
        }
    }
    return count;
}

uint32_t
nn_arena_collect_stableptrs(void **output, uint32_t max_count)
{
    uint32_t total = nn_thunk_count();
    uint32_t written = 0;
    uint32_t i;

    for (i = 0; i < total && written < max_count; i++) {
        nn_thunk_t *t = nn_thunk_get(i);
        if (!t) continue;

        uint8_t state = nn_thunk_state(t);
        if (state == NN_THUNK_PENDING || state == NN_THUNK_BLACKHOLE) {
            void *p = nn_thunk_payload(t);
            if (p) output[written++] = p;
        } else if (state == NN_THUNK_COMPUTED) {
            uint8_t vtag = nn_thunk_value_tag(t);
            if (vtag == NN_VALUE_PTR) {
                void *p = nn_thunk_payload(t);
                if (p) output[written++] = p;
            }
        }
    }
    return written;
}