For host VM code, we use plain reference counting, where cloning increments
the reference count, and dropping decrements it. We can avoid many of the
on-stack increment/decrement operations that typically plague the
performance of reference counting via Rust's ownership and borrowing system.
Moving a `VMExternRef` avoids mutating its reference count, and borrowing it
either avoids the reference count increment or delays it until if/when the
`VMExternRef` is cloned.
When passing a `VMExternRef` into compiled Wasm code, we don't want to do
reference count mutations for every compiled `local.{get,set}`, nor for
every function call. Therefore, we use a variation of **deferred reference
counting**, where we only mutate reference counts when storing
`VMExternRef`s somewhere that outlives the activation: into a global or
table. Simultaneously, we over-approximate the set of `VMExternRef`s that
are inside Wasm function activations. Periodically, we walk the stack at GC
safe points, and use stack map information to precisely identify the set of
`VMExternRef`s inside Wasm activations. Then we take the difference between
this precise set and our over-approximation, and decrement the reference
count for each of the `VMExternRef`s that are in our over-approximation but
not in the precise set. Finally, the over-approximation is replaced with the
precise set.
The `VMExternRefActivationsTable` implements the over-approximized set of
`VMExternRef`s referenced by Wasm activations. Calling a Wasm function and
passing it a `VMExternRef` moves the `VMExternRef` into the table, and the
compiled Wasm function logically "borrows" the `VMExternRef` from the
table. Similarly, `global.get` and `table.get` operations clone the gotten
`VMExternRef` into the `VMExternRefActivationsTable` and then "borrow" the
reference out of the table.
When a `VMExternRef` is returned to host code from a Wasm function, the host
increments the reference count (because the reference is logically
"borrowed" from the `VMExternRefActivationsTable` and the reference count
from the table will be dropped at the next GC).
For more general information on deferred reference counting, see *An
Examination of Deferred Reference Counting and Cycle Detection* by Quinane:
https://openresearch-repository.anu.edu.au/bitstream/1885/42030/2/hon-thesis.pdf
cc #929
Fixes #1804
35 lines
940 B
TOML
35 lines
940 B
TOML
[package]
|
|
name = "wasmtime-runtime"
|
|
version = "0.18.0"
|
|
authors = ["The Wasmtime Project Developers"]
|
|
description = "Runtime library support for Wasmtime"
|
|
documentation = "https://docs.rs/wasmtime-runtime"
|
|
license = "Apache-2.0 WITH LLVM-exception"
|
|
categories = ["wasm"]
|
|
keywords = ["webassembly", "wasm"]
|
|
repository = "https://github.com/bytecodealliance/wasmtime"
|
|
readme = "README.md"
|
|
edition = "2018"
|
|
|
|
[dependencies]
|
|
wasmtime-environ = { path = "../environ", version = "0.18.0" }
|
|
region = "2.0.0"
|
|
libc = { version = "0.2.70", default-features = false }
|
|
log = "0.4.8"
|
|
memoffset = "0.5.3"
|
|
indexmap = "1.0.2"
|
|
thiserror = "1.0.4"
|
|
more-asserts = "0.2.1"
|
|
cfg-if = "0.1.9"
|
|
backtrace = "0.3.42"
|
|
lazy_static = "1.3.0"
|
|
|
|
[target.'cfg(target_os = "windows")'.dependencies]
|
|
winapi = { version = "0.3.7", features = ["winbase", "memoryapi", "errhandlingapi"] }
|
|
|
|
[build-dependencies]
|
|
cc = "1.0"
|
|
|
|
[badges]
|
|
maintenance = { status = "actively-developed" }
|