Repository navigation
[spec/interpreter/test] Add table bulk instructions missing from bulk op proposal - #35
Conversation
| - `table.grow $x : [t i32] -> [i32]` | ||
| - iff `$x : table t` | ||
| - the first operand of `table.grow` is an initialisation value (for compatibility with future extensions to the type system, such as non-nullable references) | ||
|
|
There was a problem hiding this comment.
Any particular justification for the argument ordering for table.grow? I ask, since we chose the other ordering (init value on top of stack, delta underneath). I assume what you have here is compatible with v8?
There was a problem hiding this comment.
Yes, I tried to follow the convention of the other bulk ops, which always have argument order (dest, source, length). In particular, this would most closely match table.fill, except for omitting the start index.
(AFAIAA, V8 does not implement these instructions yet.)
There was a problem hiding this comment.
And table.fill follows memory.fill, fair enough. I'll file a bug to fix it on our end.
Though it's a bit odd that FF would be shipping features for which we don't even have a spec draft?
Well, shipping in Nightly only and it won't ride the trains until we're all aligned, but apart from this wrinkle I think we've anticipated the draft fairly well :)
| (match op s with | ||
| | 0x0f -> table_fill (at var s) | ||
| | 0x10 -> table_size (at var s) | ||
| | 0x11 -> table_grow (at var s) |
There was a problem hiding this comment.
These encodings contradict the table in #29 (first and last comments), which we have used as the basis for the decoder in Firefox. If possible I'd like these to change here since we're shipping already. Proposed encodings there are table_grow == 0x0f, table_size == 0x10, table_fill == 0x11. Ditto the encoder and any other spots.
There was a problem hiding this comment.
Ah, sorry, I completely forgot about #29. Changed. (Though it's a bit odd that FF would be shipping features for which we don't even have a spec draft?)
| | TableSet x -> op 0x26; var x | ||
| | TableSize x -> op 0xfc; op 0x10; var x | ||
| | TableGrow x -> op 0xfc; op 0x11; var x | ||
| | TableFill x -> op 0xfc; op 0x0f; var x |
There was a problem hiding this comment.
See comments in decode.ml re the encodings here.
| val type_of : table -> table_type | ||
| val size : table -> size | ||
| val grow : table -> size -> unit (* raises SizeOverflow, SizeLimit *) | ||
| val grow : table -> size -> ref_ -> unit (* raises SizeOverflow, SizeLimit *) |
There was a problem hiding this comment.
Nit: add OutOfMemory to the comment here?
| exception OutOfMemory | ||
|
|
||
| val alloc : table_type -> table | ||
| val alloc : table_type -> ref_ -> table |
There was a problem hiding this comment.
Nit: add comment that this can raise OutOfMemory?
|
|
||
| (assert_trap | ||
| (invoke "fill" (i32.const 8) (ref.host 6) (i32.const 3)) | ||
| "out of bounds" |
There was a problem hiding this comment.
In this case we also want to check that there was initialization of the elements up to the bound.
There was a problem hiding this comment.
Isn't that what the next 3 asserts are doing, or did you mean something else?
There was a problem hiding this comment.
Sorry, my oversight - eyes glazing over...
| \hex{25}~~x{:}\Btableidx &\Rightarrow& \TABLEGET~x \\ &&|& | ||
| \hex{26}~~x{:}\Btableidx &\Rightarrow& \TABLESET~x \\ | ||
| \hex{26}~~x{:}\Btableidx &\Rightarrow& \TABLESET~x \\ &&|& | ||
| \hex{FC}~\hex{0F}~~x{:}\Btableidx &\Rightarrow& \TABLEFILL~x \\ &&|& |
There was a problem hiding this comment.
See notes later about encodings here.
| 7. Assert: due to :ref:`validation <valid-table.grow>`, a value of :ref:`value type <syntax-valtype>` |I32| is on the top of the stack. | ||
|
|
||
| 8. Pop the value :math:`\I32.\CONST~n` from the stack. | ||
|
|
There was a problem hiding this comment.
I think we're missing any handling of the initializer argument here?
There was a problem hiding this comment.
Good catch, fixed. That meant also adjusting the meta function and the embedding interface accordingly to support an initialisation value.
|
|
||
| 5. Let :math:`\X{tab}` be the :ref:`table instance <syntax-tableinst>` :math:`S.\STABLES[a]`. | ||
|
|
||
| 6. Assert: due to :ref:`validation <valid-table.fill>`, a value of :ref:`value type <syntax-valtype>` |I32| is on the top of the stack. |
There was a problem hiding this comment.
Technically this is possibly a little dodgy (ditto subsequent clauses, ditto clauses for TABLESET): since we're directly manipulating the stack in the recursive call below, asserting that this is true as a consequence of validation is questionable. I'm not sure it's worth fixing though.
There was a problem hiding this comment.
Yes, fair point. I think there are actually a few other such assertions already where, strictly speaking, having the right value on the stack is rather a consequence of soundness.
lars-t-hansen
left a comment
There was a problem hiding this comment.
Looks good in general, thanks for doing this. I'd like to see the opcode encodings changed to values previously agreed upon in #29. I'd like to have a discussion about argument ordering for table.grow, as Firefox is now in conflict with this spec.
rossberg
left a comment
There was a problem hiding this comment.
Comments addresses. Also applied some minor adaptation to JS API.
See comment below regarding operand order for table.grow.
| (match op s with | ||
| | 0x0f -> table_fill (at var s) | ||
| | 0x10 -> table_size (at var s) | ||
| | 0x11 -> table_grow (at var s) |
There was a problem hiding this comment.
Ah, sorry, I completely forgot about #29. Changed. (Though it's a bit odd that FF would be shipping features for which we don't even have a spec draft?)
| exception OutOfMemory | ||
|
|
||
| val alloc : table_type -> table | ||
| val alloc : table_type -> ref_ -> table |
| val type_of : table -> table_type | ||
| val size : table -> size | ||
| val grow : table -> size -> unit (* raises SizeOverflow, SizeLimit *) | ||
| val grow : table -> size -> ref_ -> unit (* raises SizeOverflow, SizeLimit *) |
| - `table.grow $x : [t i32] -> [i32]` | ||
| - iff `$x : table t` | ||
| - the first operand of `table.grow` is an initialisation value (for compatibility with future extensions to the type system, such as non-nullable references) | ||
|
|
There was a problem hiding this comment.
Yes, I tried to follow the convention of the other bulk ops, which always have argument order (dest, source, length). In particular, this would most closely match table.fill, except for omitting the start index.
(AFAIAA, V8 does not implement these instructions yet.)
|
|
||
| (assert_trap | ||
| (invoke "fill" (i32.const 8) (ref.host 6) (i32.const 3)) | ||
| "out of bounds" |
There was a problem hiding this comment.
Isn't that what the next 3 asserts are doing, or did you mean something else?
| 7. Assert: due to :ref:`validation <valid-table.grow>`, a value of :ref:`value type <syntax-valtype>` |I32| is on the top of the stack. | ||
|
|
||
| 8. Pop the value :math:`\I32.\CONST~n` from the stack. | ||
|
|
There was a problem hiding this comment.
Good catch, fixed. That meant also adjusting the meta function and the embedding interface accordingly to support an initialisation value.
|
|
||
| 5. Let :math:`\X{tab}` be the :ref:`table instance <syntax-tableinst>` :math:`S.\STABLES[a]`. | ||
|
|
||
| 6. Assert: due to :ref:`validation <valid-table.fill>`, a value of :ref:`value type <syntax-valtype>` |I32| is on the top of the stack. |
There was a problem hiding this comment.
Yes, fair point. I think there are actually a few other such assertions already where, strictly speaking, having the right value on the stack is rather a consequence of soundness.
|
Thanks for reviewing! |
This commit fixes #34 by specifying that the flags field (which indicates if a segment is passive) is a `varuint32` instead of a `uint8`. It was discovered in #34 that the memory index located at that position today is a `varuint32`, which can be validly encoded as `0x80 0x00` in addition to `0x00` (in addition to a number of other encodings). This means that if the first field were repurposed as a single byte of flags, it would break these existing modules that work today. It's not currently known how many modules in the wild actually take advantage of such an encoding, but it's probably better to be safe than sorry! Closes #34
Adds table.size, table.grow, table.fill to overview, spec, interpreter, and tests, as decided at recent CG meeting. Also adds a few more tests for table.get and table.set.
Edit: Also, change interpreter's segment encoding to match bulk ops proposal, addressing #18. (Not updated in spec yet, since corresponding spec text is still missing from bulk ops proposal.)