Allow const global variables


#1

It would be useful to allow const global variables in asm.js that could be used in place of numeric literals. This would allow Emscripten to reduce code size by factoring out frequent long numeric literals, replacing them with a short identifier. This could be done with a normal global var but, without the const-ness, a single-pass AOT compiler will not know if the var is const or not which makes it hard to avoid emitting a global load instead of a immediate.

One motivation for this is factoring out common float32 constants (e.g. fround(0)). Another is a possible heap-access optimization: if Emscripten explicitly masks heap indices (e.g., HEAP32[(i&0xfffffff)>>2]), then the compiler can see that the access must in-bounds (by comparing the mask with the minimum heap size) and avoid bounds checks. However, heap masks take a lot of characters, so consts allow a significant size reduction.

The extension is pretty simple:

  • Literal-initialized global variables can be declared with const instead of var.
  • The Global Environment already records mutability of global variables which is checked by assignment, so const globals are recorded as imm.
  • The type of a const global is the precise type of the numeric literal (float, double, signed, fixnum, unsigned), so they can be used exactly where a numeric literal could be used without explicit coercion.
  • In addition to being used by Identifier expressions, const globals can be used in place of numeric literals in variable type annotations and return type annotations.

This is in release Firefox along with the heap-masking optimization. Emscripten doesn’t emit heap-masked code, though, so this is all considered experimental and feedback is welcome.


#2

Looks good to me. Is there a scenario for const in variable environment as well?


#3

We didn’t do that initially since it was extra work and there isn’t a good reason to use it (if you are going to hoist a constant, you’d want to hoist it to global scope; intra-procedural analyses don’t need any help from ‘const’ to optimize literals). There is an argument for regularity, but we also strive for minimality, so it seems like a tradeoff and we’re certainly open to other opinions.


#4

How does this relate to Firefox’s implementation of const? Notably, I’m wondering about this:

In FF if I already have in the global scope “var fround = stdlib.Math.fround; const a = fround(0)”, then in a function, the return statement “return a” doesn’t validate (but “return fround(a)” does). Is this an implementation bug, or am I misunderstanding the proposal?


#5

You are correctly understanding the proposal. While writing up these rules, I realized there were a two places where const belonged but was missing, so I added them in bug 1095740. (In addition to ‘return a’, there is also the refinement of the type of a global const literal to be the exact type of the initializer.) These changes are in FF 36 (currently in the Nighly release channel, to be released in ~14 weeks).