Skip to content

Commit 29bf377

Browse files
authored
Limit context-local-storage length to 1 and add convention note (#501)
closes #491, closes #485
1 parent 4745bd9 commit 29bf377

File tree

3 files changed

+23
-7
lines changed

3 files changed

+23
-7
lines changed

design/mvp/Async.md

+18-5
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,14 @@ current task's context-local storage can be read and written from core wasm
226226
code by calling the [`context.get`] and [`context.set`] built-ins.
227227

228228
The context-local storage array's length is currently fixed to contain exactly
229-
2 `i32`s with the goal of allowing this array to be stored inline in whatever
229+
1 `i32` with the goal of allowing this array to be stored inline in whatever
230230
existing runtime data structure is already efficiently reachable from ambient
231231
compiled wasm code. Because module instantiation is declarative in the
232232
Component Model, the imported `context.{get,set}` built-ins can be inlined by
233233
the core wasm compiler as-if they were instructions, allowing the generated
234234
machine code to be a single load or store. This makes context-local storage a
235-
good place to store the linear-memory shadow stack pointer as well as the
236-
pointer to the struct used to implement [thread-local storage] APIs used by
237-
guest code.
235+
good place to store the pointer to the struct used to implement [thread-local
236+
storage] APIs used by guest code.
238237

239238
When [memory64] is integrated into the Component Model's Canonical ABI,
240239
`context.{get,set}` will be backwards-compatibly relaxed to allow `i64`
@@ -246,7 +245,20 @@ When [threads are added](#interaction-with-multi-threading), each thread will
246245
also get its own distinct mutable context-local storage array. This is the
247246
reason why "context-local" storage is not called "task-local" storage (where a
248247
"context" is a finer-grained unit of execution than either a "task" or a
249-
"thread").
248+
"thread"). As part of this, the context-local storage array length will be
249+
increased to 2, allowing the linear-memory stack pointer to be moved from a
250+
core wasm `global` into context-local storage.
251+
252+
Since the same mutable context-local storage cells are shared by all core wasm
253+
running under the same task/thread in the same component, the cells' contents
254+
must be carefully coordinated in the same way as native code has to carefully
255+
coordinate native ISA state (e.g., the [FS or GS segment base address]). In the
256+
common case, context-local storage is only `context.set` by the entry
257+
trampoline invoked by [`canon_lift`] and then all transitively reachable core
258+
wasm code (including from any `callback`) assumes `context.get` returns the
259+
same value. Thus, if any *non*-entry-trampoline code calls `context.set`, it is
260+
the responsibility of *that code* to restore this default assumption before
261+
allowing control flow to escape into the wild.
250262

251263
For details, see [`context.get`] in the AST explainer and [`canon_context_get`]
252264
in the Canonical ABI explainer.
@@ -937,6 +949,7 @@ comes after:
937949
[Structured Concurrency]: https://en.wikipedia.org/wiki/Structured_concurrency
938950
[Unit]: https://en.wikipedia.org/wiki/Unit_type
939951
[Thread-local Storage]: https://en.wikipedia.org/wiki/Thread-local_storage
952+
[FS or GS Segment Base Address]: https://docs.kernel.org/arch/x86/x86_64/fsgs.html
940953

941954
[AST Explainer]: Explainer.md
942955
[Lift and Lower Definitions]: Explainer.md#canonical-definitions

design/mvp/CanonicalABI.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ when threads are integrated, each `thread.spawn`ed thread would also get a
444444
fresh, zero-initialized `ContextLocalStorage`.)
445445
```python
446446
class ContextLocalStorage:
447-
LENGTH = 2
447+
LENGTH = 1
448448
array: list[int]
449449

450450
def __init__(self):
@@ -457,6 +457,9 @@ class ContextLocalStorage:
457457
def get(self, i):
458458
return self.array[i]
459459
```
460+
`LENGTH` is currently set to `1`, but the plan is to increase it to `2` once
461+
toolchains are ready to migrate the linear-memory-stack pointer from a
462+
`global` to context-local storage as part of implementing threads.
460463

461464

462465
#### Task State

design/mvp/canonical-abi/definitions.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ def write(self, vs):
358358
#### Context-Local Storage
359359

360360
class ContextLocalStorage:
361-
LENGTH = 2
361+
LENGTH = 1
362362
array: list[int]
363363

364364
def __init__(self):

0 commit comments

Comments
 (0)