summaryrefslogtreecommitdiffstats
path: root/src/compile.c
diff options
context:
space:
mode:
authorNicolas Williams <nico@cryptonector.com>2017-12-11 11:20:16 -0600
committerNicolas Williams <nico@cryptonector.com>2017-12-11 11:20:16 -0600
commit9a4576e7567dd38b91f28592b47eb6dafe0c4332 (patch)
tree3f825020433fd48aafd9d424f1095abe099a9abf /src/compile.c
parentb5560d8420d330c4f90b3282c028bba476b01c1c (diff)
Revert "reduce: handle empty updates (fix #1313)"
This reverts commit e24af3c78e78a3aab05a2800d825d56f1d842b1b. While the semantics are desirable, there is no way to implement them efficiently. The reason is that in order to handle backtracking (empty) from the state update expression, we have to retain a reference to the reduction state value in order to restore it upon backtracking. Retaining a reference to the reduction state kills performance by causing lots of additional memory allocations and garbage because the input to the update expression will always have at least two references, thus no changes to it can be done in-place, and all changes end up being CoW changes. Avoiding this is the very reason for the LOADVN instruction (leaving `null` in the variable loaded from).
Diffstat (limited to 'src/compile.c')
-rw-r--r--src/compile.c22
1 files changed, 1 insertions, 21 deletions
diff --git a/src/compile.c b/src/compile.c
index afd42aed..33a8e72c 100644
--- a/src/compile.c
+++ b/src/compile.c
@@ -823,32 +823,12 @@ static block bind_alternation_matchers(block matchers, block body) {
block gen_reduce(block source, block matcher, block init, block body) {
block res_var = gen_op_var_fresh(STOREV, "reduce");
- block update_var = gen_op_bound(STOREV, res_var);
- block jmp = gen_op_targetlater(JUMP);
- if (body.last == NULL) {
- inst_set_target(jmp, jmp);
- } else {
- inst_set_target(jmp, body);
- }
block loop = BLOCK(gen_op_simple(DUPN),
source,
bind_alternation_matchers(matcher,
BLOCK(gen_op_bound(LOADVN, res_var),
- /*
- * We fork to the body, jump to
- * the STOREV. This means that
- * if body produces no results
- * (i.e., it just does empty)
- * then we keep the current
- * reduction state as-is.
- *
- * To break out of a
- * reduction... use break.
- */
- gen_op_target(FORK, jmp),
- jmp,
body,
- update_var)),
+ gen_op_bound(STOREV, res_var))),
gen_op_simple(BACKTRACK));
return BLOCK(gen_op_simple(DUP),
init,