-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make local continuations direct style if possible (#777)
This PR tries to remove the overhead of CPS (and trampolining) for direct style code. Essentially, for the following code in CPS ``` let cont k(x, ks) = ... if (cond) { k(42, ks') } else { k(43, ks') } ``` we are now generating the following JS: ```javascript let x; if (cond) { x = 42 } else { x = 43 }; ... ``` This only works under the assumption that: - `k` is not used somewhere in a more first-class manner (under a different context, as part of a continuation passed to a function, etc.) - `k` is always called with the currently in scope meta continuation `ks'` (so that we can avoid assigning it -- this turns out to be essential with the feature interaction of loops) The interaction with loops was difficult to get right: - turning recursive functions into direct style loops makes additional continuations more local - making a continuation more local turns more functions into loops As a result, the function `parse_worker` (from the `parsing_dollars` benchmark) is now a tight loop. **Before the PR** ```javascript function parse_worker_0(a_1, ks_7, k_4) { const x_0 = i_0.value; function k_3(c_0, ks_4) { if (c_0 === (36)) { return () => parse_worker_0((a_1 + (1)), ks_4, k_4); } else if (c_0 === (10)) { const x_1 = s_0.value; s_0.value = (x_1 + a_1); return () => parse_worker_0(0, ks_4, k_4); } else { return SHIFT(p_0, (k_5, ks_5, k_6) => k_6($effekt.unit, ks_5), ks_4, k_4); } } if ((x_0 > n_0)) { return SHIFT(p_0, (k_7, ks_6, k_8) => k_8($effekt.unit, ks_6), ks_7, (v_r_1, ks_8) => $effekt.emptyMatch()); } else { const x_2 = j_0.value; if (x_2 === (0)) { const x_3 = i_0.value; i_0.value = (x_3 + (1)); const x_4 = i_0.value; j_0.value = x_4; return () => k_3(10, ks_7); } else { const x_5 = j_0.value; j_0.value = (x_5 - (1)); return () => k_3(36, ks_7); } } } ``` **After the PR** ```javascript function parse_worker_0(a_9, ks_293, k_236) { parse_worker_0: while (true) { const x_11 = i_13.value; let c_0 = undefined; if ((x_11 > n_17)) { return SHIFT(p_32, (k_232, ks_292, k_233) => k_233($effekt.unit, ks_292), ks_293, (v_r_95, ks_294) => $effekt.emptyMatch()); } else { const x_12 = j_0.value; if (x_12 === (0)) { const x_13 = i_13.value; i_13.value = (x_13 + (1)); const x_14 = i_13.value; j_0.value = x_14; c_0 = 10; } else { const x_15 = j_0.value; j_0.value = (x_15 - (1)); c_0 = 36; } } if (c_0 === (36)) { /* prepare tail call */ const a_8 = (a_9 + (1)); a_9 = a_8; continue parse_worker_0; } else if (c_0 === (10)) { const x_16 = s_4.value; s_4.value = (x_16 + a_9); /* prepare tail call */ const a_10 = 0; a_9 = a_10; continue parse_worker_0; } else { return SHIFT(p_32, (k_234, ks_295, k_235) => k_235($effekt.unit, ks_295), ks_293, k_236); } } } ``` Additionally, here are a few preliminary benchmark results: ![image](https://github.com/user-attachments/assets/6d3bd21a-fdcf-4149-8e0a-78ba48c4c6d2)
- Loading branch information
Showing
2 changed files
with
170 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters