-
Notifications
You must be signed in to change notification settings - Fork 40
[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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 :)
interpreter/binary/decode.ml
Outdated
(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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?)
interpreter/binary/encode.ml
Outdated
| TableGet x -> op 0x25; var x | ||
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments in decode.ml re the encodings here.
interpreter/runtime/table.mli
Outdated
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: add OutOfMemory to the comment here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
interpreter/runtime/table.mli
Outdated
|
||
val alloc : table_type -> table | ||
val alloc : table_type -> ref_ -> table |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: add comment that this can raise OutOfMemory?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
(assert_trap | ||
(invoke "fill" (i32.const 8) (ref.host 6) (i32.const 3)) | ||
"out of bounds" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't that what the next 3 asserts are doing, or did you mean something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, my oversight - eyes glazing over...
|
||
.. math:: | ||
\begin{array}{llclll} | ||
\production{instruction} & \Binstr &::=& \dots \\ &&|& | ||
\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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're missing any handling of the initializer argument here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments addresses. Also applied some minor adaptation to JS API.
See comment below regarding operand order for table.grow.
interpreter/binary/decode.ml
Outdated
(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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?)
interpreter/runtime/table.mli
Outdated
|
||
val alloc : table_type -> table | ||
val alloc : table_type -> ref_ -> table |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
interpreter/runtime/table.mli
Outdated
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
- `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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.)