Repository navigation
interp: mark objects reached through the current value of a global - #5909
Draft
davecheney wants to merge 1 commit into
Draft
davecheney wants to merge 1 commit into
davecheney wants to merge 1 commit into
Conversation
When interp leaves a call for run time, the objects that the call can reach must be marked so that later loads and stores of them are not done at compile time. For a global variable, markExternal followed the pointers in the LLVM initializer of the global. But interp writes its results to those initializers only after it has finished, so a pointer that was stored to a global at compile time was not followed. For example, an init function that sets a global to the address of another global, starts a goroutine with the address of the first global, waits for the goroutine on a channel, and then reads the second global gives the old value. The goroutine changed the value through the pointer before the read. The program has no data race, and the 0.43.0 release has the same problem at all optimization levels. markExternal now follows the pointers in the current value of the object. This also reaches heap objects that interp allocated and that do not have an LLVM global yet. A global with no known value at compile time still uses its LLVM initializer. The problem was found during review of tinygo-org#5903. This change does not depend on tinygo-org#5903 or on the other interp fixes on dfc/interp-getwritable-rollback and dfc/interp-load-alias.
davecheney
force-pushed
the
dfc/interp-mark-current-buffer
branch
from
October 17, 2026 22:43
4c38f19 to
e5033db
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 interp leaves a call for run time, the objects that the call can reach must be marked so that later loads and stores of them are not done at compile time. For a global variable, markExternal followed the pointers in the LLVM initializer of the global. But interp writes its results to those initializers only after it has finished, so a pointer that was stored to a global at compile time was not followed. For example, an init function that sets a global to the address of another global, starts a goroutine with the address of the first global, waits for the goroutine on a channel, and then reads the second global gives the old value. The goroutine changed the value through the pointer before the read. The program has no data race, and the 0.43.0 release has the same problem at all optimization levels.
markExternal now follows the pointers in the current value of the object. This also reaches heap objects that interp allocated and that do not have an LLVM global yet. A global with no known value at compile time still uses its LLVM initializer.
The problem was found during review of #5903. This change does not depend on #5903 or on the other interp fixes on dfc/interp-getwritable-rollback and dfc/interp-load-alias.