{"action":"created","issue":{"url":"https://api.github.com/repos/WebAssembly/design/issues/838","repository_url":"https://api.github.com/repos/WebAssembly/design","labels_url":"https://api.github.com/repos/WebAssembly/design/issues/838/labels{/name}","comments_url":"https://api.github.com/repos/WebAssembly/design/issues/838/comments","events_url":"https://api.github.com/repos/WebAssembly/design/issues/838/events","html_url":"https://github.com/WebAssembly/design/issues/838","id":185548604,"number":838,"title":"Can WebAssembly.Instance recompile an already-compiled Module?","user":{"login":"jfbastien","id":298127,"avatar_url":"https://avatars.githubusercontent.com/u/298127?v=3","gravatar_id":"","url":"https://api.github.com/users/jfbastien","html_url":"https://github.com/jfbastien","followers_url":"https://api.github.com/users/jfbastien/followers","following_url":"https://api.github.com/users/jfbastien/following{/other_user}","gists_url":"https://api.github.com/users/jfbastien/gists{/gist_id}","starred_url":"https://api.github.com/users/jfbastien/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jfbastien/subscriptions","organizations_url":"https://api.github.com/users/jfbastien/orgs","repos_url":"https://api.github.com/users/jfbastien/repos","events_url":"https://api.github.com/users/jfbastien/events{/privacy}","received_events_url":"https://api.github.com/users/jfbastien/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":76,"created_at":"2016-10-27T00:59:57Z","updated_at":"2016-12-28T01:34:03Z","closed_at":null,"body":"Say I have this code:\n\n``` js\nlet descriptor = /* ... */;\nlet memories = Array.apply(null, {length: 1024}).map(() => new WebAssembly.Memory(descriptor));\nlet instance = fetch('foo.wasm')\n  .then(response => response.arrayBuffer())\n  .then(buffer => WebAssembly.compile(buffer))\n  .then(module => new WebAssembly.Instance(module, { memory: memories[1023] }));\n```\n\nIs `WebAssembly.Instance` allowed to block for a substantial amount of time. Could it for example recompile the `WebAssembly.Module`?\n\nIn most cases I'd say no, but what if the already-compiled code doesn't particularly like the memory it receives? Say, because that memory is a slow-mode memory and the code was compiled assuming fast-mode? maybe `memories[0]` was a fast-mode memory, but `memories[1023]` sure won't be.\n\nWhat about this code instead:\n\n``` js\nlet instances = [0,1,2,3,4,5,6,7].map(v => fetch(`foo${v}.wasm`)\n  .then(response => response.arrayBuffer())\n  .then(buffer => WebAssembly.compile(buffer))\n  .then(module => new WebAssembly.Instance(module)));\n```\n\nAre those calls to `WebAssembly.Instance` allowed to cause recompilation?\n\nAssuming the above makes sense, here are a few related questions:\n- Do we want a promise-returning async function which can compile _and_ instantiate? I'm not saying that we should drop any of the synchronous and asynchronous APIs that we already have, I'm proposing a new asynchronous API.\n- How does a browser expose that compiled code in a `WebAssembly.Module` is fast, and that a `WebAssembly.Memory` instance is suitable for such fast code? Right now the answer seems to be \"try it and see if you can notice\".\n- How does a user know how many `WebAssembly.Memory` instances they're allowed before they get slow code (counting the implicit ones, e.g. as created by the second example)?\n"},"comment":{"url":"https://api.github.com/repos/WebAssembly/design/issues/comments/269410254","html_url":"https://github.com/WebAssembly/design/issues/838#issuecomment-269410254","issue_url":"https://api.github.com/repos/WebAssembly/design/issues/838","id":269410254,"user":{"login":"kripken","id":173661,"avatar_url":"https://avatars.githubusercontent.com/u/173661?v=3","gravatar_id":"","url":"https://api.github.com/users/kripken","html_url":"https://github.com/kripken","followers_url":"https://api.github.com/users/kripken/followers","following_url":"https://api.github.com/users/kripken/following{/other_user}","gists_url":"https://api.github.com/users/kripken/gists{/gist_id}","starred_url":"https://api.github.com/users/kripken/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kripken/subscriptions","organizations_url":"https://api.github.com/users/kripken/orgs","repos_url":"https://api.github.com/users/kripken/repos","events_url":"https://api.github.com/users/kripken/events{/privacy}","received_events_url":"https://api.github.com/users/kripken/received_events","type":"User","site_admin":false},"created_at":"2016-12-28T01:34:03Z","updated_at":"2016-12-28T01:34:03Z","body":"Talking offline, @lukewagner impressed upon me that the main issue here is having the Memory while compiling the module. Overall then, it seems that there are three issues that relate to how easy it is to use this new API in practice:\r\n\r\n1. Providing the Memory when compiling.\r\n2. Providing all the imports when compiling (superset of the previous).\r\n3. Doing all this asynchronously.\r\n\r\nGiven how the toolchain currently works, doing 2 + 3 is hard, as described above, because it will break existing users. We can do it, but possibly not want it on by default, at least not initially - we'd need to consult community members etc. And to do it really well - no new overhead - will require time and work (doing it quickly can be done by adding a layer of indirection on either the imports or exports).\r\n\r\nBut some other options are trivially easy to use:\r\n\r\n * 1 + 3 would require a new API like `instantiate(bytes, Memory) -> Promise`. The reason this is easy to use is that the Memory can be created early anyhow (while almost all the other imports are JS functions, which we can't have early on).\r\n * 2 by itself, without 3, i.e., `new Instance(bytes, imports)`. That is, synchronous compilation on binary data + imports. The reason this is easy to use is that our current code does this: `instance = new WebAssembly.Instance(new WebAssembly.Module(getBinary()), imports)` so we would just fold that into 1 API call.\r\n\r\nI think the last option makes sense. It basically means adding a sync version of the new API, making things more symmetrical with our existing synchronous compilation option. And I don't see a reason to tie the new optimization of knowing the Memory at compile time to asynchronous compilation? (async is great, but a separate issue?)\r\n"}}
{"actor":{"display_login":"kripken"}}