From e1c8812473c89b96e9c1a09f3a46f8f392945b64 Mon Sep 17 00:00:00 2001 From: eunhhu Date: Tue, 6 Oct 2026 03:46:11 +0100 Subject: JIT: an append to a HASHED list in a nest whose books keep DENSE appends' growth in registers checks the memory against the books' headroom (the app's growth lacks theirs until written back): it faulted MEMORY a round late, its work a round more than the executor's (a loop appending to DENSE, FLAT and HASHED lists, memory 6000: 3562 for 3525). pure-run: memory N, the states' budget --- cli/pure-run.c | 6 ++++++ core/module-jit.c | 24 ++++++++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/cli/pure-run.c b/cli/pure-run.c index 8ef91d9..e62bc98 100644 --- a/cli/pure-run.c +++ b/cli/pure-run.c @@ -12,6 +12,7 @@ * saved at the end of input or by save. --batch N defers saving and saves * every N commands (and at the end), so N events share one commit. * down NAME | up NAME | frame [N] | type NAME HEX|- | message NAME HEX|- | tick NAME | time MS | replace PATH | save | show + * budget N (the work an event may do) | memory N (what the states may hold) | work (the last event's work) * (type gives a text input its bytes, message a message input its payload, laid out as the module says.) * Text states and text views print as JSON strings; cursors as byte positions; * lists as arrays of objects; indices as positions; a table view as an array @@ -201,6 +202,11 @@ int main(int argc, char **argv) { unsigned long long budget = strtoull(argument, &end, 10); if (!*argument || *end) failure = "budget"; else pure_app_work(&app, budget); + } else if (!strcmp(command, "memory")) { /* what the states may hold (0: no budget) */ + char *end; + unsigned long long bytes = strtoull(argument, &end, 10); + if (!*argument || *end) failure = "memory"; + else pure_app_memory(&app, (size_t)bytes); } else if (!strcmp(command, "work")) printf("{\"work\":%llu}\n", (unsigned long long)app.work); /* the last event's */ else if (strcmp(command, "show")) failure = "unknown command"; if (batch && strcmp(command, "show") && ++unsaved == batch) { diff --git a/core/module-jit.c b/core/module-jit.c index 7110a19..765d3cd 100644 --- a/core/module-jit.c +++ b/core/module-jit.c @@ -1555,17 +1555,21 @@ static void append(Block *k, const PureOp *op, uint32_t pc, unsigned height) { load64(e, X0, X23, offsetof(PureApp, spent)); add_imm(e, X0, X0, bytes); store64(e, X0, X23, offsetof(PureApp, spent)); - int budgeted = new_label(e); - load64(e, X1, X23, offsetof(PureApp, memory)); - cbz_x(e, X1, budgeted); - cmp_reg(e, X10, X1); - b_cond(e, GT, fault_at(k, PURE_FAULT_MEMORY, pc)); - bind(e, budgeted); - load64(e, X1, X23, offsetof(PureApp, room)); - cmp_reg(e, X0, X1); - b_cond(e, GT, fault_at(k, PURE_FAULT_MEMORY, pc)); int head = kept_find(k, k->loop_of[pc - k->block.start], C_HEADROOM, 0, 0); - if (head >= 0 && k->fresh >> head & 1) sub_imm(e, k->kept[head].reg, k->kept[head].reg, bytes); /* the nest's books' */ + if (head >= 0 && k->fresh >> head & 1) { /* the nest's books keep the headroom: the growth they hold not in the app's yet */ + subs_imm(e, k->kept[head].reg, k->kept[head].reg, bytes); + b_cond(e, LT, fault_at(k, PURE_FAULT_MEMORY, pc)); + } else { + int budgeted = new_label(e); + load64(e, X1, X23, offsetof(PureApp, memory)); + cbz_x(e, X1, budgeted); + cmp_reg(e, X10, X1); + b_cond(e, GT, fault_at(k, PURE_FAULT_MEMORY, pc)); + bind(e, budgeted); + load64(e, X1, X23, offsetof(PureApp, room)); + cmp_reg(e, X0, X1); + b_cond(e, GT, fault_at(k, PURE_FAULT_MEMORY, pc)); + } slow_back(k, s, V_MEM, 0); } -- cgit v1.2.3