Skip to content

Conversation

@niaow
Copy link
Member

@niaow niaow commented Nov 8, 2025

The compiler needs to know whether a defer is in a loop to determine whether to allocate stack or heap memory. Previously, this performed a DFS of the CFG every time a defer was found. This resulted in time complexity jointly proportional to the number of defers and the number of blocks in the function.

Now, the compiler will instead use Tarjan's strongly connected components algorithm to find cycles in linear time. The search is performed lazily, so this has minimal performance impact on functions without defers.

In order to implement Tarjan's SCC algorithm, additional state needed to be attached to the blocks. I chose to merge all of the per-block state into a single slice to simplify memory management.

@niaow
Copy link
Member Author

niaow commented Nov 8, 2025

I think I see what is going on here. I seem to have missed it since i ran mostly the non-device tests when developing this. The map seems to have been hiding the assignment with a nil block before.

The compiler needs to know whether a defer is in a loop to determine whether to allocate stack or heap memory.
Previously, this performed a DFS of the CFG every time a defer was found.
This resulted in time complexity jointly proportional to the number of defers and the number of blocks in the function.

Now, the compiler will instead use Tarjan's strongly connected components algorithm to find cycles in linear time.
The search is performed lazily, so this has minimal performance impact on functions without defers.

In order to implement Tarjan's SCC algorithm, additional state needed to be attached to the blocks.
I chose to merge all of the per-block state into a single slice to simplify memory management.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant