diff --git a/proposals/threads/ConditionalSegmentInitialization.md b/proposals/threads/ConditionalSegmentInitialization.md index 220e41e6..5b6b3525 100644 --- a/proposals/threads/ConditionalSegmentInitialization.md +++ b/proposals/threads/ConditionalSegmentInitialization.md @@ -175,3 +175,80 @@ elem ::= 0x01 e_o:expr e_a:expr y*:vec(funcindex) => {table 0, offset e_o, ap As with data segments, the `apply` initializer expression is evaluated during instantiation, and will be applied only if the expression evaluates to a non-zero value. + +## Solution 3: New instructions to initialize data and element segments + +Similar to solution 2, we repurpose the memory index as a flags field. Unlike +solution 2, the flags field specifies whether this segment is _inactive_. An +inactive segment will not be automatically copied into the memory or table on +instantiation, and must instead be applied manually using two new instructions: +`init_memory` and `init_table`. + +When the least-significant bit of the flags field is `1`, the segment is +inactive. The rest of the bits of the flags field must be zero. + +An inactive segment has no initializer expression, since it will be specified +as an operand to `init_memory` or `init_table`. + +The data section is encoded as follows: + +``` +datasec ::= seg*:section\_11(vec(data)) => seg +data ::= 0x00 e:expr b*:vec(byte) => {data 0, offset e, init b*, active true} +data ::= 0x01 b*:vec(byte) => {data 0, offset empty, init b*, active false} +``` + +The element section is encoded similarly. + +### `init_memory` instruction + +The `init_memory` instruction copies data from a given segment into a target +memory. The source segment and target memory are given as immediates. The +instruction also has three i32 operands: an offset into the source segment, an +offset into the target memory, and a length to copy. + +When `init_memory` is executed, its behavior matches the steps described in +step 11 of +[instantiation](https://webassembly.github.io/spec/exec/modules.html#instantiation), +but it behaves as though the segment were specified with the source offset, +target offset, and length as given by the `init_memory` operands. + +`init_memory` may only be used during +[instantiation](https://webassembly.github.io/spec/exec/modules.html#instantiation) +when the start function is being invoked. At any other times, the instructions +will trap. + +A trap occurs if any of the accessed bytes lies outside the source data segment +or the target memory. + +Note that it is allowed to use `init_memory` on the same data segment more than +once, or with an active data segment. + +### `init_table` instruction + +The `init_table` instruction behaves similary to the `init_memory` instruction, +with the difference that it operates on element segments and tables, instead of +data segments and memories. The offset and length operands of `init_table` have +element units instead of bytes as well. + +### Example + +Consider the example given in solution 2; there are two data sections, the +first is always active and the second is conditionally active if global 0 has a +non-zero value. This could be implemented as follows: + +``` +(import "a" "global" (global i32)) ;; global 0 +(memory 1) +(data (i32.const 0) "hello") ;; data segment 0, is active so always copied +(data inactive "goodbye") ;; data segment 1, is inactive + +(func $start + (if (get\_global 0) + ;; copy data segment 1 into memory + (init\_memory 1 + (i32.const 0) ;; source offset + (i32.const 16) ;; target offset + (i32.const 7))) ;; length +) +```