-
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
Update wiggle's BorrowChecker
implementation
#8277
Update wiggle's BorrowChecker
implementation
#8277
Conversation
This commit is a refactoring and modernization of wiggle's `BorrowChecker` implementation. This type is quite old and predates everything related to the component model for example. This type additionally predates the implementation of WASI threads for Wasmtime as well. In general, this type is old and has not been updated in a long time. Originally a `BorrowChecker` was intended to be a somewhat cheap method of enabling the host to have active safe shared and mutable borrows to guest memory. Over time though this hasn't really panned out. The WASI threads proposal, for example, doesn't allow safe shared or mutable borrows at all. Instead everything must be modeled as a copy in or copy out of data. This means that all of `wasmtime-wasi` and `wasi-common` have largely already been rewritten in such a way to minimize borrows into linear memory. Nowadays the only types that represent safe borrows are the `GuestSlice` type and its equivalents (e.g. `GuestSliceMut`, `GuestStr`, etc). These are minimally used throughout `wasi-common` and `wasmtime-wasi` and when they are used they're typically isolated to a small region of memory. This is all coupled with the facst that `BorrowChecker` never ended up being optimized. It's a `Mutex<HashMap<..>>` effectively and a pretty expensive one at that. The `Mutex` is required because `&BorrowChecker` must both allow mutations and be `Sync`. The `HashMap` is used to implement precise byte-level region checking to fulfill the original design requirements of what `wiggle` was envisioned to be. Given all that, this commit guts `BorrowChecker`'s implementation and functionality. The type is now effectively a glorified `RefCell` for the entire span of linear memory. Regions are no longer considered when borrows are made and instead a shared borrow is considered as borrowing the entirety of shared memory. This means that it's not possible to simultaneously have a safe shared and mutable borrow, even if they're disjoint, at the same time. The goal of this commit is to address performance issues seen in bytecodealliance#7973 which I've seen locally as well. The heavyweight implementation of `BorrowChecker` isn't really buying us much nowadays, especially with much development having since moved on to the component model. The hope is that this much coarser way of implementing borrow checking, which should be much more easily optimizable, is sufficient for the needs of WASI and not a whole lot else.
|
||
fn is_shared_borrowed(&self, r: Region) -> bool { | ||
self.shared_borrows.values().any(|b| b.overlaps(r)) | ||
pub fn mut_unborrow(&self, _: BorrowHandle) { |
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.
Should there be different handle types for mut vs shared borrows?
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 theory yeah, but I'm not too keen to do too much refactoring here because it's all basically a dated library on life support now. These are all ignored anyway so I should probably refactor to remove them entirely, but I'll leave that as a future TODO if necessary
Turns out we haven't been running wasi-common tests for some time in CI and they've started failing. Force enable the test at all times and then fix the test failures. The test failures here were introduced in bytecodealliance#8277 and weren't caught due to the test not running and the fix was to relax the implementation of `fd_pread` to avoid taking multiple mutable borrows.
* Fix running wasi-common tests on CI Turns out we haven't been running wasi-common tests for some time in CI and they've started failing. Force enable the test at all times and then fix the test failures. The test failures here were introduced in #8277 and weren't caught due to the test not running and the fix was to relax the implementation of `fd_pread` to avoid taking multiple mutable borrows. * Fix CI
* Fix running wasi-common tests on CI Turns out we haven't been running wasi-common tests for some time in CI and they've started failing. Force enable the test at all times and then fix the test failures. The test failures here were introduced in bytecodealliance#8277 and weren't caught due to the test not running and the fix was to relax the implementation of `fd_pread` to avoid taking multiple mutable borrows. * Fix CI
* c-api: Better differentiate between `wasm.h` and `wasmtime.h` APIs (#8344) This renames some types and adds some type aliases to help us better distinguish between `wasm.h` APIs and `wasmtime.h` APIs, primarily for `Store`-related types. In general, `WasmFoo` is related to `wasm.h` and `WasmtimeFoo` is related to `wasmtime.h`. * `StoreRef` -> `WasmStoreRef` * Introduce the `WasmStore[Data]` and `WasmStoreContext[Mut]` aliases * `StoreData` -> `WasmtimeStoreData` * `CStoreContext[Mut]` -> `WasmtimeStoreContext[Mut]` * Introduce the `Wasmtime{Store,Caller}` aliases * `wasmtime-c-api`: Improve non-support of GC references in `wasm.h` APIs (#8345) * c-api: Better differentiate between `wasm.h` and `wasmtime.h` APIs This renames some types and adds some type aliases to help us better distinguish between `wasm.h` APIs and `wasmtime.h` APIs, primarily for `Store`-related types. In general, `WasmFoo` is related to `wasm.h` and `WasmtimeFoo` is related to `wasmtime.h`. * `StoreRef` -> `WasmStoreRef` * Introduce the `WasmStore[Data]` and `WasmStoreContext[Mut]` aliases * `StoreData` -> `WasmtimeStoreData` * `CStoreContext[Mut]` -> `WasmtimeStoreContext[Mut]` * Introduce the `Wasmtime{Store,Caller}` aliases * c-api: Improve non-support of GC references in `wasm.h` APIs A couple small tweaks: error message improvements, exhaustive matching, etc... * Fix running wasi-common tests on CI (#8353) * Fix running wasi-common tests on CI Turns out we haven't been running wasi-common tests for some time in CI and they've started failing. Force enable the test at all times and then fix the test failures. The test failures here were introduced in #8277 and weren't caught due to the test not running and the fix was to relax the implementation of `fd_pread` to avoid taking multiple mutable borrows. * Fix CI * Update release notes for 20.0.0 (#8358) A busy release! * Enable the gc feature by default in the c-api (#8356) Match the Wasmtime crate in this respect * wasmtime-c-api: Add support for GC references in `wasmtime.h` APIs (#8346) Restores support for `externref` in `wasmtime_val_t`, methods for manipulating them and getting their wrapped host data, and examples/tests for these things. Additionally adds support for `anyref` in `wasmtime_val_t`, clone/delete methods similar to those for `externref`, and a few `i31ref`-specific methods. Also adds C and Rust example / test for working with `anyref`. * Fix calculation of gc refs in functions (#8355) * Fix calculation of gc refs in functions In addition to excluding i31 also exclude funcrefs. * Review comments * Remove `wasi_config_preopen_socket` from C header (#8364) This was removed in #8066 * Tidy up some headers related to shared memory (#8366) * Tidy up some headers related to shared memory * Don't declare an anonymous `struct wasmtime_sharedmemory`, instead `#include` the actual definition. * Fix an issue where a header in `sharedmemory.h` referred to a type in `extern.h` which wasn't `#include`'d. This function, `wasmtime_sharedmemory_into_extern`, additionally isn't necessary as it's no different than manually constructing it. Fix this by removing this function. * Run clang-format * c-api: Fix alignment of `wasmtime_val_*` (#8363) * c-api: Fix alignment of `wasmtime_val_*` This commit fixes an issue where `wasmtime_val_raw_t` had an incorrect alignment. In Rust `ValRaw` contains a `u128` which has an alignment of 16 but in C the representation had a smaller alignment meaning that the alignment of the two structures was different. This was seen to cause alignment faults when structure were passed from C++ to Rust, for example. This commit changes the Rust representation of `ValRaw`'s `v128` field to do the same as C which is to use `[u8; 16]`. This avoids the need to raise the alignment in C which appears to be nontrivial. Cranelift is appropriately adjusted to understand that loads/stores from `ValRaw` are no longer aligned. Technically this only applies to the `v128` field but it's not too bad to apply it to the other fields as well. * Try alternate syntax for alignof * Use `--locked` on all `cargo install` in CI, also remove non-locked example (#8369) * Use `--locked` on all `cargo install` in CI Prevents any updates to rustc or crates from accidentally causing issues by ensuring that the same set of deps is used over time. * Remove rust/WASI markdown parser example The documentation referring to this example was removed in #6994 and that forgot to remove this as well. This example is building without a lock file which is causing issues in #8368. --------- Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com>
…8277 Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com>
…8277 Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com>
* We can only have one mutable borrow at a time after #8277 Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com> * Add a test like pread/pwrite, but for read/write --------- Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com>
…ealliance#8415) * We can only have one mutable borrow at a time after bytecodealliance#8277 Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com> * Add a test like pread/pwrite, but for read/write --------- Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com>
Update the wasmtime dependency to wasmtime-20, and also remove the dependency on wasi-common in favor of using the preview1-on-preview2 implementation provided by wasmtime-wasi. There was also a change in wiggle's borrow checker for the 20.0.0 release that affected our host call implementations directly: borrows are no longer to a region, but the whole guest memory. This caused a bit of churn in the wiggle_abi tree, and I'm not completely certain that all issues have been resolved, as the test suite can only test so many paths through the host calls. For reference, here's the wiggle refactoring PR in wasmtime: bytecodealliance/wasmtime#8277.
This commit is a refactoring of the `wiggle` crate which powers the `*.witx`-based bindings generation of Wasmtime for wasip1 support. Originally `wiggle` had a full-blown runtime borrow checker which verified that borrows were disjoint when appropriate. In bytecodealliance#8277 this was removed in favor of a more coarse "either all shared or all mutable" guarantee. It turns out that this exactly matches what the Rust type system guarantees at compile time as well. This commit removes all runtime borrow checking in favor of compile-time borrow checking instead. This means that there is no longer the possibility of a runtime error arising from borrowing errors. Current bindings in Wasmtime needed no restructuring to work with this new API. The source of the refactors here are all in the `wiggle` crate. Changes include: * The `GuestPtr` type lost its type parameter. Additionally it only contains a `u32` pointer now instead. * The `GuestMemory` trait is replaced with a simple `enum` of possibilities. * Helper methods on `GuestPtr` are all moved to `GuestMemory`. * A number of abstractions were simplified now that borrow checking is no longer necessary. * Generated trait methods now all take `&mut GuestMemory<'_>` as an argument. These changes were then propagated to the `wasmtime-wasi` and `wasi-common` crates in their preview0 and preview1 implementations of WASI. All changes are just general refactors, no functional change is intended here.
This commit is a refactoring of the `wiggle` crate which powers the `*.witx`-based bindings generation of Wasmtime for wasip1 support. Originally `wiggle` had a full-blown runtime borrow checker which verified that borrows were disjoint when appropriate. In bytecodealliance#8277 this was removed in favor of a more coarse "either all shared or all mutable" guarantee. It turns out that this exactly matches what the Rust type system guarantees at compile time as well. This commit removes all runtime borrow checking in favor of compile-time borrow checking instead. This means that there is no longer the possibility of a runtime error arising from borrowing errors. Current bindings in Wasmtime needed no restructuring to work with this new API. The source of the refactors here are all in the `wiggle` crate. Changes include: * The `GuestPtr` type lost its type parameter. Additionally it only contains a `u32` pointer now instead. * The `GuestMemory` trait is replaced with a simple `enum` of possibilities. * Helper methods on `GuestPtr` are all moved to `GuestMemory`. * A number of abstractions were simplified now that borrow checking is no longer necessary. * Generated trait methods now all take `&mut GuestMemory<'_>` as an argument. These changes were then propagated to the `wasmtime-wasi` and `wasi-common` crates in their preview0 and preview1 implementations of WASI. All changes are just general refactors, no functional change is intended here.
* Remove the borrow checking from `wiggle` entirely This commit is a refactoring of the `wiggle` crate which powers the `*.witx`-based bindings generation of Wasmtime for wasip1 support. Originally `wiggle` had a full-blown runtime borrow checker which verified that borrows were disjoint when appropriate. In #8277 this was removed in favor of a more coarse "either all shared or all mutable" guarantee. It turns out that this exactly matches what the Rust type system guarantees at compile time as well. This commit removes all runtime borrow checking in favor of compile-time borrow checking instead. This means that there is no longer the possibility of a runtime error arising from borrowing errors. Current bindings in Wasmtime needed no restructuring to work with this new API. The source of the refactors here are all in the `wiggle` crate. Changes include: * The `GuestPtr` type lost its type parameter. Additionally it only contains a `u32` pointer now instead. * The `GuestMemory` trait is replaced with a simple `enum` of possibilities. * Helper methods on `GuestPtr` are all moved to `GuestMemory`. * A number of abstractions were simplified now that borrow checking is no longer necessary. * Generated trait methods now all take `&mut GuestMemory<'_>` as an argument. These changes were then propagated to the `wasmtime-wasi` and `wasi-common` crates in their preview0 and preview1 implementations of WASI. All changes are just general refactors, no functional change is intended here. * Review comments * Fix publishing of wiggle-macro crate * Fix wiggle docs
This commit is a refactoring and modernization of wiggle's
BorrowChecker
implementation. This type is quite old and predates everything related to the component model for example. This type additionally predates the implementation of WASI threads for Wasmtime as well. In general, this type is old and has not been updated in a long time.Originally a
BorrowChecker
was intended to be a somewhat cheap method of enabling the host to have active safe shared and mutable borrows to guest memory. Over time though this hasn't really panned out. The WASI threads proposal, for example, doesn't allow safe shared or mutable borrows at all. Instead everything must be modeled as a copy in or copy out of data. This means that all ofwasmtime-wasi
andwasi-common
have largely already been rewritten in such a way to minimize borrows into linear memory.Nowadays the only types that represent safe borrows are the
GuestSlice
type and its equivalents (e.g.GuestSliceMut
,GuestStr
, etc). These are minimally used throughoutwasi-common
andwasmtime-wasi
and when they are used they're typically isolated to a small region of memory.This is all coupled with the facst that
BorrowChecker
never ended up being optimized. It's aMutex<HashMap<..>>
effectively and a pretty expensive one at that. TheMutex
is required because&BorrowChecker
must both allow mutations and beSync
. TheHashMap
is used to implement precise byte-level region checking to fulfill the original design requirements of whatwiggle
was envisioned to be.Given all that, this commit guts
BorrowChecker
's implementation and functionality. The type is now effectively a glorifiedRefCell
for the entire span of linear memory. Regions are no longer considered when borrows are made and instead a shared borrow is considered as borrowing the entirety of shared memory. This means that it's not possible to simultaneously have a safe shared and mutable borrow, even if they're disjoint, at the same time.The goal of this commit is to address performance issues seen in #7973 which I've seen locally as well. The heavyweight implementation of
BorrowChecker
isn't really buying us much nowadays, especially with much development having since moved on to the component model. The hope is that this much coarser way of implementing borrow checking, which should be much more easily optimizable, is sufficient for the needs of WASI and not a whole lot else.