Skip to content
This repository was archived by the owner on Nov 3, 2021. It is now read-only.

[spec/interpreter/test] Add table bulk instructions missing from bulk op proposal - #35

Merged
rossberg merged 7 commits into
masterfrom
table-bulk
Apr 3, 2019
Merged

rossberg merged 7 commits into
masterfrom
table-bulk

Conversation

@rossberg

@rossberg rossberg commented Apr 2, 2019 •

Copy link
Copy Markdown
Member

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.)

@rossberg
rossberg requested a review from lars-t-hansen April 2, 2019 08:40
- `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)

Copy link
Copy Markdown
Contributor

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?

Copy link
Copy Markdown
Member Author

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.)

Copy link
Copy Markdown
Contributor

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 :)

Comment thread 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)

Copy link
Copy Markdown
Contributor

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.

Copy link
Copy Markdown
Member Author

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?)

Comment thread interpreter/binary/encode.ml Outdated
| 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

Copy link
Copy Markdown
Contributor

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.

Comment thread 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 *)

Copy link
Copy Markdown
Contributor

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?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment thread interpreter/runtime/table.mli Outdated
exception OutOfMemory

val alloc : table_type -> table
val alloc : table_type -> ref_ -> table

Copy link
Copy Markdown
Contributor

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?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment thread test/core/table_fill.wast

(assert_trap
(invoke "fill" (i32.const 8) (ref.host 6) (i32.const 3))
"out of bounds"

@lars-t-hansen lars-t-hansen Apr 3, 2019 •

Copy link
Copy Markdown
Contributor

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.

Copy link
Copy Markdown
Member Author

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?

Copy link
Copy Markdown
Contributor

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...

Comment thread document/core/binary/instructions.rst Outdated
\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 \\ &&|&

Copy link
Copy Markdown
Contributor

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.

Copy link
Copy Markdown
Contributor

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?

Copy link
Copy Markdown
Member Author

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.

Copy link
Copy Markdown
Contributor

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.

Copy link
Copy Markdown
Member Author

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.

@lars-t-hansen lars-t-hansen left a comment

Copy link
Copy Markdown
Contributor

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.

@rossberg rossberg left a comment

Copy link
Copy Markdown
Member Author

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.

Comment thread 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)

Copy link
Copy Markdown
Member Author

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?)

Comment thread interpreter/runtime/table.mli Outdated
exception OutOfMemory

val alloc : table_type -> table
val alloc : table_type -> ref_ -> table

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment thread 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 *)

Copy link
Copy Markdown
Member Author

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)

Copy link
Copy Markdown
Member Author

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.)

Comment thread test/core/table_fill.wast

(assert_trap
(invoke "fill" (i32.const 8) (ref.host 6) (i32.const 3))
"out of bounds"

Copy link
Copy Markdown
Member Author

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.

Copy link
Copy Markdown
Member Author

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.

Copy link
Copy Markdown
Member Author

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.

@rossberg

rossberg commented Apr 3, 2019

Copy link
Copy Markdown
Member Author

Thanks for reviewing!

@rossberg
rossberg merged commit c3d5cbc into master Apr 3, 2019
rossberg pushed a commit that referenced this pull request Nov 20, 2019
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
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants