-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Refactor vm::Instance
for better Store
safety
#9565
Merged
fitzgen
merged 3 commits into
bytecodealliance:main
from
fitzgen:instance-and-store-split
Nov 5, 2024
Merged
Refactor vm::Instance
for better Store
safety
#9565
fitzgen
merged 3 commits into
bytecodealliance:main
from
fitzgen:instance-and-store-split
Nov 5, 2024
Conversation
This file contains 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
At various times, for example in libcalls, we need to go from a raw `vmctx` pointer that Wasm gave us to both an `&mut Instance` and an `&mut Store{Opaque,Context}`. This is a pretty fundamental unsafe aspect of implementing a language runtimne in Rust, but we can tighten things up a bit and make them a little safer than they currently are. This commit is such an attempt and is notably tackling the issue of creating multiple store borrows after we have an instance borrow. This commit makes the following changes: * `Instance` doesn't expose a method to get the raw `*mut dyn VMStore` pointer or otherwise create a store borrow. * You cannot construct an `Instance` directly from a `vmctx` pointer. * There is now an `InstanceAndStore` type that represents unique access to both an `Instance` and a `Store`. * You can (with `unsafe`) create an `InstanceAndStore` from a raw `vmctx` pointer. This generally only happens inside a couple "bottlenecks", not all throughout the codebase, like the shared plumbing code for libcalls. * The `InstanceAndStore` can be unpacked into a mutable borrow of an `Instance` and a mutable borrow of a `Store`. This unpacking takes holds a mutable borrow of the original `InstanceAndStore`, so double borrows of the store are no longer a concern, so long as you don't use `unsafe` to create new `InstanceAndStore`s for the same `vmctx`. * All `Instance` methods and functions that previously would unsafely turn the `Instance`'s internal store pointer into a store borrow to perform some action now take a store argument, and this store is threaded around as necessary. Altogether, I feel that we've ended up with an architecture that is a safety improvement over where we were previously, and will help us properly avoid Rust UB. For what its worth, I do not think this is the end state. I foresee at least two additional follow ups that I unfortunately do not currently have time for: 1. Create `ComponentInstanceAndStore`, which is the same thing that this commit did but for components. I started on this but ran out of fuel while trying to update macros for all the component shims and transcoders. 2. Stop dealing with `&mut vm::Table`s and `&mut vm::Global`s and all that in the runtime. Instead just deal with indices, similar to how things are structured in the host API level. This refactoring was not previously possible due to (1) the `wasmtime` versus `wasmtime-runtime` crate split and (2) the lack of `StoreOpaque`s threaded through the VM internals. The first blocker was addressed a few months ago, this commit removes the second blocker. This will still be a pretty large refactoring though, but I think ultimately will be worth it.
fitzgen
force-pushed
the
instance-and-store-split
branch
from
November 5, 2024 20:43
b058063
to
e67f00d
Compare
alexcrichton
reviewed
Nov 5, 2024
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.
Looks great 👍
One comment about the 'static
though on the dyn VMStore
type though.
alexcrichton
approved these changes
Nov 5, 2024
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.
At various times, for example in libcalls, we need to go from a raw
vmctx
pointer that Wasm gave us to both an&mut Instance
and an&mut Store{Opaque,Context}
. This is a pretty fundamental unsafe aspect of implementing a language runtimne in Rust, but we can tighten things up a bit and make them a little safer than they currently are. This commit is such an attempt and is notably tackling the issue of creating multiple store borrows after we have an instance borrow.This commit makes the following changes:
Instance
doesn't expose a method to get the raw*mut dyn VMStore
pointer or otherwise create a store borrow.You cannot construct an
Instance
directly from avmctx
pointer.There is now an
InstanceAndStore
type that represents unique access to both anInstance
and aStore
.You can (with
unsafe
) create anInstanceAndStore
from a rawvmctx
pointer. This generally only happens inside a couple "bottlenecks", not all throughout the codebase, like the shared plumbing code for libcalls.The
InstanceAndStore
can be unpacked into a mutable borrow of anInstance
and a mutable borrow of aStore
. This unpacking takes holds a mutable borrow of the originalInstanceAndStore
, so double borrows of the store are no longer a concern, so long as you don't useunsafe
to create newInstanceAndStore
s for the samevmctx
.All
Instance
methods and functions that previously would unsafely turn theInstance
's internal store pointer into a store borrow to perform some action now take a store argument, and this store is threaded around as necessary.Altogether, I feel that we've ended up with an architecture that is a safety improvement over where we were previously, and will help us properly avoid Rust UB.
For what its worth, I do not think this is the end state. I foresee at least two additional follow ups that I unfortunately do not currently have time for:
Create
ComponentInstanceAndStore
, which is the same thing that this commit did but for components. I started on this but ran out of fuel while trying to update macros for all the component shims and transcoders.Stop dealing with
&mut vm::Table
s and&mut vm::Global
s and all that in the runtime. Instead just deal with indices, similar to how things are structured in the host API level. This refactoring was not previously possible due to (1) thewasmtime
versuswasmtime-runtime
crate split and (2) the lack ofStoreOpaque
s threaded through the VM internals. The first blocker was addressed a few months ago, this commit removes the second blocker. This will still be a pretty large refactoring though, but I think ultimately will be worth it.