aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/qreg-commands.c
diff options
context:
space:
mode:
authorRobin Haberkorn <rhaberkorn@fmsbw.de>2026-08-22 22:27:33 +0200
committerRobin Haberkorn <rhaberkorn@fmsbw.de>2026-08-22 22:27:33 +0200
commit2e097cec409182c3cb39b74489387480bf8a278f (patch)
tree47f501fa2634835cc0c70a9214f01b32f49b9d30 /src/qreg-commands.c
parent3ae89e34f6a04dd553f3871856521334a4dbe62f (diff)
optimize main state machine transitions with tail calls
* On newer GCC (>= 15) and Clang (>= 13) versions we can tail call at the end of input_cb() implementations to the next state's input_cb(), which will be optimized to jumps (often direct jumps). That is, the compilers always optimized tail calls, but we can guarantee tail calls with the __attribute__((musttail)) statement attribute. * Every `return &teco_state_xxx` has to be replaced with `TECO_RETURN(ctx, &teco_state_xxx, error)`. * This speeds up `-O2 -flto` builds by 18% (e.g. tested on grosciteco for sciteco(7)). Part of the speed up could also be because of inlining through TECO_RETURN(). * The other state machines (stringbuilding and q-reg spec) cannot currently be optimized the same way since they get their characters passed in from the "main" state machine. * All loops around callbacks could be optimized the same way. E.g. the undo token runner could also tail call into the next runner, but it's probably not important to optimize undo token executions.
Diffstat (limited to 'src/qreg-commands.c')
-rw-r--r--src/qreg-commands.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/src/qreg-commands.c b/src/qreg-commands.c
index a6390a1..d7b0a10 100644
--- a/src/qreg-commands.c
+++ b/src/qreg-commands.c
@@ -62,7 +62,7 @@ teco_state_expectqreg_input(teco_machine_main_t *ctx, gunichar chr, GError **err
case TECO_MACHINE_QREGSPEC_ERROR:
return NULL;
case TECO_MACHINE_QREGSPEC_MORE:
- return current;
+ TECO_RETURN(ctx, current, error);
case TECO_MACHINE_QREGSPEC_DONE:
break;
}
@@ -72,7 +72,8 @@ teco_state_expectqreg_input(teco_machine_main_t *ctx, gunichar chr, GError **err
* states. This means, it must usually be reset manually in got_register_cb() via:
* teco_state_expectqreg_reset(ctx);
*/
- return current->expectqreg.got_register_cb(ctx, qreg, table, error);
+ teco_state_t *next = current->expectqreg.got_register_cb(ctx, qreg, table, error);
+ TECO_RETURN(ctx, next, error);
}
static teco_state_t *