wasm_global (wasm v0.1.0)
View SourceMutable globals that two instances can share.
Read this when you link modules that share a global. Module A exports a mutable
global, module B imports it, and a global.set in either has to be visible to
the other. A value copied into each instance's state
cannot do that: the two would silently diverge, which is the same defect
imported tables had before 0.2.0.
Why not every global
A cell is an ETS row, and reading one measured 17.7 ns against 1.9 ns for the
element/2 read of an inline value. global.get is hot in real compiler
output, where the shadow stack pointer is a mutable global read on nearly every
function entry, so paying that on every global would be a poor trade for a
feature only dynamic linking uses.
So a global becomes a cell only when it is mutable and either imported or
exported, which is exactly when sharing is observable. That is decided from the
module alone, and wasm_instance resolves it into the instruction when the IR
is built, so an ordinary global.get still reads a tuple element.
Lifetime
A cell is held by whoever can reach it: the instance that created it, and every instance that imported it. It goes when the last of them lets go, so an exported global outlives the instance that created it. Nothing for you to release.
It was not so. The cell was tied to the creating process alone, so an exported
global vanished the moment that process exited and the importer's global.get
found nothing.
Summary
Functions
Add a holder, for an instance importing this global.
Whether a term is a global cell.
Create a cell, saying who holds it.
Remove a holder. The cell goes when the last one lets go.
This cell's registry identity.
Types
-nominal global() :: {wasm_global, reference()}.
An opaque, shareable handle to one mutable global.
Functions
-spec acquire(global(), wasm_keeper:token(), pid() | none) -> ok | {error, gone | keeper_unavailable}.
Add a holder, for an instance importing this global.
Whether a term is a global cell.
This doubles as the mutability check across an import boundary: an export hands over a cell for a mutable global and a bare value for an immutable one, so a module that declared the wrong mutability is refused rather than linked.
Create a cell, saying who holds it.
holder is a {Token, Owner} pair naming the registry entry to create and the
process whose death removes it. An instance passes its own token, so the cell
lives as long as anything that imported it.
-spec release(global(), wasm_keeper:token()) -> ok.
Remove a holder. The cell goes when the last one lets go.
-spec resource(global()) -> wasm_keeper:resource().
This cell's registry identity.