
Firefox's low-latency WebAssembly compiler - robin_reala
http://wingolog.org/archives/2020/03/25/firefoxs-low-latency-webassembly-compiler
======
davnicwil
What's the latest with WebAssembly? I must admit, I'm not fully sure I
understand what its goals are and what we should expect its usecases to be.

For a time there seemed to be a lot of hype around writing SPAs in whatever
language you like, not just JavaScript, but that seems to have cooled off
somewhat - at least that's my impression.

Last time I checked in it seemed to be actually quite the opposite - good for
low level stuff, data processing, graphics, things in other threads
essentially, but if you want to touch the DOM at all just use JS seemed to
still be the standard advice. I haven't looked again since. Have things
progressed on that front, and if not was that ever really a goal of
WebAssembly anyway?

~~~
austincheney
The goal: Allow a uniform execution context (compile target) in the browser
via a standard byte code. That means executing an application written in any
language, provided a corresponding compiler, as an island in a web page.

In practical terms the language of the browser is JavaScript, but what if
JavaScript doesn't do what you need, or it isn't fast enough, or you simply
don't like JavaScript. Instead you want to write some application in Rust
(just using that as an example). The language of the web is still JavaScript
and not Rust so your new application will not run directly in a web page.
That's unfortunate, because the web is a fantastic distribution platform
because things that run in web pages do not require a separate installation
step or a separate download step, since web page assets are downloaded
automatically as called by the web page. If you compile your Rust application
to WASM it can run in a web browser.

To be clear though WASM isn't replacing JavaScript or even in any way
competing with JavaScript, because that is certainly what it sounds like. WASM
is a separate and isolated execution instance in the browser, even from the
page that contains it. JavaScript, on the other hand, executes directly in the
context of the page that requests it.

You might hear some discussion of wanting WASM to replace JavaScript, but that
is clearly stated by the WASM project as not a design goal. You might also
hear that if only the containing page's DOM were available to WASM it would
replace JavaScript, but that isn't a design goal either. That part about the
DOM is the confluence of a misunderstanding about the DOM and about WASM's
security goals of a separate execution context. There is work, however, on
providing some Web API capabilities to WASM so that a WASM instance may have
some awareness of its execution context or to allow some manner of external
interaction of the WASM instance from the surrounding page. I don't know the
status of that work though.

* WASM project site - [https://webassembly.org/](https://webassembly.org/)

* Web APIs, a list of de facto standards for interacting with web browsers from JavaScript - [https://developer.mozilla.org/en-US/docs/Web/API](https://developer.mozilla.org/en-US/docs/Web/API)

* DOM specification, the DOM is a language agnostic dynamic tree model that represents markup and containing content - [https://dom.spec.whatwg.org/](https://dom.spec.whatwg.org/)

~~~
justinclift
> You might hear some discussion of wanting WASM to replace JavaScript, but
> that is clearly stated by the WASM project as not a design goal.

Unfortunately, that appears to be a huge miss. There are a _lot_ of
programmers in other (non-JS) languages that would very much like to create
front end pieces for their web applications.

Hopefully when the interface types proposal (or whatever) happens, direct
access to the DOM does become a thing and non-JS programmers really can do
their front end work without JS.

~~~
austincheney
Nobody from the WASM working group is working on that though, so the
probability of direct access to the page’s DOM is close to zero. Programmers
have been hoping for this for years but WASM has been very clear that isn’t in
the project’s design path. The are intentional design objectives limiting that
work officially but likely the largest hurdle is overcoming various security
and privacy concerns already in place due to the isolation of WASM instances
from their containing page.

Far more likely, and this already exists in various unofficial examples, is
that WASM instances ship with a DOM for accessing markup provided by or
requested into the WASM instance.

~~~
justinclift
> ... WASM instances ship with a DOM for accessing markup provided by or
> requested into the WASM instance.

Sounds like it would achieve the same end goal? eg direct access to the page
elements, without needing to go through JS

Or is that my not really understanding the problem space? :)

~~~
austincheney
No, a DOM that is provided by a WASM instance will provide access to markup
contents available to that WASM instance, such as markup requested or shipping
with the WASM code, but not outside the WASM instance such as the containing
page.

~~~
justinclift
Interesting. What's the intended use case for that?

Trying to think of something, but nothing is coming to mind.

~~~
austincheney
If your WASM application makes use of any kind of XML or HTML content you need
to parse it or it’s just a string.

~~~
justinclift
No worries, thanks. :)

------
nojvek
AFAIK I know Figma uses a fair bit of webassembly for perf. Their editing core
is C++ compiled to webassembly which is then bound to a canvas. I am pretty
impressed at how silky smooth their UI is. (I could be wrong)

If anyone from Figma is reading this, would love if you could shed more light
on how you use webassembly and your learnings.

~~~
dmitriid
[https://www.figma.com/blog/webassembly-cut-figmas-load-
time-...](https://www.figma.com/blog/webassembly-cut-figmas-load-time-by-3x/)

------
jokoon
I'm still wondering why webassembly is not used more. I did not discover
helloworlds tutorials, how to call js from WASM and vice versa... I sense WASM
is still a little fastidious?

I would love to have python released as a python WASM blob, there's pyiodine
but it's not just python.

I thought I would see more libraries compiled to WASM but it doesn't seem to
be the case. I want to guess the c/c++ toolchains are lacking support and
usage, or maybe C/C++ devs don't care about WASM? I know I do.

WASM lets non-web-developers run their code in a browser, but web developers
don't really care since they prefer writing JS. Maybe that's why WASM is not
taking off. That's a shame.

~~~
seangrogg
> I'm still wondering why webassembly is not used more

Largely because the majority of the problems that I have as a web developer
are not solved by manipulating 32/64-bit ints/floats at native speeds.

While I'm sure there are many exceptional uses for wasm that are related to
computational pipelines, machine learning, and canvas rendering none of that
really helps me add a text node to a DOM element that let's my user know they
entered an invalid username/password combination.

------
saagarjha
> In SpiderMonkey there is no mechanism currently to tier down; if you need to
> debug WebAssembly code, you need to refresh the page, causing the wasm code
> to be compiled in debugging mode.

Is there ever a reason to "tier down" WebAssembly besides debugging? In
JavaScript functions will often get deoptimized back to the baseline
interpreter if they side exit too often, but is this a thing that needs to be
done in WebAssembly?

~~~
dathinab
As far as I know: Not really the initial "downgraded" code is normally worse
in more or less any aspect. It's just emitted fastly.

The only reason I could come up with is to downgrade to them upgrade again to
a differently optimized code. But then WebAssembly doesn't need to do
speculative optimizations like JS needs. So I guess it's not really relevant.

~~~
sfink
In theory, you could generate better code after having observed the actual
arguments to various functions and recompile while treating them as constants.
Basically profile-guided (re)optimization. But the observation would slow down
the initial code, it would be a large implementation effort, and the gains
would be dubious imho. Especially given how much information was already lost
via the initial AOT (ahead of time) optimizing compile; you might need to keep
the original source around or something.

Unlikely to happen.

~~~
mappu
_> you could generate better code after having observed the actual arguments
to various functions and recompile while treating them as constants_

This transformation is valid for pure functions; therefore you can mark it
constexpr before compiling to WASM. There's the `constexpr-everything` project
(among others) that uses libclang to apply constexpr to all legal
functions/expressions in a codebase.

That's for C++ - Rust is working on `const fn`.

~~~
saagarjha
> This transformation is valid for pure functions; therefore you can mark it
> constexpr before compiling to WASM.

It's also valid for non-pure functions at runtime.

------
jnordwick
Real question.

Most of the wasm instructions are very low level (eg, the test and branch are
different, similar to assembly).

But then when you get to the control flow constructs they went in the this
weird direction. There is no goto, some of the instructions (br) are context
dependent, and if the wasm JIT tries to inline anything it has to muck with
the br operand (not even the worst of it). The looping constructs are just odd
too.

When I last checked you couldn't even do basic blocks with a control flow
graph like most other compilers (so that also means no jump threading
optimizations, and without goto you would have a hard time optimizing at the
wasm generation level).

It just seems like this part of the instruction set was developed by somebody
who wanted some weird higher-level asm, but others wanted an asm close to the
instruction set. Just seems like a really bad decitions.

Is there a reason for this or has this been cleaned up at all?

~~~
Rusky
That was done entirely on purpose, to make validation simpler. It does make
things harder for compilers that want to support irreducible control flow, but
the workaround is a single "relooper" algorithm that doesn't really
fundamentally change how those compilers work.

It is possible that in the future this will be relaxed (without giving up on
the benefits for validation) via something like this:
[https://github.com/WebAssembly/funclets](https://github.com/WebAssembly/funclets)

~~~
FullyFunctional
It's not just validation. A lot of things compilers have to do becomes
dramatically simpler with structured control flow and simpler means faster.
When you operate on an unstructured CFG you first have to analyze the entire
graph to find the dominators, loops etc and _then_ you have to propagate the
dataflow information in that order. All these complications go away.

There's been a few other works that realized this, among them the CORTL IR,
suggested by Carl McConnell in his Thesis proposal "Tree Based Optimizations"
and the IR used in the Oberon compiler by Michael Franz.

~~~
jnordwick
1\. You can have both. Jumps (conditional or unconditional allow for more
complex control flow and different control flow than was immediately thought
of.

2 only having structured control flow makes it a difficult target for HLL,
which is what was is supposed to be.

3\. A few years ago I was working on an array language and was trying to use
tree based optimization and code generation, but I put it on hold until i
understood more - can you recommend and links or papers?

4\. Wasm is an IR, both target and source. Why not add a goto and structured
primitive. There are clearly some things that cannot be compiled anywhere
remotely performant.

------
bluntfang
what's the use case for WebAssembly? Why are people working on it and why
should I use it?

edit: why am i being downvoted? Is this a bad question?

~~~
sfink
As I understand it: (1) calling an optimized library written in another
language for performance or size -- say you have a physics engine component in
your game, or a graph traversal algorithm, or whatever; (2) calling an
existing library that is available in another language with no JS equivalent;
and (3) running a full existing application of some sort that is written in
another language and giving it a Web interface. Oh, and (4) sandboxing
untrusted code, and coming up or already present (I'm not keeping close track)
(5) portability, where you can either run it on the Web or on a truly cross-
platform runtime (WasmTime I think?).

(And the downvotes are probably because your question could be interpreted as
implying that Wasm is useless and people are wasting their time. Even though
you're asking a totally fair question, it's easy to read the tone as negative
and dismissive whether you meant it that way or not.)

