-
Notifications
You must be signed in to change notification settings - Fork 787
Provide Module& parameter to operateOnScopeNameUsesAndSentTypes #6096
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
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
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
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
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
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
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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The root of this sequence of changes appears to be adding
Module& wasm
here. That leads to needing the module in the newBranchTypeSeeker
which leads toBlock::finalize
needing it, which leads to lots of changes.However, I do not actually see
Module& wasm
used here inoperateOnScopeNameUsesAndSentTypes
, so I don't yet understand the motivation. Reading the code in #6083 I don't seewasm
used there. I do see some discussion in https://github.com/WebAssembly/binaryen/pull/6083/files#r1382658351 but I can't understand it 😄 Probably because it speaks about wasm proposals I am not familiar with.What I am trying to understand is: what would the code look like, that uses
Module& wasm
here?I ask because this PR looks like a very large refactoring of the sort we've tried to avoid in general. For example,
RefFunc
could in theory read the type of the function from the Module, but we purposefully do not do that inReFinalize::visitRefFunc
, and instead rely on it being set initially in a correct manner, and then we just preserve it there (and anyone that changes a Function's type is responsible for updatingRefFunc
s). In that case it avoids parallelism risks of modifying one function's type while modifying the contents of another, for example - in general, we try to avoid reading global state like this for Expressions.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The core problem is that the new
resume
instruction from typed continuations and the newtry_table
instruction from the redesigned EH proposal act as a branches where the sent types depends on tag types. We currently depend on being able to determine the sent type of branches just by inspecting the branchingExpression
, but the new dependencies on tag types means that determining the types of branches requires being able to look up the tags on the module as well.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's right.
Sorry, I realize that this PR and the linked one do a bad job at showing what the
Module&
is actually needed for.From a high-level perspective, the typed continuations proposal allows writing something like this:
This means that if you
suspend
to the tag$mytag
while running the continuation$mycont
, then execution continues after $myblock. The type of the data that is provided to$myblock
depends on the types of the tag used and the type of the continuation (the latter is$ct
here).Something very similar will happen for the new EH proposal, where exception handlers are just ordinary blocks, and
throw
jumps to them, with additional data.Practically speaking, for
operateOnScopeNameUsesAndSentTypes
this means that we need to do something like this:I agree that this is a rather large refactoring. Id be happy to hear if there are ways of decreasing its footprint somehow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation!
Can we simply duplicate the type into the resume? This is what we do in practice for e.g. RefFunc today: the type of each RefFunc mirrors the module's information about the function's signature. Likewise a Call mirrors the returns of the signature, etc. While in general such duplication is not great, it allows us to avoid reading global state constantly.
If that can't work, maybe elaborate on what
i
is in that example, and whattype send to label is calculated
means in practice? (if those things are referring to some kind of "dynamic" read from the module, then simple mirroring of a single value might not work, but I hope that's not the case here...) For the new EH proposal, at least, I think this should work.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both of the new instructions take a vector of (tag, label) pairs, so they're similar to
br_table
except that they can potentially send different types to each of the labels. If we want to store the sent types directly in the newExpression
s, they would have to beArenaVector<Type>
rather than just a single type.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is nothing prohibiting this from a technical perspective. Note that in general, each
resume
instruction has a list of(tag $sometag $someblock)
clauses, where my example above only used one. This means that we would have to duplicate theSignature
s of all of the tags into theResume
object.I just used the
i
to reflect that theResume
node actually contains a list of tags and a list of blocks, together representing a(tag $sometag $someblock)
entry. I was trying to hand-wave this away, becauseoperateOnScopeNameUsesAndSentTypes
needs some unrelated adapation to avoid a quadratic blowup because of this, but that is independent from the need to have access to theModule
.But coming back to your actual question: The information we need from the
Module
is entirely static. We just need access to the param and results types that were given when defining the tags in the tags section of the module.More concretely, the types of the values that flow into a handler block (such as
$myblock
in my example above) are then a) the param types of the tag used, followed by b) a continuation type. The latter continuation type is determined entirely by the result types of the tag and the type of theresume
d continuation (which can be read off from the instruction itself).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, in my previous comment I mentioned storing the signtatures of each of the tag in the
Resume
node for each(tag ...)
clause, but we may equally store the sent types directly. Note that these are often tuples, because the types sent to the handler are the param types of the corresponding tag, followed by a continuation type.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, thanks, that it's a list of types is the tricky part then.
An
ArenaVector<Type>
seems like a reasonable way to proceed here, since I don't think we will have very many such nodes and not very long lists in them? For EH at least for C++ I believe the list will always be of length 1 (the single standard C++ exception tag with a pointer in it).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, the size of the
ArenaVector<Type>
itself will be equal to the number of(tag ...)
clauses of theresume
instruction. EachType
will then be a tuple type with n_i + 1 elements, where n_i is the number of parameters of the tag used by the i-th clause.I think it's difficult to give a meaningful estimate of how many
(tag ...)
clauses aresume
instruction will usually have, and how manyparams
the involved tags will have. But I would be surprised to see larger numbers of each.Going back to your original concerns about this refactoring, I don't quite understand what you meant by the following:
Were you concerned that we are relying on some kind of global mutable state here? Luckily, this is not the case. Or was your concern more generally about the fact that in, say,
Block::finalize(Module& wasm)
we would be relying on information that is maintained outside of the block in question? That is definitely true.During the refactoring, it seemed like the
Module
was usually in reach and just needed to be passed on to additional places (which arguably then sums up to: quite a lot of additional places).I don't mind discarding this PR and adding the
ArenaVector
to theResume
nodes in #6083 if that is your preferred option.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry if I wasn't clear about the parallelism. Yes, in this case it is safe. I was trying to give an example of why we avoid reading global state in general, one reason for which is that in some situations it is unsafe.
I do prefer to add an ArenaVector. It's less of a change, and it is more consistent with our existing coding style, I think. If we see it adds significant overhead in practice we can always optimize it later.