diff --git a/proposals/bulk-memory-operations/Overview.md b/proposals/bulk-memory-operations/Overview.md index c1cfd44d..824ce133 100644 --- a/proposals/bulk-memory-operations/Overview.md +++ b/proposals/bulk-memory-operations/Overview.md @@ -19,7 +19,7 @@ when profiling some WebAssembly benchmarks. Some examples: ### Bulk Memory Operations Prototype -I implemented a prototype implementation of a `mem.copy` instruction in v8 which just calls out +I implemented a prototype implementation of a `memory.copy` instruction in v8 which just calls out to v8's [`MemMove` function](https://cs.chromium.org/chromium/src/v8/src/utils.h?l=446). I compared this to an implementation [generated by emscripten](https://gist.github.com/binji/c57dc945bba60985439ef8e5b574eee0) and currently used in the Unity demo. This implementation aligns then performs copies using `i32.load` and `i32.store`. I've also included performance achieved by unrolling this loop manually and increasing the size to `i64`. @@ -39,7 +39,7 @@ This is the core loop: ``` The code for the benchmark can be found [here](https://gist.github.com/binji/b8e8bc0c0121235d9f1668bc447c7f8c). -Note that this will not run properly without a WebAssembly implementation of `mem.copy`. For my tests, I +Note that this will not run properly without a WebAssembly implementation of `memory.copy`. For my tests, I hacked a version of v8 to replace any exported function called `memcpy` or `memmove` with a new function with the following contents: @@ -48,7 +48,7 @@ the following contents: get_local $dst get_local $src get_local $size - mem.copy + memory.copy get_local $dst) ``` @@ -144,8 +144,8 @@ requires two modules where one should be enough. When [discussing the design of Conditional Segment Initialization](https://github.com/WebAssembly/threads/issues/62), we found that programmatic memory initialization from a read-only data segment -(via the `mem.init` instruction, described below) has similar behavior to the -proposed instruction to copy memory regions from linear memory (`mem.copy`, +(via the `memory.init` instruction, described below) has similar behavior to the +proposed instruction to copy memory regions from linear memory (`memory.copy`, also described below.) ## Design @@ -153,14 +153,14 @@ also described below.) Copying between regions in linear memory or a table is accomplished with the new `*.copy` instructions: -* `mem.copy`: copy from one region of linear memory to another +* `memory.copy`: copy from one region of linear memory to another * `table.copy`: copy from one region of a table to another -Filling a memory region can be accomplished with `mem.fill`: +Filling a memory region can be accomplished with `memory.fill`: -* `mem.fill`: fill a region of linear memory with a given byte value +* `memory.fill`: fill a region of linear memory with a given byte value -TODO: should we provide `mem.clear` and `table.clear` instead? +TODO: should we provide `memory.clear` and `table.clear` instead? The [binary format for the data section](https://webassembly.github.io/spec/binary/modules.html#data-section) currently has a collection of segments, each of which has a memory index, an @@ -174,15 +174,15 @@ _passive_. A passive segment will not be automatically copied into the memory or table on instantiation, and must instead be applied manually using the following new instructions: -* `mem.init`: copy a region from a data segment +* `memory.init`: copy a region from a data segment * `table.init`: copy a region from an element segment A passive segment has no initializer expression, since it will be specified -as an operand to `mem.init` or `table.init`. +as an operand to `memory.init` or `table.init`. Passive segments can also be discarded by using the following new instructions: -* `mem.drop`: prevent further use of a data segment +* `memory.drop`: prevent further use of a data segment * `table.drop`: prevent further use of an element segment Attempting to drop an active segment is a validation error. @@ -197,36 +197,36 @@ data ::= 0x01 b*:vec(byte) => {data 0, offset empty, init b*, acti The element section is encoded similarly. -### `mem.init` instruction +### `memory.init` instruction -The `mem.init` instruction copies data from a given passive segment into a target +The `memory.init` instruction copies data from a given passive 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 `mem.init` is executed, its behavior matches the steps described in +When `memory.init` 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 `mem.init` operands. +target offset, and length as given by the `memory.init` operands. A trap occurs if: * the segment is passive -* the segment is used after it has been dropped via `mem.drop` +* the segment is used after it has been dropped via `memory.drop` * any of the accessed bytes lies outside the source data segment or the target memory -Note that it is allowed to use `mem.init` on the same data segment more than +Note that it is allowed to use `memory.init` on the same data segment more than once. -### `mem.drop` instruction +### `memory.drop` instruction -The `mem.drop` instruction prevents further use of a given segment. After a -data segment has been dropped, it is no longer valid to use it in a `mem.init` +The `memory.drop` instruction prevents further use of a given segment. After a +data segment has been dropped, it is no longer valid to use it in a `memory.init` instruction. This instruction is intended to be used as an optimization hint to the WebAssembly implementation. After a memory segment is dropped its data can no longer be retrieved, so the memory used by this segment may be freed. -### `mem.copy` instruction +### `memory.copy` instruction Copy data from a source memory region to destination region; these regions may overlap: the copy is performed as if the source region was first copied to a @@ -239,7 +239,7 @@ The instruction has the signature `[i32 i32 i32] -> []`. The parameters are, in - top-1: source address - top-0: size of memory region in bytes -### `mem.fill` instruction +### `memory.fill` instruction Set all bytes in a memory region to a given byte. @@ -251,7 +251,7 @@ The instruction has the signature `[i32 i32 i32] -> []`. The parameters are, in ### `table.init`, `table.drop`, and `table.copy` instructions -The `table.*` instructions behave similary to the `mem.*` instructions, with +The `table.*` instructions behave similary to the `memory.*` instructions, with the difference that they operate on element segments and tables, instead of data segments and memories. The offset and length operands of `table.init` and `table.copy` have element units instead of bytes as well. @@ -272,14 +272,14 @@ implemented as follows: (if (get_global 0) ;; copy data segment 1 into memory - (mem.init 1 + (memory.init 1 (i32.const 0) ;; source offset (i32.const 16) ;; target offset (i32.const 7)) ;; length ;; The memory used by this segment is no longer needed, so this segment can ;; be dropped. - (mem.drop 1)) + (memory.drop 1)) ) ``` @@ -287,10 +287,10 @@ implemented as follows: | Name | Opcode | Immediate | Description | | ---- | ---- | ---- | ---- | -| `mem.init` | `0xfc` | `0x08` | :thinking: copy from a passive data segment to linear memory | -| `mem.drop` | `0xfc` | `0x09` | :thinking: prevent further use of passive data segment | -| `mem.copy` | `0xfc` | `0x0a` | :thinking: copy from one region of linear memory to another region | -| `mem.fill` | `0xfc` | `0x0b` | :thinking: fill a region of linear memory with a given byte value | +| `memory.init` | `0xfc` | `0x08` | :thinking: copy from a passive data segment to linear memory | +| `memory.drop` | `0xfc` | `0x09` | :thinking: prevent further use of passive data segment | +| `memory.copy` | `0xfc` | `0x0a` | :thinking: copy from one region of linear memory to another region | +| `memory.fill` | `0xfc` | `0x0b` | :thinking: fill a region of linear memory with a given byte value | | `table.init` | `0xfc` | `0x0c` | :thinking: copy from a passive element segment to a table | | `table.drop` | `0xfc` | `0x0d` | :thinking: prevent further use of a passive element segment | | `table.copy` | `0xfc` | `0x0e` | :thinking: copy from one region of a table to another region |