At the moment, wasm can only call functions that were passed as values of the import object which is passed to to one of the instantiation functions (e.g. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...), so which function gets called is up to the embedding JS code.
The current plan (https://github.com/WebAssembly/design/blob/master/Web.md#imp...) is to integrate WebAssembly into the ES6 module system (so you could have a JS module import a WebAssembly module and vice versa). With this design, the WebAssembly polyfill would hook into the ES6 module loader (if implemented natively) or the ES6 module loader polyfill.
It should also be possible to have a <script type="application/wasm" src="something.wasm" />, and then additionally source a JavaScript polyfill that checks if wasm is supported and translates to JavaScript if not. That would remove the need to have JavaScript shims.
Hmm, neither one of these options (ES6 import or <script> type wasm) can quite fit in with the way we're using asm.js (including it inline with other JavaScript inside a Worker[1]).
If there were a way to flexibly invoke wasm in any scenario where asm.js currently works, I think it would be a lot friendlier and truer to the "it's just JavaScript" goal.
Furthermore, tying this to ES6 seems unnecessary to me. How does this affect those of us using Babel or TypeScript to output ES3 code? The purposes of wasm and ES6 just strike me as completely orthogonal.
---
1: There are good reasons we have to do this, but they're beyond the scope of this thread.
> Hmm, neither one of these options (ES6 import or <script> type wasm) can quite fit in with the way we're using asm.js (including it inline with other JavaScript inside a Worker[1]).
Could you import a module, and then call the resulting functions from within your Worker?
> If there were a way to flexibly invoke wasm in any scenario where asm.js currently works, I think it would be a lot friendlier and truer to the "it's just JavaScript" goal.
"it's just JavaScript" is a goal of asm.js; I don't see anything about WebAssembly that makes it a stated goal of wasm. "It works anywhere JavaScript works, and can call and be called by JavaScript" would be a more sensible goal.
> 1: There are good reasons we have to do this, but they're beyond the scope of this thread.
Not sure if the security model allows it, but maybe you could write the wasm into a blob, create an URI from the blob[1] and then use that as <script> src.
Or maybe data uris.
> How does this affect those of us using Babel or TypeScript to output ES3 code?
Well, if you're already transpiling the whole load of ES6 features then it's just one more shim to consider, no?
Any idea if wasm / ES6 modules / module loader shims work with object URLs and/or data URIs cross-browser by design?
Doing something similar for Workers, one of the problems we've had is that IE and I think Safari block that, so to make it work we have to fall back on a permanently cached shim that puts an eval statement inside self.onmessage. (Obviously no equivalent to eval exists for wasm, or I wouldn't have a problem here in the first place.)
I wouldn't say this is "tied" to ES6, but rather intends to integrate nicely. If a developer has no interest in being called by or calling JS, they should be able to ignore the ES6 module aspect. For workers, it should (eventually, probably not in the MVP v.1) be possible to pass a URL (which, with Blob + Object URL needn't be a remote fetch and can be explicitly cached (Cache API or IndexedDB) or dynamically generated (Blob constructor)) to a worker constructor.
>Could you import a module, and then call the resulting functions from within your Worker? ... I'd be interested to hear them.
I have more detail here[1], but what it comes down to is that our application's security model is dependent on the ability to pack all of its code into one file.
I'm admittedly not too familiar with the ES6 module system (we're using TypeScript modules), but it looks like importing necessarily requires pulling in an external file. Workers are problematic in a similar way, but simple enough to work around using a few different methods (that I can't think of how to apply to ES6 modules).
> For workers, it should ... to a worker constructor.
In our case, the asm.js modules aren't being used as standalone workers, but rather pulled in to a worker that does a bunch of other stuff, so that probably couldn't be applied here exactly.
If that blob URL setup worked with ES6 import, though, that could work. (It might make things messier for generated TypeScript code though, not sure.)
> I wouldn't say this is "tied" to ES6, but rather intends to integrate nicely.
When I say tied, I mean in the sense that ES6 looks to be the only method of arbitrarily executing wasm code.
To use wasm, I'd need the ability to drop it in the middle of a block of JS.
Almost nobody is using asm.js right now, and backward compatibility with asm.js should not be a top consideration for WebAssembly which (with agreement from multiple vendors) will achieve something much more important than asm.js backward compatibility.
With this module loader, can you generate your own code to load at runtime reasonably easily and efficiently? Say you're compiling from user input to asm.js within the browser (as I did the week asm.js was announced) -- can you change it to compile to wasm?
(That link pointed to another link on module loading, a long page I didn't find an answer on right away. Admittedly I'm only curious for now.)
That'd be perfect; thanks! I'll have to play around with that once wasm is in a testable state.
As far as compiling within the browser, it sounds like compiling the wasm will be the same process as compiling to asm.js – except the final bytecode format won't be directly executable as JS. If that's the case, then I'd imagine any asm.js compiler could have wasm support added the same way emscripten will.
I think in both of our use cases it all just depends on how easy it will be to execute the code from there. (In your case, the worst case scenario is that you have to post the generated code to a server and redownload it – ridiculously ugly, but not a blocker.)
In the Java applet days you'd actually have to do that -- round-trip your generated bytecode back through the server -- and I was like "Hello, you must be kidding". That's why I don't just assume they've made direct loading possible.
I haven't followed the module loader work super closely, but the overriding impression that I've gotten is that the ability to customize how code is loaded and from where is a primary goal.
asm.js now allows the heap to be resized (by replacing the heap's ArrayBuffer with a newer, bigger ArrayBuffer that was either copied or produced via ES7-proposed ArrayBuffer.transfer [1]). Heap resizing currently has to be enabled in Emscripten (by passing -s ALLOW_MEMORY_GROWTH=1), but may become the default in the future. The main asm.js spec page hasn't been updated yet, but the extension was discussed publicly with comments from Microsoft engineers [2].
That is nice to hear. I don't keep enough track to see that this was being discussed, but it does deal with the only major issue I had with C++ -> asm.js code conversion, particularly for mobile.
On x64 in Firefox, at least, there are no bounds checks; the index is a uint32; the entire accessible 4GB range is mapped PROT_NONE with only the accessible region mapped PROT_READ|PROT_WRITE; out-of-bounds accesses thus reliably turn into SIGSEGVs which are handled safely after which execution resumes. Thus, bounds checking is effectively performed by the MMU.
For (1): You're right that an option is to compile the VM itself to asm.js (since the VM is usually written C/C++ code; JITs are an obvious exception since they generate machine code at runtime). This has already been done, e.g., for Java [1] and Lua [2]. What is meant by "supporting GC languages" is translating GC objects in the source language to real JavaScript objects so that the JS GC may be used on them. For statically-typed source languages like .NET/JVM, the proposed Typed Objects extension to JavaScript [3] could be naturally integrated into asm.js to describe classes. This is all a little ways off since Typed Objects needs to be standardized first. Also, the lack of finalizers in JS would limit the fidelity of the translation.
The 'war on native' has multiple fronts and this post is just reporting on one of them. For many apps, I agree that the items you've mentioned are the most significant and progress is also being made on these fronts (e.g., GPU-acceleration of some CSS transitions are already in Firefox; more and more DOM APIs are being exposed to workers). For other apps, though, especially ones using WebGL like games or authoring tools, raw computational throughput is the most significant.
Referring to http://agner.org/optimize, both Nehalem (Intel Core i7) and Jaguar (AMD Kabini) instruction tables: you are right that addss, subss show the same latency as addsd and subsd, resp. However, mulss and divss show better latencies than mulsd and divsd.