Repository navigation
interp: pass runtime values back to the caller - #5991
Draft
davecheney wants to merge 1 commit into
Draft
davecheney wants to merge 1 commit into
davecheney wants to merge 1 commit into
Conversation
davecheney
force-pushed
the
interp-emit-more-at-runtime
branch
from
October 22, 2026 13:16
a2e4ce3 to
abc9e3a
Compare
When an instruction has an operand that is only known at runtime, interp emits it into runtime.initAll, but runAtRuntime can only emit a few opcodes. A ret of a runtime value rolls back the whole call, so a function returning an atomic load, a volatile register read or a global written at runtime is always called at runtime, even though everything else in it was evaluated. icmp, and, or, xor, the shifts, trunc and sext roll back in the same way. Across stdlib.go and json.go on the host, cmd/maindec from github.com/davecheney/pdp11 on wasip1, and a net/http program on rp2350, ret caused 42% of 297 rollbacks and icmp another 25%. This change returns a runtime value from ret to the caller, which already treats a runtime operand as a runtime instruction, and emits the other opcodes at runtime. The same programs roll back 151 times instead of 297. No binary grows, and cmd/maindec on wasip1 is 1.5% smaller. A //go:noruntime function must still be evaluated completely, or it must survive as a call so that the noruntime check reports it. Interp now rolls back such a function if it would leave any instruction to run at runtime, including one emitted by a function it calls, instead of moving that work into runtime.initAll. In the revert test, the first z.setArr call is now expanded as its comment says it can be, instead of becoming a call at runtime.
davecheney
force-pushed
the
interp-emit-more-at-runtime
branch
from
October 22, 2026 21:23
abc9e3a to
77bf069
Compare
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When an instruction has an operand that is only known at runtime, interp emits it into runtime.initAll, but runAtRuntime can only emit a few opcodes. A ret of a runtime value rolls back the whole call, so a function returning an atomic load, a volatile register read or a global written at runtime is always called at runtime, even though everything else in it was evaluated. icmp, and, or, xor, the shifts, trunc and sext roll back in the same way.
Across stdlib.go and json.go on the host, cmd/maindec from github.com/davecheney/pdp11 on wasip1, and a net/http program on rp2350, ret caused 42% of 297 rollbacks and icmp another 25%.
This change returns a runtime value from ret to the caller, which already treats a runtime operand as a runtime instruction, and emits the other opcodes at runtime. The same programs roll back 151 times instead of 297. No binary grows, and cmd/maindec on wasip1 is 1.5% smaller.
A //go:noruntime function must still be evaluated completely, or it must survive as a call so that the noruntime check reports it. Interp now rolls back such a function if it would leave any instruction to run at runtime, including one emitted by a function it calls, instead of moving that work into runtime.initAll.
In the revert test, the first z.setArr call is now expanded as its comment says it can be, instead of becoming a call at runtime.