aboutsummaryrefslogtreecommitdiffstats
path: root/core/module.c
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-10-05 08:41:45 +0100
committereunhhu <[email protected]>2026-10-05 08:41:45 +0100
commit1ef9dd24773058f766ad80ffc7a59295fc44c92d (patch)
tree1fd00811ed87ff2976b1698d0dbed4873b44adc3 /core/module.c
parentc1d1fdde86832f8c8528135975b660b00f1a3678 (diff)
downloadpure-1ef9dd24773058f766ad80ffc7a59295fc44c92d.tar.gz
pure-1ef9dd24773058f766ad80ffc7a59295fc44c92d.zip
Compile only blocks with a loop, keep no code for a module without one, set a frame's fields one by one, and inline group_of (021)
- Compiled code paid only where blocks repeat; a block run once (a view's cell, a fold's item, most handlers) ran slower through the code's entry and its calls of step: the bank's table queries took 16-24% more instructions. Now only a block with an EACH or a LOOP is compiled, and a module with none keeps no compiled code. - run() set its whole frame each time (the compiled code's run among it); now its fields one by one. - group_of is inlined into its pass: after the executor's refactor it was a call per row (per_branch +4-5% instructions; now +1.1-1.3%).
Diffstat (limited to 'core/module.c')
-rw-r--r--core/module.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/core/module.c b/core/module.c
index c486d45..8771cab 100644
--- a/core/module.c
+++ b/core/module.c
@@ -2294,7 +2294,7 @@ static size_t group_slot(uint64_t bits, size_t capacity) {
}
/* key's group, added when absent (with add); NULL when absent, or without room. */
-static Group *group_of(struct PurePass *pass, double key, unsigned how, bool add) {
+static inline __attribute__((always_inline)) Group *group_of(struct PurePass *pass, double key, unsigned how, bool add) {
key = key == 0 ? 0 : key;
if (pass->capacity) {
for (size_t at = group_slot(order_bits(key), pass->capacity);; at = (at + 1) & (pass->capacity - 1)) {
@@ -3071,13 +3071,24 @@ int pure_run_iterate(Frame *frame) {
return how != STEP_NEXT ? how : next != UINT32_MAX ? STEP_NEXT : STEP_DONE;
}
+/* A frame for block, its fields set one by one: a block runs often (a
+ * fold's item, a view's cell), and filling the whole frame each time (the
+ * compiled code's run among it) costs more than the block. */
+static inline __attribute__((always_inline)) void open_frame(Frame *frame, const PureModule *m, PureValue *values, PureBlock block,
+ Event *ev, Slot *stack, Loop *loops) {
+ frame->m = m, frame->values = values, frame->ev = ev, frame->app = ev->app, frame->arena = ev->arena;
+ frame->stack = stack, frame->sp = 0, frame->loops = loops, frame->depth = 0;
+ frame->end = block.start + block.length;
+}
+
/* A block run by its compiled code. */
static __attribute__((noinline)) PureResult run_compiled(PureCompiled code, const PureModule *m, PureValue *values,
PureBlock block, Event *ev, Slot *result) {
Slot stack[PURE_MODULE_STACK];
Loop loops[PURE_MODULE_NESTING];
- Frame frame = {.m = m, .values = values, .ev = ev, .app = ev->app, .arena = ev->arena, .stack = stack,
- .end = block.start + block.length, .loops = loops};
+ Frame frame;
+ open_frame(&frame, m, values, block, ev, stack, loops);
+ frame.run.list = NULL; /* no run kept yet */
return finish(&frame, code(&frame), result);
}
@@ -3086,8 +3097,8 @@ static PureResult run(const PureModule *m, PureValue *values, PureBlock block, E
if (code) return run_compiled(code, m, values, block, ev, result);
Slot stack[PURE_MODULE_STACK];
Loop loops[PURE_MODULE_NESTING];
- Frame frame = {.m = m, .values = values, .ev = ev, .app = ev->app, .arena = ev->arena, .stack = stack,
- .end = block.start + block.length, .loops = loops};
+ Frame frame;
+ open_frame(&frame, m, values, block, ev, stack, loops);
int how = STEP_NEXT;
for (uint32_t pc = block.start;;) {
if (pc >= frame.end) { /* the block ran; or a loop's ran once: again, or the loop ends (its end may be its outer's) */