@@ -483,8 +483,8 @@ a task function would ordinarily return, it should instead switch to
483483the next task. When doing so, it should pass a new flag to the target
484484continuation to indicate that the source continuation should not be
485485enqueued in the task list, but should instead be cancelled. Cancellation
486- can be implemented using another instruction , ` resume_throw ` , which is
487- described later in the document.
486+ can be implemented using two more instructions , ` resume_throw ` and
487+ ` resume_throw_ref ` , which are described later in the document.
488488
489489Full versions of ` $scheduler1 ` and ` $scheduler2 ` can be found
490490[ here] ( examples/scheduler1.wast ) and [ here] ( examples/scheduler2.wast ) .
@@ -543,7 +543,7 @@ The following instruction creates a *suspended continuation* from a
543543function.
544544
545545``` wast
546- cont.new $ct : [(ref $ft)] -> [(ref $ct)]
546+ cont.new $ct : [(ref null $ft)] -> [(ref $ct)]
547547 where:
548548 - $ft = func [t1*] -> [t2*]
549549 - $ct = cont $ft
@@ -561,7 +561,7 @@ continuation under a *handler*. The handler specifies what to do when
561561control is subsequently suspended again.
562562
563563``` wast
564- resume $ct hdl* : [t1* (ref $ct)] -> [t2*]
564+ resume $ct hdl* : [t1* (ref null $ct)] -> [t2*]
565565 where:
566566 - $ct = cont [t1*] -> [t2*]
567567```
@@ -581,7 +581,7 @@ The second way to invoke a continuation is to raise an exception at
581581the control tag invocation site which causes the stack to be unwound.
582582
583583``` wast
584- resume_throw $ct $exn hdl* : [te* (ref $ct)] )] -> [t2*]
584+ resume_throw $ct $exn hdl* : [te* (ref null $ct)] -> [t2*]
585585 where:
586586 - $ct = cont [t1*] -> [t2*]
587587 - $exn : [te*] -> []
@@ -597,11 +597,24 @@ exception is being raised (the continuation is not actually being
597597supplied a value) the parameter types for the continuation ` t1* ` are
598598unconstrained.
599599
600+ Exceptions can also be raised at a suspension site using
601+ ` resume_throw_ref ` .
602+
603+ ``` wast
604+ resume_throw_ref $ct hdl* : [exnref (ref null $ct)] -> [t2*]
605+ where:
606+ - $ct = cont [t1*] -> [t2*]
607+ ```
608+
609+ The ` resume_throw_ref ` instruction is identical to the ` resume_throw `
610+ instruction except that the exception it raises is given by an exnref
611+ operand rather than by an exception tag immediate.
612+
600613The third way to invoke a continuation is to perform a symmetric
601614switch.
602615
603616``` wast
604- switch $ct1 $e : [t1* (ref $ct1)] -> [t2*]
617+ switch $ct1 $e : [t1* (ref null $ct1)] -> [t2*]
605618 where:
606619 - $e : [] -> [t*]
607620 - $ct1 = cont [t1* (ref $ct2)] -> [t*]
@@ -614,8 +627,9 @@ continuation argument (`$ct1`) and a control tag
614627performs a direct switch to the suspended peer continuation (of type
615628` $ct1 ` ), passing in the required parameters (including the just
616629suspended current continuation, in order to allow the peer to switch
617- back again). As with ` resume ` and ` resume_throw ` , the ` switch `
618- instruction fully consumes its suspended continuation argument.
630+ back again). As with ` resume ` , ` resume_throw ` , and ` resume_throw_ref ` ,
631+ the ` switch ` instruction fully consumes its suspended continuation
632+ argument.
619633
620634### Suspending continuations
621635
@@ -641,7 +655,7 @@ A suspended continuation can be partially applied to a prefix of its
641655arguments yielding another suspended continuation.
642656
643657``` wast
644- cont.bind $ct1 $ct2 : [t1* (ref $ct1)] -> [(ref $ct2)]
658+ cont.bind $ct1 $ct2 : [t1* (ref null $ct1)] -> [(ref $ct2)]
645659 where:
646660 - $ct1 = cont [t1* t3*] -> [t2*]
647661 - $ct2 = cont [t3*] -> [t2*]
@@ -672,21 +686,23 @@ preallocating one slot for each continuation argument.
672686
673687#### Consuming continuations
674688
675- There are four different ways in which suspended continuations are
676- consumed (` resume,resume_throw,switch,cont.bind ` ). A suspended
677- continuation may be resumed with a particular handler with ` resume ` ;
678- aborted with ` resume_throw ` ; directly switched to via ` switch ` ; or
679- partially applied with ` cont.bind ` .
689+ There are five different ways in which suspended continuations are
690+ consumed (` resume ` , ` resume_throw ` , ` resume_throw_ref ` , ` switch ` ,
691+ ` cont.bind ` ). A suspended continuation may be resumed with a particular
692+ handler with ` resume ` ; aborted with ` resume_throw ` or
693+ ` resume_throw_ref ` ; directly switched to via ` switch ` ; or partially
694+ applied with ` cont.bind ` .
680695
681696In order to ensure that continuations are one-shot, ` resume ` ,
682- ` resume_throw ` , ` switch ` , and ` cont.bind ` destructively modify the
683- suspended continuation such that any subsequent use of the same
684- suspended continuation will result in a trap.
697+ ` resume_throw ` , ` resume_throw_ref ` , ` switch ` , and ` cont.bind `
698+ destructively modify the suspended continuation such that any
699+ subsequent use of the same suspended continuation will result in a
700+ trap.
685701
686702## Further examples
687703
688704We now illustrate the use of tags with result values and the
689- instructions ` cont.bind ` and ` resume.throw ` , by adapting and extending
705+ instructions ` cont.bind ` and ` resume_throw ` , by adapting and extending
690706the examples of [ Section
6917073] ( #introduction-to-continuation-based-stack-switching ) .
692708
@@ -977,6 +993,13 @@ This abbreviation will be formalised with an auxiliary function or other means i
977993 - and ` C.types[$ft] ~~ func [te*] -> [] `
978994 - and ` (hdl : t2*)* `
979995
996+ - ` resume_throw_ref <typeidx> hdl* `
997+ - Execute a given continuation, but force it to immediately throw the given exception.
998+ - Used to abort a continuation.
999+ - ` resume_throw_ref $ct hdl* : [exnref (ref null $ct)] -> [t2*] `
1000+ - iff ` C.types[$ct] ~~ cont [t1*] -> [t2*] `
1001+ - and ` (hdl : t2*)* `
1002+
9801003- ` hdl = (on <taguse> <labelidx>) | (on <taguse> switch) `
9811004 - Handlers attached to ` resume ` and ` resume_throw ` , handling control tags for ` suspend ` and ` switch ` , respectively.
9821005 - ` (on tu $l) : t* `
@@ -1094,15 +1117,22 @@ H^ea ::=
10941117
10951118* ` S; F; (ref.null t) (resume_throw $ct $e hdl*) --> S; F; trap `
10961119
1097- * ` S; F; (ref.cont ca) (resume_throw $ct $e hdl*) --> S; F; trap `
1120+ * ` S; F; v^m (ref.cont ca) (resume_throw $ct $e hdl*) --> S'; F; (ref.exn |S.exns|) (ref.const ca) (resume_throw_ref $ct hdl*) `
1121+ - iff ` ta = F.module.tags[$e] `
1122+ - and ` S.tags[ta].type ~~ [t1^m] -> [t2*] `
1123+ - and ` S' = S with exns += {S.tags[ta], v^m} `
1124+
1125+ * ` S; F; (ref.null t) (resume_throw_ref $ct hdl*) --> S; F; trap `
1126+
1127+ * ` S; F; (ref.cont ca) (resume_throw_ref $ct hdl*) --> S; F; trap `
10981128 - iff ` S.conts[ca] = epsilon `
10991129
1100- * ` S; F; v^m (ref.cont ca) (resume_throw $ct $e hdl*) --> S''; F; prompt{hdl'*} E[(ref.exn |S'.exns|) throw_ref] end `
1130+ * ` S; F; (ref.null t) (ref.cont ca) (resume_throw_ref $ct hdl*) --> S; F; trap `
1131+ - iff ` S.conts[ca] = (E : n) `
1132+
1133+ * ` S; F; (ref.exn ea) (ref.cont ca) (resume_throw_ref $ct hdl*) --> S'; F; prompt{hdl'*} E[(ref.exn ea) throw_ref] end `
11011134 - iff ` S.conts[ca] = (E : n) `
1102- - and ` ta = S.tags[F.module.tags[$e]] `
1103- - and ` ta.type ~~ [t1^m] -> [t2*] `
1104- - and ` S' = S with exns += {ta, v^m} `
1105- - and ` S'' = S' with conts[ca] = epsilon `
1135+ - and ` S' = S with conts[ca] = epsilon `
11061136 - and ` hdl'* = hdl*[F.module.tags / 0..|F.module.tags|-1] `
11071137
11081138* ` S; F; (prompt{hdl*} v* end) --> S; F; v* `
@@ -1157,7 +1187,7 @@ The opcode for heap types is encoded as an `s33`.
11571187
11581188#### Instructions
11591189
1160- We use the use the opcode space ` 0xe0-0xe5 ` for the six new instructions.
1190+ We use the use the opcode space ` 0xe0-0xe6 ` for the seven new instructions.
11611191
11621192| Opcode | Instruction | Immediates |
11631193| ------ | ------------------------ | ---------- |
@@ -1166,10 +1196,11 @@ We use the use the opcode space `0xe0-0xe5` for the six new instructions.
11661196| 0xe2 | ` suspend $t ` | ` $t : u32 ` |
11671197| 0xe3 | ` resume $ct hdl* ` | ` $ct : u32 ` (for hdl see below) |
11681198| 0xe4 | ` resume_throw $ct $e hdl* ` | ` $ct : u32 ` , ` $e : u32 ` (for hdl see below) |
1169- | 0xe5 | ` switch $ct1 $e ` | ` $ct1 : u32 ` , ` $e : u32 ` |
1199+ | 0xe5 | ` resume_throw_ref $ct hdl* ` | ` $ct : u32 ` (for hdl see below) |
1200+ | 0xe6 | ` switch $ct1 $t ` | ` $ct1 : u32 ` , ` $t : u32 ` |
11701201
1171- In the case of ` resume ` and ` resume_throw ` we use a leading byte to
1172- indicate the shape of ` hdl ` as follows.
1202+ In the cases of ` resume ` , ` resume_throw ` , and ` resume_throw_ref ` we use a
1203+ leading byte to indicate the shape of ` hdl ` as follows.
11731204
11741205| Opcode | On clause shape | Immediates |
11751206| ------ | --------------- | ---------- |
0 commit comments