Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes #4695; closure iterators support for JS backend #23493

Merged
merged 8 commits into from
Apr 18, 2024
Merged

Conversation

ringabout
Copy link
Member

@ringabout ringabout commented Apr 10, 2024

fixes #4695

ref #15818

Since nkState is only for the main loop state labels and nkGotoState is used only for dispatching the :state (since #7770), it's feasible to rewrite the loop body into a single case-based dispatcher, which enables support for JS, VM backend. nkState Node is replaced by a label and Node pair and nkGotoState is only used for intermediary processing. Backends only need to implement nkBreakState and closureIterSetupExc to support closure iterators.

pending #23484

I also observed some performance boost for C backend in the release mode (not in the danger mode though, I suppose the old implementation is optimized into computed goto in the danger mode)

allPathsAsgnResult???

@zerbina
Copy link
Contributor

zerbina commented Apr 10, 2024

There's a small error in the PR description: nkBreakState, not nkGotoState, has to be implemented by the code generators in order to support closure iterators.

@ringabout
Copy link
Member Author

ringabout commented Apr 11, 2024

import asyncdispatch

proc main {.async.} =
  proc foo: Future[int] {.async.} =
    echo 1
  let x = await foo()

waitFor(main())

expands into previously

goto :state 1
var :state
state 0:

Now:

var :state
case :state
of 0:

I suppose :state is not lifted correctly

@ringabout ringabout changed the title closure iterators support for JS backend fixes #4695; closure iterators support for JS backend Apr 11, 2024
@ringabout
Copy link
Member Author

check: tests/async/tasynctry.nim

@ringabout
Copy link
Member Author

ringabout commented Apr 17, 2024

read(cast[typeof(problemCall(
  template yieldFuture() {.redefine.} =
    yield FutureBase()

  var internalTmpFuture`gensym30: FutureBase = expandValue()
  yield internalTmpFuture`gensym30
  read(cast[typeof(expandValue())](internalTmpFuture`gensym30))))](internalTmpFuture`gensym32))

Here is the problem. The previous implementation split the state on the case that there is a yield in the dest type of the cast. I don't think it's reasonable. It downgrades the performance of chained await calls and happended to work before since it execute the code without the state transition assignment.

It was translated into

state 3:
read(cast[...](...))
state 4:
:envP.`:state` = 5

But it is supposed to have a state assignement in the state 3 part

@ringabout ringabout marked this pull request as ready for review April 18, 2024 13:04
@Araq Araq merged commit 9e1d0d1 into devel Apr 18, 2024
22 checks passed
@Araq Araq deleted the pr_js_closure_iter branch April 18, 2024 16:52
Copy link
Contributor

Thanks for your hard work on this PR!
The lines below are statistics of the Nim compiler built from 9e1d0d1

Hint: mm: orc; opt: speed; options: -d:release
178495 lines; 8.481s; 752.418MiB peakmem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Problem with closure iterators in js target
3 participants