Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamically initializing a non mutable array #515

Open
ericvergnaud opened this issue Feb 5, 2024 · 4 comments
Open

Dynamically initializing a non mutable array #515

ericvergnaud opened this issue Feb 5, 2024 · 4 comments

Comments

@ericvergnaud
Copy link
Contributor

Hi,

I'm probably missing the obvious but I can't seem to find a way to dynamically populate a non mutable array:

  • there is no array.new_xxx for initializing a new array from existing array data or from linear memory
  • array.set fails if dest array is not mutable
  • array.copy fails if dest array is not mutable

There are many scenarios where a non-mutable array needs to be dynamically populated rather than sourced from static data. Some examples:

  • string literal: init non mutable array from utf-8 data, convert it to utf-16 stored into a mutable array, init the string struct with a non mutable array copied from the previous mutable array
  • string concat
  • etc...

What am I missing ?

@rossberg
Copy link
Member

rossberg commented Feb 5, 2024

There are several instructions: array.new_fixed (initialises from stack operands), array.new_data (initialises from data segment), array.new_elem (initialises from element segment). Clearly, we cannot allow array.set or array.copy on immutable arrays.

We did not add array.new_array, array.new_memory, or array.new_table for the MVP, although it might make sense to have those. One rationale was that none of them will be enough to cover all cases anyway, e.g., consider the initialisation of cyclic structures like in the compilation of function closures. Personally, I believe we will need some notion like readonly to have a sufficiently general solution. Another alternative recently proposed is ref.freeze, although it's unclear how that could be implemented efficiently.

That said, keep in mind that the only reason why we have immutable arrays in the first place is richer Wasm-level subtyping. In cases where you don't need subtyping on the array field type – such as in the representation of strings – there is no particular reason to use immutable arrays. In particular, immutability is pointless when the field type isn't a reference.

@ericvergnaud
Copy link
Contributor Author

Thanks for confirming.
Yes ref.freeze would be a great solution for the above use use cases since it avoids a copy altogether, and readonly is a generic solution to the exact problem I'm facing.
I agree that using mutable arrays is a temporarily acceptable solution, but not sure I agree with sub typing being the 'only reason'. Another strong reason I can think of for having immutable arrays is if I compile to WebAssembly a language that supports const concepts, I'd want that attribute to be reflected in the generated Wasm, such that it is guaranteed at runtime, not just at compile time.
In the String example, I expect that if the characters are stored in a readonly array, then no code will be able to change one of those characters.

@rossberg
Copy link
Member

rossberg commented Feb 5, 2024

I'd want that attribute to be reflected in the generated Wasm.

I'm afraid that is a misunderstanding of Wasm's intended role. Wasm is a low-level language abstracting hardware, a virtual CPU, and as such not meant to reflect source-level concepts. In particular, the GC extension is not intended to give producers any more protection than they get with linear memory, the only inherent protection is for the engine itself. Any source-level protection mechanisms must be ensured at a higher level, as with a physical CPU.

@ericvergnaud
Copy link
Contributor Author

Thanks for the clarification 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants