aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-10-06 03:46:11 +0100
committereunhhu <[email protected]>2026-10-06 03:46:11 +0100
commite1c8812473c89b96e9c1a09f3a46f8f392945b64 (patch)
tree69d15026709b48933c9f2aa282f40de6624ba12e
parent1b64ab89710a637e66604ece15d83f40ba314586 (diff)
downloadpure-e1c8812473c89b96e9c1a09f3a46f8f392945b64.tar.gz
pure-e1c8812473c89b96e9c1a09f3a46f8f392945b64.zip
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
-rw-r--r--cli/pure-run.c6
-rw-r--r--core/module-jit.c24
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);
}