Skip to content

Commit 3e3abe7

Browse files
committed
Merge with WebAssembly/gc
2 parents 6c78ed3 + 3fa0537 commit 3e3abe7

File tree

8 files changed

+73
-74
lines changed

8 files changed

+73
-74
lines changed

document/core/appendix/changes.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ Added more precise types for references [#proposal-typedref]_.
168168
.. index:: reference, reference type, heap type, field type, storage type, structure type, array type, composite type, sub type, recursive type
169169

170170
Garbage Collection
171-
~~~~~~~~~~~~~~~~~~
171+
..................
172172

173173
Added managed reference types [#proposal-gc]_.
174174

document/core/exec/instructions.rst

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,47 +1341,43 @@ Where:
13411341

13421342
19. Assert: due to :ref:`validation <valid-array.init_data>`, the :ref:`array instance <syntax-arrayinst>` :math:`S.\SARRAYS[a]` exists.
13431343

1344-
20. If :math:`d + n` is larger than or equal to the length of :math:`S.\SARRAYS[a].\AIFIELDS`, then:
1344+
20. Assert: due to :ref:`validation <valid-array.init_data>`, the :ref:`field type <syntax-fieldtype>` :math:`\X{ft}` has a defined :ref:`bit width <bitwidth-fieldtype>`.
13451345

1346-
a. Trap.
1347-
1348-
21. Assert: due to :ref:`validation <valid-array.init_data>`, the :ref:`field type <syntax-fieldtype>` :math:`\X{ft}` has a defined :ref:`bit width <bitwidth-fieldtype>`.
1346+
21. Let :math:`z` be the :ref:`bit width <bitwidth-fieldtype>` of :ref:`field type <syntax-fieldtype>` :math:`\X{ft}` divided by eight.
13491347

1350-
22. Let :math:`z` be the :ref:`bit width <bitwidth-fieldtype>` of :ref:`field type <syntax-fieldtype>` :math:`\X{ft}` divided by eight.
1351-
1352-
23. If the sum of :math:`s` and :math:`n` times :math:`z` is larger than the length of :math:`\datainst.\DIDATA`, then:
1348+
22. If :math:`d + n` is larger than the length of :math:`S.\SARRAYS[a].\AIFIELDS`, or the sum of :math:`s` and :math:`n` times :math:`z` is larger than the length of :math:`\datainst.\DIDATA`, then:
13531349

13541350
a. Trap.
13551351

1356-
24. If :math:`n = 0`, then:
1352+
23. If :math:`n = 0`, then:
13571353

13581354
a. Return.
13591355

1360-
25. Let :math:`b^\ast` be the :ref:`byte <syntax-byte>` sequence :math:`\datainst.\DIDATA[s \slice z]`.
1356+
24. Let :math:`b^\ast` be the :ref:`byte <syntax-byte>` sequence :math:`\datainst.\DIDATA[s \slice z]`.
13611357

1362-
26. Let :math:`t` be the :ref:`value type <syntax-valtype>` :math:`\unpacktype(\X{ft})`.
1358+
25. Let :math:`t` be the :ref:`value type <syntax-valtype>` :math:`\unpacktype(\X{ft})`.
13631359

1364-
27. Assert: due to :ref:`validation <valid-array.init_data>`, :math:`\bytes_{\X{ft}}` is defined.
1360+
26. Assert: due to :ref:`validation <valid-array.init_data>`, :math:`\bytes_{\X{ft}}` is defined.
13651361

1366-
28. Let :math:`c` be the constant for which :math:`\bytes_{\X{ft}}(c)` is :math:`b^\ast`.
1362+
27. Let :math:`c` be the constant for which :math:`\bytes_{\X{ft}}(c)` is :math:`b^\ast`.
13671363

1368-
29. Push the value :math:`\REFARRAYADDR~a` to the stack.
1364+
28. Push the value :math:`\REFARRAYADDR~a` to the stack.
13691365

1370-
30. Push the value :math:`\I32.\CONST~d` to the stack.
1366+
29. Push the value :math:`\I32.\CONST~d` to the stack.
13711367

1372-
31. Push the value :math:`t.\CONST~c` to the stack.
1368+
30. Push the value :math:`t.\CONST~c` to the stack.
13731369

1374-
32. Execute the instruction :math:`\ARRAYSET~x`.
1370+
31. Execute the instruction :math:`\ARRAYSET~x`.
13751371

1376-
33. Push the value :math:`\REFARRAYADDR~a` to the stack.
1372+
32. Push the value :math:`\REFARRAYADDR~a` to the stack.
13771373

1378-
34. Push the value :math:`\I32.\CONST~(d+1)` to the stack.
1374+
33. Push the value :math:`\I32.\CONST~(d+1)` to the stack.
13791375

1380-
35. Push the value :math:`\I32.\CONST~(s+z)` to the stack.
1376+
34. Push the value :math:`\I32.\CONST~(s+z)` to the stack.
13811377

1382-
36. Push the value :math:`\I32.\CONST~(n-1)` to the stack.
1378+
35. Push the value :math:`\I32.\CONST~(n-1)` to the stack.
13831379

1384-
37. Execute the instruction :math:`\ARRAYINITDATA~x~y`.
1380+
36. Execute the instruction :math:`\ARRAYINITDATA~x~y`.
13851381

13861382
.. math::
13871383
~\\[-1ex]
@@ -1462,37 +1458,33 @@ Where:
14621458

14631459
19. Assert: due to :ref:`validation <valid-array.init_elem>`, the :ref:`array instance <syntax-arrayinst>` :math:`S.\SARRAYS[a]` exists.
14641460

1465-
20. If :math:`d + n` is larger than or equal to the length of :math:`S.\SARRAYS[a].\AIFIELDS`, then:
1461+
20. If :math:`d + n` is larger than the length of :math:`S.\SARRAYS[a].\AIFIELDS`, or :math:`s + n` is larger than the length of :math:`\eleminst.\EIELEM`, then:
14661462

14671463
a. Trap.
14681464

1469-
21. If :math:`s + n` is larger than or equal to the length of :math:`\eleminst.\EIELEM`, then:
1470-
1471-
a. Trap.
1472-
1473-
22. If :math:`n = 0`, then:
1465+
21. If :math:`n = 0`, then:
14741466

14751467
a. Return.
14761468

1477-
23. Let :math:`\reff'` be the :ref:`reference value <syntax-ref>` :math:`\eleminst.\EIELEM[s]`.
1469+
22. Let :math:`\reff'` be the :ref:`reference value <syntax-ref>` :math:`\eleminst.\EIELEM[s]`.
14781470

1479-
24. Push the value :math:`\REFARRAYADDR~a` to the stack.
1471+
23. Push the value :math:`\REFARRAYADDR~a` to the stack.
14801472

1481-
25. Push the value :math:`\I32.\CONST~d` to the stack.
1473+
24. Push the value :math:`\I32.\CONST~d` to the stack.
14821474

1483-
26. Push the value :math:`\reff'` to the stack.
1475+
25. Push the value :math:`\reff'` to the stack.
14841476

1485-
27. Execute the instruction :math:`\ARRAYSET~x`.
1477+
26. Execute the instruction :math:`\ARRAYSET~x`.
14861478

1487-
28. Push the value :math:`\REFARRAYADDR~a` to the stack.
1479+
27. Push the value :math:`\REFARRAYADDR~a` to the stack.
14881480

1489-
29. Push the value :math:`\I32.\CONST~(d+1)` to the stack.
1481+
28. Push the value :math:`\I32.\CONST~(d+1)` to the stack.
14901482

1491-
30. Push the value :math:`\I32.\CONST~(s+1)` to the stack.
1483+
29. Push the value :math:`\I32.\CONST~(s+1)` to the stack.
14921484

1493-
31. Push the value :math:`\I32.\CONST~(n-1)` to the stack.
1485+
30. Push the value :math:`\I32.\CONST~(n-1)` to the stack.
14941486

1495-
32. Execute the instruction :math:`\ARRAYINITELEM~x~y`.
1487+
31. Execute the instruction :math:`\ARRAYINITELEM~x~y`.
14961488

14971489
.. math::
14981490
~\\[-1ex]

document/core/exec/modules.rst

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -517,19 +517,17 @@ It is up to the :ref:`embedder <embedder>` to define how such conditions are rep
517517

518518
.. _exec-initvals:
519519

520-
5. Let :math:`\moduleinst_{\F{init}}` be the auxiliary module :ref:`instance <syntax-moduleinst>` :math:`\{\MIGLOBALS~\evglobals(\externval^n), \MIFUNCS~\moduleinst.\MIFUNCS\}` that only consists of the imported globals and the imported and allocated functions from the final module instance :math:`\moduleinst`, defined below.
520+
6. Let :math:`F` be the auxiliary :ref:`frame <syntax-frame>` :math:`\{ \AMODULE~\moduleinst, \ALOCALS~\epsilon \}`, that consists of the final module instance :math:`\moduleinst`, defined below.
521521

522-
6. Let :math:`F_{\F{init}}` be the auxiliary :ref:`frame <syntax-frame>` :math:`\{ \AMODULE~\moduleinst_{\F{init}}, \ALOCALS~\epsilon \}`.
523-
524-
7. Push the frame :math:`F_{\F{init}}` to the stack.
522+
7. Push the frame :math:`F` to the stack.
525523

526524
8. Let :math:`\val_{\F{g}}^\ast` be the vector of :ref:`global <syntax-global>` initialization :ref:`values <syntax-val>` determined by :math:`\module` and :math:`\externval^n`. These may be calculated as follows.
527525

528526
a. For each :ref:`global <syntax-global>` :math:`\global_i` in :math:`\module.\MGLOBALS`, do:
529527

530528
i. Let :math:`\val_{\F{g}i}` be the result of :ref:`evaluating <exec-expr>` the initializer expression :math:`\global_i.\GINIT`.
531529

532-
b. Assert: due to :ref:`validation <valid-module>`, the frame :math:`F_{\F{init}}` is now on the top of the stack.
530+
b. Assert: due to :ref:`validation <valid-module>`, the frame :math:`F` is now on the top of the stack.
533531

534532
c. Let :math:`\val_{\F{g}}^\ast` be the concatenation of :math:`\val_{\F{g}i}` in index order.
535533

@@ -543,7 +541,7 @@ It is up to the :ref:`embedder <embedder>` to define how such conditions are rep
543541

544542
iii. Let :math:`\reff_{\F{t}i}` be the reference :math:`\val_{\F{t}i}`.
545543

546-
b. Assert: due to :ref:`validation <valid-module>`, the frame :math:`F_{\F{init}}` is now on the top of the stack.
544+
b. Assert: due to :ref:`validation <valid-module>`, the frame :math:`F` is now on the top of the stack.
547545

548546
c. Let :math:`\reff_{\F{t}}^\ast` be the concatenation of :math:`\reff_{ti}` in index order.
549547

@@ -557,15 +555,9 @@ It is up to the :ref:`embedder <embedder>` to define how such conditions are rep
557555

558556
c. Let :math:`(\reff_{\F{e}}^\ast)^\ast` be the concatenation of function element vectors :math:`\reff^\ast_i` in order of index :math:`i`.
559557

560-
11. Pop the frame :math:`F_{\F{init}}` from the stack.
561-
562-
12. Let :math:`\moduleinst` be a new module instance :ref:`allocated <alloc-module>` from :math:`\module` in store :math:`S` with imports :math:`\externval^n`, global initializer values :math:`\val_{\F{g}}^\ast`, table initializer values :math:`\reff_{\F{t}}^\ast`, and element segment contents :math:`(\reff_{\F{e}}^\ast)^\ast`, and let :math:`S'` be the extended store produced by module allocation.
563-
564-
13. Let :math:`F` be the auxiliary :ref:`frame <syntax-frame>` :math:`\{ \AMODULE~\moduleinst, \ALOCALS~\epsilon \}`.
565-
566-
14. Push the frame :math:`F` to the stack.
558+
11. Let :math:`\moduleinst` be a new module instance :ref:`allocated <alloc-module>` from :math:`\module` in store :math:`S` with imports :math:`\externval^n`, global initializer values :math:`\val_{\F{g}}^\ast`, table initializer values :math:`\reff_{\F{t}}^\ast`, and element segment contents :math:`(\reff_{\F{e}}^\ast)^\ast`, and let :math:`S'` be the extended store produced by module allocation.
567559

568-
15. For each :ref:`element segment <syntax-elem>` :math:`\elem_i` in :math:`\module.\MELEMS` whose :ref:`mode <syntax-elemmode>` is of the form :math:`\EACTIVE~\{ \ETABLE~\tableidx_i, \EOFFSET~\X{einstr}^\ast_i~\END \}`, do:
560+
12. For each :ref:`element segment <syntax-elem>` :math:`\elem_i` in :math:`\module.\MELEMS` whose :ref:`mode <syntax-elemmode>` is of the form :math:`\EACTIVE~\{ \ETABLE~\tableidx_i, \EOFFSET~\X{einstr}^\ast_i~\END \}`, do:
569561

570562
a. Let :math:`n` be the length of the vector :math:`\elem_i.\EINIT`.
571563

@@ -579,11 +571,11 @@ It is up to the :ref:`embedder <embedder>` to define how such conditions are rep
579571

580572
f. :ref:`Execute <exec-elem.drop>` the instruction :math:`\ELEMDROP~i`.
581573

582-
16. For each :ref:`element segment <syntax-elem>` :math:`\elem_i` in :math:`\module.\MELEMS` whose :ref:`mode <syntax-elemmode>` is of the form :math:`\EDECLARATIVE`, do:
574+
13. For each :ref:`element segment <syntax-elem>` :math:`\elem_i` in :math:`\module.\MELEMS` whose :ref:`mode <syntax-elemmode>` is of the form :math:`\EDECLARATIVE`, do:
583575

584576
a. :ref:`Execute <exec-elem.drop>` the instruction :math:`\ELEMDROP~i`.
585577

586-
17. For each :ref:`data segment <syntax-data>` :math:`\data_i` in :math:`\module.\MDATAS` whose :ref:`mode <syntax-datamode>` is of the form :math:`\DACTIVE~\{ \DMEM~\memidx_i, \DOFFSET~\X{dinstr}^\ast_i~\END \}`, do:
578+
14. For each :ref:`data segment <syntax-data>` :math:`\data_i` in :math:`\module.\MDATAS` whose :ref:`mode <syntax-datamode>` is of the form :math:`\DACTIVE~\{ \DMEM~\memidx_i, \DOFFSET~\X{dinstr}^\ast_i~\END \}`, do:
587579

588580
a. Assert: :math:`\memidx_i` is :math:`0`.
589581

@@ -599,15 +591,15 @@ It is up to the :ref:`embedder <embedder>` to define how such conditions are rep
599591

600592
g. :ref:`Execute <exec-data.drop>` the instruction :math:`\DATADROP~i`.
601593

602-
18. If the :ref:`start function <syntax-start>` :math:`\module.\MSTART` is not empty, then:
594+
15. If the :ref:`start function <syntax-start>` :math:`\module.\MSTART` is not empty, then:
603595

604596
a. Let :math:`\start` be the :ref:`start function <syntax-start>` :math:`\module.\MSTART`.
605597

606598
b. :ref:`Execute <exec-call>` the instruction :math:`\CALL~\start.\SFUNC`.
607599

608-
19. Assert: due to :ref:`validation <valid-module>`, the frame :math:`F` is now on the top of the stack.
600+
16. Assert: due to :ref:`validation <valid-module>`, the frame :math:`F` is now on the top of the stack.
609601

610-
20. Pop the frame :math:`F` from the stack.
602+
17. Pop the frame :math:`F` from the stack.
611603

612604

613605
.. math::
@@ -658,7 +650,7 @@ where:
658650

659651
Similarly, module :ref:`allocation <alloc-module>` and the :ref:`evaluation <exec-expr>` of :ref:`global <syntax-global>` and :ref:`table <syntax-table>` initializers as well as :ref:`element segments <syntax-elem>` are mutually recursive because the global initialization :ref:`values <syntax-val>` :math:`\val_{\F{g}}^\ast`, :math:`\reff_{\F{t}}`, and element segment contents :math:`(\reff^\ast)^\ast` are passed to the module allocator while depending on the module instance :math:`\moduleinst` and store :math:`S'` returned by allocation.
660652
Again, this recursion is just a specification device.
661-
In practice, the initialization values can :ref:`be determined <exec-initvals>` beforehand by staging module allocation further such that first, the module's own :ref:`function instances <syntax-funcinst>` are pre-allocated in the store, then the initializer expressions are evaluated in order, allocating globals on the way, then the rest of the module instance is allocated, and finally the new function instances' :math:`\AMODULE` fields are set to that module instance.
653+
In practice, the initialization values can :ref:`be determined <exec-initvals>` beforehand by staging module allocation such that first, the module's own :ref:`function instances <syntax-funcinst>` are pre-allocated in the store, then the initializer expressions are evaluated in order, allocating globals on the way, then the rest of the module instance is allocated, and finally the new function instances' :math:`\AMODULE` fields are set to that module instance.
662654
This is possible because :ref:`validation <valid-module>` ensures that initialization expressions cannot actually call a function, only take their reference.
663655

664656
All failure conditions are checked before any observable mutation of the store takes place.

document/core/valid/matching.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,11 @@ A :ref:`defined type <syntax-deftype>` :math:`\deftype_1` matches a type :math:`
453453
C \vdashdeftypematch \deftype_1 \matchesdeftype \deftype_2
454454
}
455455
456+
.. note::
457+
Note that there is no explicit definition of type _equivalence_,
458+
since it coincides with syntactic equality,
459+
as used in the premise of the fomer rule above.
460+
456461

457462
.. index:: limits
458463
.. _match-limits:

interpreter/text/parse.mli

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ exception Syntax of Source.region * string
33
module type S =
44
sig
55
type t
6-
val parse : string -> Lexing.lexbuf -> t
7-
val parse_file : string -> t
8-
val parse_string : string -> t
9-
val parse_channel : in_channel -> t
6+
val parse : string -> Lexing.lexbuf -> t (* raises Syntax *)
7+
val parse_file : string -> t (* raises Syntax *)
8+
val parse_string : string -> t (* raises Syntax *)
9+
val parse_channel : in_channel -> t (* raises Syntax *)
1010
end
1111

1212
module Module : S with type t = Script.var option * Script.definition

interpreter/text/parser.mly

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,13 +1504,14 @@ result :
15041504
| LPAR REF_I31 RPAR { RefResult (RefTypePat I31HT) @@ at () }
15051505
| LPAR REF_STRUCT RPAR { RefResult (RefTypePat StructHT) @@ at () }
15061506
| LPAR REF_ARRAY RPAR { RefResult (RefTypePat ArrayHT) @@ at () }
1507-
| LPAR REF_NULL RPAR { RefResult NullPat @@ at () }
15081507
| LPAR REF_FUNC RPAR { RefResult (RefTypePat FuncHT) @@ at () }
15091508
| LPAR REF_EXTERN RPAR { RefResult (RefTypePat ExternHT) @@ at () }
1509+
| LPAR REF_NULL RPAR { RefResult NullPat @@ at () }
15101510
| LPAR VEC_CONST VEC_SHAPE list(numpat) RPAR
15111511
{ if V128.num_lanes $3 <> List.length $4 then
15121512
error (at ()) "wrong number of lane literals";
1513-
VecResult (VecPat (Value.V128 ($3, List.map (fun lit -> lit $3) $4))) @@ at () }
1513+
VecResult (VecPat
1514+
(Value.V128 ($3, List.map (fun lit -> lit $3) $4))) @@ at () }
15141515

15151516
script :
15161517
| list(cmd) EOF { $1 }

test/core/gc/array.wast

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,17 +152,24 @@
152152
(type $vec (array i8))
153153
(type $mvec (array (mut i8)))
154154

155-
(data $d "\00\01\02\03\04")
155+
(data $d "\00\01\02\ff\04")
156156

157157
(func $new (export "new") (result (ref $vec))
158158
(array.new_data $vec $d (i32.const 1) (i32.const 3))
159159
)
160160

161-
(func $get (param $i i32) (param $v (ref $vec)) (result i32)
161+
(func $get_u (param $i i32) (param $v (ref $vec)) (result i32)
162162
(array.get_u $vec (local.get $v) (local.get $i))
163163
)
164-
(func (export "get") (param $i i32) (result i32)
165-
(call $get (local.get $i) (call $new))
164+
(func (export "get_u") (param $i i32) (result i32)
165+
(call $get_u (local.get $i) (call $new))
166+
)
167+
168+
(func $get_s (param $i i32) (param $v (ref $vec)) (result i32)
169+
(array.get_s $vec (local.get $v) (local.get $i))
170+
)
171+
(func (export "get_s") (param $i i32) (result i32)
172+
(call $get_s (local.get $i) (call $new))
166173
)
167174

168175
(func $set_get (param $i i32) (param $v (ref $mvec)) (param $y i32) (result i32)
@@ -186,11 +193,13 @@
186193

187194
(assert_return (invoke "new") (ref.array))
188195
(assert_return (invoke "new") (ref.eq))
189-
(assert_return (invoke "get" (i32.const 0)) (i32.const 1))
196+
(assert_return (invoke "get_u" (i32.const 2)) (i32.const 0xff))
197+
(assert_return (invoke "get_s" (i32.const 2)) (i32.const -1))
190198
(assert_return (invoke "set_get" (i32.const 1) (i32.const 7)) (i32.const 7))
191199
(assert_return (invoke "len") (i32.const 3))
192200

193-
(assert_trap (invoke "get" (i32.const 10)) "out of bounds array access")
201+
(assert_trap (invoke "get_u" (i32.const 10)) "out of bounds array access")
202+
(assert_trap (invoke "get_s" (i32.const 10)) "out of bounds array access")
194203
(assert_trap (invoke "set_get" (i32.const 10) (i32.const 7)) "out of bounds array access")
195204

196205
(module
@@ -302,5 +311,5 @@
302311
)
303312
)
304313

305-
(assert_trap (invoke "array.get-null") "null array")
306-
(assert_trap (invoke "array.set-null") "null array")
314+
(assert_trap (invoke "array.get-null") "null array reference")
315+
(assert_trap (invoke "array.set-null") "null array reference")

test/core/gc/struct.wast

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@
152152
)
153153
)
154154

155-
(assert_trap (invoke "struct.get-null") "null structure")
156-
(assert_trap (invoke "struct.set-null") "null structure")
155+
(assert_trap (invoke "struct.get-null") "null structure reference")
156+
(assert_trap (invoke "struct.set-null") "null structure reference")
157157

158158
;; Packed field instructions
159159

0 commit comments

Comments
 (0)