Skip to content

Commit ee4822a

Browse files
committed
CABI: give Table its own subsection heading, reorder ResourceHandle/ResourceType
1 parent a0bc232 commit ee4822a

File tree

2 files changed

+91
-84
lines changed

2 files changed

+91
-84
lines changed

design/mvp/CanonicalABI.md

Lines changed: 58 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ being specified here.
1212
* [Canonical ABI Options](#canonical-abi-options)
1313
* [Runtime State](#runtime-state)
1414
* [Component Instance State](#component-instance-state)
15+
* [Table State](#table-state)
1516
* [Resource State](#resource-state)
1617
* [Task State](#task-state)
1718
* [Buffer, Stream and Future State](#buffer-stream-and-future-state)
@@ -172,60 +173,12 @@ class ComponentInstance:
172173
self.starting_pending_task = False
173174
```
174175

176+
#### Table State
175177

176-
#### Resource State
177-
178-
The `ResourceTables` stored in the `resources` field maps `ResourceType`s to
179-
`Table`s of `ResourceHandle`s (defined next), establishing a separate
180-
`i32`-indexed array per resource type:
181-
```python
182-
class ResourceTables:
183-
rt_to_table: MutableMapping[ResourceType, Table[ResourceHandle]]
184-
185-
def __init__(self):
186-
self.rt_to_table = dict()
187-
188-
def table(self, rt):
189-
if rt not in self.rt_to_table:
190-
self.rt_to_table[rt] = Table[ResourceHandle]()
191-
return self.rt_to_table[rt]
192-
193-
def get(self, rt, i):
194-
return self.table(rt).get(i)
195-
def add(self, rt, h):
196-
return self.table(rt).add(h)
197-
def remove(self, rt, i):
198-
return self.table(rt).remove(i)
199-
```
200-
While this Python code performs a dynamic hash-table lookup on each handle
201-
table access, as we'll see below, the `rt` parameter is always statically known
202-
such that a normal implementation can statically enumerate all `Table` objects
203-
at compile time and then route the calls to `get`, `add` and `remove` to the
204-
correct `Table` at the callsite. The net result is that each component instance
205-
will contain one handle table per resource type used by the component, with
206-
each compiled adapter function accessing the correct handle table as-if it were
207-
a global variable.
208-
209-
The `ResourceType` class represents a concrete resource type that has been
210-
created by the component instance `impl`. `ResourceType` objects are used as
211-
keys by `ResourceTables` above and thus we assume that Python object identity
212-
corresponds to resource type equality, as defined by [type checking] rules.
213-
```python
214-
class ResourceType(Type):
215-
impl: ComponentInstance
216-
dtor: Optional[Callable]
217-
dtor_sync: bool
218-
dtor_callback: Optional[Callable]
219-
220-
def __init__(self, impl, dtor = None, dtor_sync = True, dtor_callback = None):
221-
self.impl = impl
222-
self.dtor = dtor
223-
self.dtor_sync = dtor_sync
224-
self.dtor_callback = dtor_callback
225-
```
226-
The `Table` class, used by `ResourceTables` above, encapsulates a single
227-
mutable, growable array of generic elements, indexed by Core WebAssembly
228-
`i32`s.
178+
The generic `Table` class, used by the `resources`, `waitables` and
179+
`error_contexts` fields of `ComponentInstance` above, encapsulates a single
180+
mutable, growable array of elements that are represented in Core WebAssembly as
181+
`i32` indices into the array.
229182
```python
230183
ElemT = TypeVar('ElemT')
231184
class Table(Generic[ElemT]):
@@ -277,6 +230,40 @@ The limit of `2**30` ensures that the high 2 bits of table indices are unset
277230
and available for other use in guest code (e.g., for tagging, packed words or
278231
sentinel values).
279232

233+
234+
#### Resource State
235+
236+
The `ResourceTables` stored in the `resources` field maps `ResourceType`s to
237+
`Table`s of `ResourceHandle`s (defined next), establishing a separate
238+
`i32`-indexed array per resource type:
239+
```python
240+
class ResourceTables:
241+
rt_to_table: MutableMapping[ResourceType, Table[ResourceHandle]]
242+
243+
def __init__(self):
244+
self.rt_to_table = dict()
245+
246+
def table(self, rt):
247+
if rt not in self.rt_to_table:
248+
self.rt_to_table[rt] = Table[ResourceHandle]()
249+
return self.rt_to_table[rt]
250+
251+
def get(self, rt, i):
252+
return self.table(rt).get(i)
253+
def add(self, rt, h):
254+
return self.table(rt).add(h)
255+
def remove(self, rt, i):
256+
return self.table(rt).remove(i)
257+
```
258+
While this Python code performs a dynamic hash-table lookup on each handle
259+
table access, as we'll see below, the `rt` parameter is always statically known
260+
such that a normal implementation can statically enumerate all `Table` objects
261+
at compile time and then route the calls to `get`, `add` and `remove` to the
262+
correct `Table` at the callsite. The net result is that each component instance
263+
will contain one handle table per resource type used by the component, with
264+
each compiled adapter function accessing the correct handle table as-if it were
265+
a global variable.
266+
280267
The `ResourceHandle` class defines the elements of the per-resource-type
281268
`Table`s stored in `ResourceTables`:
282269
```python
@@ -315,6 +302,24 @@ table only contains `own` or `borrow` handles and then, based on this,
315302
statically eliminate the `own` and the `lend_count` xor `borrow_scope` fields,
316303
and guards thereof.
317304

305+
The `ResourceType` class represents a concrete resource type that has been
306+
created by the component instance `impl`. `ResourceType` objects are used as
307+
keys by `ResourceTables` above and thus we assume that Python object identity
308+
corresponds to resource type equality, as defined by [type checking] rules.
309+
```python
310+
class ResourceType(Type):
311+
impl: ComponentInstance
312+
dtor: Optional[Callable]
313+
dtor_sync: bool
314+
dtor_callback: Optional[Callable]
315+
316+
def __init__(self, impl, dtor = None, dtor_sync = True, dtor_callback = None):
317+
self.impl = impl
318+
self.dtor = dtor
319+
self.dtor_sync = dtor_sync
320+
self.dtor_callback = dtor_callback
321+
```
322+
318323

319324
#### Task State
320325

design/mvp/canonical-abi/definitions.py

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -227,37 +227,7 @@ def __init__(self):
227227
self.pending_tasks = []
228228
self.starting_pending_task = False
229229

230-
#### Resource State
231-
232-
class ResourceTables:
233-
rt_to_table: MutableMapping[ResourceType, Table[ResourceHandle]]
234-
235-
def __init__(self):
236-
self.rt_to_table = dict()
237-
238-
def table(self, rt):
239-
if rt not in self.rt_to_table:
240-
self.rt_to_table[rt] = Table[ResourceHandle]()
241-
return self.rt_to_table[rt]
242-
243-
def get(self, rt, i):
244-
return self.table(rt).get(i)
245-
def add(self, rt, h):
246-
return self.table(rt).add(h)
247-
def remove(self, rt, i):
248-
return self.table(rt).remove(i)
249-
250-
class ResourceType(Type):
251-
impl: ComponentInstance
252-
dtor: Optional[Callable]
253-
dtor_sync: bool
254-
dtor_callback: Optional[Callable]
255-
256-
def __init__(self, impl, dtor = None, dtor_sync = True, dtor_callback = None):
257-
self.impl = impl
258-
self.dtor = dtor
259-
self.dtor_sync = dtor_sync
260-
self.dtor_callback = dtor_callback
230+
#### Table State
261231

262232
ElemT = TypeVar('ElemT')
263233
class Table(Generic[ElemT]):
@@ -292,6 +262,26 @@ def remove(self, i):
292262
self.free.append(i)
293263
return e
294264

265+
#### Resource State
266+
267+
class ResourceTables:
268+
rt_to_table: MutableMapping[ResourceType, Table[ResourceHandle]]
269+
270+
def __init__(self):
271+
self.rt_to_table = dict()
272+
273+
def table(self, rt):
274+
if rt not in self.rt_to_table:
275+
self.rt_to_table[rt] = Table[ResourceHandle]()
276+
return self.rt_to_table[rt]
277+
278+
def get(self, rt, i):
279+
return self.table(rt).get(i)
280+
def add(self, rt, h):
281+
return self.table(rt).add(h)
282+
def remove(self, rt, i):
283+
return self.table(rt).remove(i)
284+
295285
class ResourceHandle:
296286
rep: int
297287
own: bool
@@ -304,6 +294,18 @@ def __init__(self, rep, own, borrow_scope = None):
304294
self.borrow_scope = borrow_scope
305295
self.lend_count = 0
306296

297+
class ResourceType(Type):
298+
impl: ComponentInstance
299+
dtor: Optional[Callable]
300+
dtor_sync: bool
301+
dtor_callback: Optional[Callable]
302+
303+
def __init__(self, impl, dtor = None, dtor_sync = True, dtor_callback = None):
304+
self.impl = impl
305+
self.dtor = dtor
306+
self.dtor_sync = dtor_sync
307+
self.dtor_callback = dtor_callback
308+
307309
#### Task State
308310

309311
class CallState(IntEnum):

0 commit comments

Comments
 (0)