Skip to content

Commit e66bf2b

Browse files
authored
CABI: Remove the zero-index special case for callback return value (#517)
1 parent 935c478 commit e66bf2b

File tree

4 files changed

+16
-19
lines changed

4 files changed

+16
-19
lines changed

design/mvp/Async.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -906,7 +906,11 @@ not externally-visible behavior.
906906
(func (export "cb") (param $event i32) (param $p1 i32) (param $p2 i32)
907907
...
908908
if (result i32) ;; if subtasks remain:
909-
i32.const 2 ;; return WAIT
909+
(i32.or ;; return (WAIT | ($wsi << 4))
910+
(i32.const 2)
911+
(i32.shl
912+
(global.get $wsi)
913+
(i32.const 4)))
910914
else ;; if no subtasks remain:
911915
...
912916
call $task_return ;; return the string result (pointer,length)

design/mvp/CanonicalABI.md

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3004,31 +3004,25 @@ returning to an event loop in `canon_lift`, with the `callback` called
30043004
repeatedly until the `EXIT` code is returned:
30053005
```python
30063006
[packed] = await call_and_trap_on_throw(callee, task, flat_args)
3007-
s = None
30083007
while True:
30093008
code,si = unpack_callback_result(packed)
3010-
if si != 0:
3011-
s = task.inst.table.get(si)
3012-
trap_if(not isinstance(s, WaitableSet))
30133009
match code:
30143010
case CallbackCode.EXIT:
30153011
task.exit()
30163012
return
30173013
case CallbackCode.YIELD:
30183014
e = await task.yield_(sync = False)
30193015
case CallbackCode.WAIT:
3020-
trap_if(not s)
3016+
s = task.inst.table.get(si)
3017+
trap_if(not isinstance(s, WaitableSet))
30213018
e = await task.wait_for_event(s, sync = False)
30223019
case CallbackCode.POLL:
3023-
trap_if(not s)
3020+
s = task.inst.table.get(si)
3021+
trap_if(not isinstance(s, WaitableSet))
30243022
e = await task.poll_for_event(s, sync = False)
30253023
event_code, p1, p2 = e
30263024
[packed] = await call_and_trap_on_throw(opts.callback, task, [event_code, p1, p2])
30273025
```
3028-
One detail worth noting here is that the index of the waitable set does not need
3029-
to be returned every time; as an optimization to avoid a table access on every
3030-
turn of the event loop, if the returned waitable set index is `0` (which is an
3031-
invalid table index), the previous waitable set will be used.
30323026

30333027
The bit-packing scheme used for the `i32` `packed` return value is defined as
30343028
follows:

design/mvp/canonical-abi/definitions.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,23 +1866,21 @@ async def canon_lift(opts, inst, ft, callee, caller, on_start, on_resolve, on_bl
18661866
return
18671867

18681868
[packed] = await call_and_trap_on_throw(callee, task, flat_args)
1869-
s = None
18701869
while True:
18711870
code,si = unpack_callback_result(packed)
1872-
if si != 0:
1873-
s = task.inst.table.get(si)
1874-
trap_if(not isinstance(s, WaitableSet))
18751871
match code:
18761872
case CallbackCode.EXIT:
18771873
task.exit()
18781874
return
18791875
case CallbackCode.YIELD:
18801876
e = await task.yield_(sync = False)
18811877
case CallbackCode.WAIT:
1882-
trap_if(not s)
1878+
s = task.inst.table.get(si)
1879+
trap_if(not isinstance(s, WaitableSet))
18831880
e = await task.wait_for_event(s, sync = False)
18841881
case CallbackCode.POLL:
1885-
trap_if(not s)
1882+
s = task.inst.table.get(si)
1883+
trap_if(not isinstance(s, WaitableSet))
18861884
e = await task.poll_for_event(s, sync = False)
18871885
event_code, p1, p2 = e
18881886
[packed] = await call_and_trap_on_throw(opts.callback, task, [event_code, p1, p2])

design/mvp/canonical-abi/run_tests.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ async def core_producer_pre(fut, task, args):
683683
producer2 = partial(canon_lift, producer_opts, producer_inst, producer_ft, core_producer2)
684684

685685
consumer_ft = FuncType([],[U32Type()])
686+
seti = 0
686687
async def consumer(task, args):
687688
assert(len(args) == 0)
688689

@@ -696,6 +697,7 @@ async def consumer(task, args):
696697
assert(subi2 == 2)
697698
assert(state == Subtask.State.STARTED)
698699

700+
nonlocal seti
699701
[seti] = await canon_waitable_set_new(task)
700702
assert(seti == 3)
701703
[] = await canon_waitable_join(task, subi1, seti)
@@ -707,7 +709,6 @@ async def consumer(task, args):
707709

708710
async def callback(task, args):
709711
assert(len(args) == 3)
710-
seti = 1
711712
[ctx] = await canon_context_get('i32', 0, task)
712713
match ctx:
713714
case 42:
@@ -723,7 +724,7 @@ async def callback(task, args):
723724
assert(args[2] == 0)
724725
fut2.set_result(None)
725726
[] = await canon_context_set('i32', 0, task, 62)
726-
return [definitions.CallbackCode.WAIT]
727+
return [definitions.CallbackCode.WAIT | (seti << 4)]
727728
case 62:
728729
assert(args[0] == EventCode.SUBTASK)
729730
assert(args[1] == 2)

0 commit comments

Comments
 (0)