summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/asm.js
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /js/src/jit-test/tests/asm.js
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'js/src/jit-test/tests/asm.js')
-rw-r--r--js/src/jit-test/tests/asm.js/bug1007512.js8
-rw-r--r--js/src/jit-test/tests/asm.js/bug1008636.js12
-rw-r--r--js/src/jit-test/tests/asm.js/bug1126251.js53
-rw-r--r--js/src/jit-test/tests/asm.js/bug1161298.js13
-rw-r--r--js/src/jit-test/tests/asm.js/bug1174372.js6
-rw-r--r--js/src/jit-test/tests/asm.js/bug1201124-simd-proxy.js28
-rw-r--r--js/src/jit-test/tests/asm.js/bug1219954.js13
-rw-r--r--js/src/jit-test/tests/asm.js/bug1268955-usestrict-semantics.js19
-rw-r--r--js/src/jit-test/tests/asm.js/bug1276028.js6
-rw-r--r--js/src/jit-test/tests/asm.js/bug1306506.js7
-rw-r--r--js/src/jit-test/tests/asm.js/bug855526.js13
-rw-r--r--js/src/jit-test/tests/asm.js/bug885976.js12
-rw-r--r--js/src/jit-test/tests/asm.js/bug923867.js8
-rw-r--r--js/src/jit-test/tests/asm.js/bug927389.js6
-rw-r--r--js/src/jit-test/tests/asm.js/bug928450.js18
-rw-r--r--js/src/jit-test/tests/asm.js/bug940864.js10
-rw-r--r--js/src/jit-test/tests/asm.js/bug941877.js164
-rw-r--r--js/src/jit-test/tests/asm.js/directives.txt1
-rw-r--r--js/src/jit-test/tests/asm.js/gating.js79
-rw-r--r--js/src/jit-test/tests/asm.js/neuter-during-arguments-coercion.js27
-rw-r--r--js/src/jit-test/tests/asm.js/oom-helper-thread-plus-validation-error.js11
-rw-r--r--js/src/jit-test/tests/asm.js/oom-helper-thread.js8
-rw-r--r--js/src/jit-test/tests/asm.js/simd-fbirds.js198
-rw-r--r--js/src/jit-test/tests/asm.js/simd-mandelbrot.js1819
-rw-r--r--js/src/jit-test/tests/asm.js/sta-transition.js63
-rw-r--r--js/src/jit-test/tests/asm.js/testAddressErrors.js47
-rw-r--r--js/src/jit-test/tests/asm.js/testAsmJSWasmMixing.js25
-rw-r--r--js/src/jit-test/tests/asm.js/testAtomic-effect.js49
-rw-r--r--js/src/jit-test/tests/asm.js/testAtomics.js1886
-rw-r--r--js/src/jit-test/tests/asm.js/testBasic.js176
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1046688.js11
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1057248.js134
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1099216.js61
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1111327.js11
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1117235.js8
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1117255.js14
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1125561.js47
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1147144.js20
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1155176.js52
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1164391.js27
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1183060.js55
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1219098.js14
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1236484.js10
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1236541.js15
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1236552.js3
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1255954.js14
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1291887.js13
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1301191.js24
-rw-r--r--js/src/jit-test/tests/asm.js/testBug1302407.js6
-rw-r--r--js/src/jit-test/tests/asm.js/testBug855442.js8
-rw-r--r--js/src/jit-test/tests/asm.js/testBug863867.js34
-rw-r--r--js/src/jit-test/tests/asm.js/testBug878435.js11
-rw-r--r--js/src/jit-test/tests/asm.js/testBug878495.js10
-rw-r--r--js/src/jit-test/tests/asm.js/testBug878520.js9
-rw-r--r--js/src/jit-test/tests/asm.js/testBug892291.js10
-rw-r--r--js/src/jit-test/tests/asm.js/testBug893364.js14
-rw-r--r--js/src/jit-test/tests/asm.js/testBug893368.js13
-rw-r--r--js/src/jit-test/tests/asm.js/testBug893519.js11
-rw-r--r--js/src/jit-test/tests/asm.js/testBug907085.js22
-rw-r--r--js/src/jit-test/tests/asm.js/testBug952022.js57
-rw-r--r--js/src/jit-test/tests/asm.js/testBug965767.js2098
-rw-r--r--js/src/jit-test/tests/asm.js/testBug975182.js20
-rw-r--r--js/src/jit-test/tests/asm.js/testBug989166.js8
-rw-r--r--js/src/jit-test/tests/asm.js/testBug999790.js65
-rw-r--r--js/src/jit-test/tests/asm.js/testBullet.js19
-rw-r--r--js/src/jit-test/tests/asm.js/testCaching.js102
-rw-r--r--js/src/jit-test/tests/asm.js/testCall.js75
-rw-r--r--js/src/jit-test/tests/asm.js/testCloning.js50
-rw-r--r--js/src/jit-test/tests/asm.js/testCompoundPlusMinus.js14
-rw-r--r--js/src/jit-test/tests/asm.js/testControlFlow.js374
-rw-r--r--js/src/jit-test/tests/asm.js/testDebugModeDisables.js9
-rw-r--r--js/src/jit-test/tests/asm.js/testExpressions.js403
-rw-r--r--js/src/jit-test/tests/asm.js/testFFI.js164
-rw-r--r--js/src/jit-test/tests/asm.js/testFastHeapAccess.js81
-rw-r--r--js/src/jit-test/tests/asm.js/testFloat32.js321
-rw-r--r--js/src/jit-test/tests/asm.js/testFloatingPoint.js134
-rw-r--r--js/src/jit-test/tests/asm.js/testFunctionPtr.js74
-rw-r--r--js/src/jit-test/tests/asm.js/testGlobals.js164
-rw-r--r--js/src/jit-test/tests/asm.js/testHeapAccess.js515
-rw-r--r--js/src/jit-test/tests/asm.js/testJumpRange.js46
-rw-r--r--js/src/jit-test/tests/asm.js/testLinkErrorAssert.js20
-rw-r--r--js/src/jit-test/tests/asm.js/testLiterals.js50
-rw-r--r--js/src/jit-test/tests/asm.js/testMathLib.js189
-rw-r--r--js/src/jit-test/tests/asm.js/testModuleFunctions.js41
-rw-r--r--js/src/jit-test/tests/asm.js/testNeuter.js44
-rw-r--r--js/src/jit-test/tests/asm.js/testParallelCompile.js26
-rw-r--r--js/src/jit-test/tests/asm.js/testProfiling.js246
-rw-r--r--js/src/jit-test/tests/asm.js/testRangeAnalysis.js15
-rw-r--r--js/src/jit-test/tests/asm.js/testSIMD-16x8.js510
-rw-r--r--js/src/jit-test/tests/asm.js/testSIMD-8x16.js524
-rw-r--r--js/src/jit-test/tests/asm.js/testSIMD-bitcasts.js84
-rw-r--r--js/src/jit-test/tests/asm.js/testSIMD-load-store.js457
-rw-r--r--js/src/jit-test/tests/asm.js/testSIMD.js1575
-rw-r--r--js/src/jit-test/tests/asm.js/testSource.js398
-rw-r--r--js/src/jit-test/tests/asm.js/testStackWalking.js98
-rw-r--r--js/src/jit-test/tests/asm.js/testStealing.js19
-rw-r--r--js/src/jit-test/tests/asm.js/testTimeout1.js8
-rw-r--r--js/src/jit-test/tests/asm.js/testTimeout2.js8
-rw-r--r--js/src/jit-test/tests/asm.js/testTimeout3.js8
-rw-r--r--js/src/jit-test/tests/asm.js/testTimeout4.js8
-rw-r--r--js/src/jit-test/tests/asm.js/testTimeout5.js12
-rw-r--r--js/src/jit-test/tests/asm.js/testTimeout6.js12
-rw-r--r--js/src/jit-test/tests/asm.js/testUseAsmWarnings.js14
-rw-r--r--js/src/jit-test/tests/asm.js/testX86ByteStore.js77
-rw-r--r--js/src/jit-test/tests/asm.js/testZOOB.js232
105 files changed, 14934 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/asm.js/bug1007512.js b/js/src/jit-test/tests/asm.js/bug1007512.js
new file mode 100644
index 000000000..657fed621
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug1007512.js
@@ -0,0 +1,8 @@
+// |jit-test| error: TypeError
+
+new(function(stdlib, n, heap) {
+ "use asm"
+ var x = new stdlib.Uint32Array(heap)
+ function f() {}
+ return f
+})
diff --git a/js/src/jit-test/tests/asm.js/bug1008636.js b/js/src/jit-test/tests/asm.js/bug1008636.js
new file mode 100644
index 000000000..03e52e9b1
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug1008636.js
@@ -0,0 +1,12 @@
+// |jit-test| error:TypeError
+// stdlib is undefined
+
+(function(stdlib, n, heap) {
+ "use asm"
+ var Int16ArrayView = new stdlib.Int16Array(heap)
+ function f() {
+ var x = 4.
+ Int16ArrayView[~~((1 ? .0 : .9) % x) >> 1] = 0
+ u(x)
+ }
+})()
diff --git a/js/src/jit-test/tests/asm.js/bug1126251.js b/js/src/jit-test/tests/asm.js/bug1126251.js
new file mode 100644
index 000000000..8470a9772
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug1126251.js
@@ -0,0 +1,53 @@
+load(libdir + "asm.js");
+
+// Bug 1126251
+var v = asmLink(asmCompile('global', `
+ "use asm";
+ var frd = global.Math.fround;
+ function e() {
+ var x = frd(.1e+71);
+ x = frd(x / x);
+ return +x;
+ }
+ return e;
+`), this)();
+
+assertEq(v, NaN);
+
+if (!isSimdAvailable() || typeof SIMD === 'undefined') {
+ quit(0);
+}
+
+var v = asmLink(asmCompile('global', `
+ "use asm";
+ var frd = global.Math.fround;
+ var Float32x4 = global.SIMD.Float32x4;
+ var splat = Float32x4.splat;
+ var ext = Float32x4.extractLane;
+ function e() {
+ var v = Float32x4(0,0,0,0);
+ var x = frd(0.);
+ v = splat(.1e+71);
+ x = ext(v,0);
+ x = frd(x / x);
+ return +x;
+ }
+ return e;
+`), this)();
+
+assertEq(v, NaN);
+
+// Bug 1130618: without GVN
+setJitCompilerOption("ion.gvn.enable", 0);
+var v = asmLink(asmCompile('global', `
+ "use asm";
+ var Float32x4 = global.SIMD.Float32x4;
+ var splat = Float32x4.splat;
+ var ext = Float32x4.extractLane;
+ function e() {
+ return +ext(splat(.1e+71),0);
+ }
+ return e;
+`), this)();
+
+assertEq(v, Infinity);
diff --git a/js/src/jit-test/tests/asm.js/bug1161298.js b/js/src/jit-test/tests/asm.js/bug1161298.js
new file mode 100644
index 000000000..604184915
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug1161298.js
@@ -0,0 +1,13 @@
+// The length exceeds INT32_MAX and should be rejected.
+
+if (!this.SharedArrayBuffer)
+ quit(0);
+
+var failed = false;
+try {
+ var sab = new SharedArrayBuffer((2147483648));
+}
+catch (e) {
+ failed = true;
+}
+assertEq(failed, true);
diff --git a/js/src/jit-test/tests/asm.js/bug1174372.js b/js/src/jit-test/tests/asm.js/bug1174372.js
new file mode 100644
index 000000000..e7031ea10
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug1174372.js
@@ -0,0 +1,6 @@
+// |jit-test| --no-baseline; --non-writable-jitcode
+(function(stdlib, foreign, heap) {
+ "use asm";
+ function f() {}
+ return f;
+})();
diff --git a/js/src/jit-test/tests/asm.js/bug1201124-simd-proxy.js b/js/src/jit-test/tests/asm.js/bug1201124-simd-proxy.js
new file mode 100644
index 000000000..edcc069ff
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug1201124-simd-proxy.js
@@ -0,0 +1,28 @@
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+if (typeof newGlobal !== 'function' ||
+ !isSimdAvailable() ||
+ typeof SIMD === 'undefined')
+{
+ quit();
+}
+
+var stdlib = new (newGlobal().Proxy)(this, new Proxy({
+ simdGet: 0,
+ getOwnPropertyDescriptor(t, pk) {
+ if (pk === "SIMD" && this.simdGet++ === 1) {
+ return {};
+ }
+ return Reflect.getOwnPropertyDescriptor(t, pk);
+ }
+}, {
+ get(t, pk, r) {
+ print("trap", pk);
+ return Reflect.get(t, pk, r);
+ }
+}));
+
+var m = asmCompile('stdlib', '"use asm"; var i4=stdlib.SIMD.Int32x4; var i4add=i4.add; return {}');
+
+assertAsmLinkFail(m, stdlib);
diff --git a/js/src/jit-test/tests/asm.js/bug1219954.js b/js/src/jit-test/tests/asm.js/bug1219954.js
new file mode 100644
index 000000000..041c6fe35
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug1219954.js
@@ -0,0 +1,13 @@
+// |jit-test| slow
+"use strict";
+
+if (!('oomTest' in this))
+ quit();
+
+let g = (function() {
+ "use asm";
+ function f() {}
+ return f;
+})();
+
+oomTest(() => "" + g);
diff --git a/js/src/jit-test/tests/asm.js/bug1268955-usestrict-semantics.js b/js/src/jit-test/tests/asm.js/bug1268955-usestrict-semantics.js
new file mode 100644
index 000000000..501c4392d
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug1268955-usestrict-semantics.js
@@ -0,0 +1,19 @@
+
+var scope = {};
+scope.mod = eval(`"use strict"; (function() { "use asm"; function f() {} return f; });`);
+
+scope.fun = scope.mod();
+
+var caught = false;
+for (let callee of ['mod', 'fun']) {
+ for (let getter of ['caller', 'arguments']) {
+ caught = false;
+ try {
+ scope[callee][getter];
+ } catch (e) {
+ caught = true;
+ assertEq(e instanceof TypeError, true);
+ }
+ assertEq(caught, true);
+ }
+}
diff --git a/js/src/jit-test/tests/asm.js/bug1276028.js b/js/src/jit-test/tests/asm.js/bug1276028.js
new file mode 100644
index 000000000..16f564060
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug1276028.js
@@ -0,0 +1,6 @@
+load(libdir + "asm.js");
+
+var f = asmLink(asmCompile(USE_ASM + "function a234567() { return 42 } return a234567"));
+assertEq(f(), 42);
+enableSPSProfiling();
+assertEq(f(), 42);
diff --git a/js/src/jit-test/tests/asm.js/bug1306506.js b/js/src/jit-test/tests/asm.js/bug1306506.js
new file mode 100644
index 000000000..69cfc7b0e
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug1306506.js
@@ -0,0 +1,7 @@
+f = (function(stdlib, foreign, heap) {
+ "use asm";
+ function f() {
+ return (1, 1 / 0)|0;
+ }
+ return f;
+});
diff --git a/js/src/jit-test/tests/asm.js/bug855526.js b/js/src/jit-test/tests/asm.js/bug855526.js
new file mode 100644
index 000000000..fd75b137d
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug855526.js
@@ -0,0 +1,13 @@
+// Don't assert.
+try {
+ eval('\
+ function asmModule(g, foreign, heap) {\
+ "use asm";\
+ let HEAP8 = new g.Int8Array(heap);\
+ function f() { return 17; } \
+ return {f: f};\
+ }\
+ let m = asmModule("", "", 1, "");\
+ ');
+} catch (ex) {
+}
diff --git a/js/src/jit-test/tests/asm.js/bug885976.js b/js/src/jit-test/tests/asm.js/bug885976.js
new file mode 100644
index 000000000..303a8d07f
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug885976.js
@@ -0,0 +1,12 @@
+// |jit-test| error: TypeError
+function test(stdlib, foreign) {
+ "use asm"
+ var ff = foreign.ff
+ function f(y) {
+ y = +y;
+ ff(0);
+ }
+ return f;
+};
+f = test(this, {ff: Object.defineProperty});
+f();
diff --git a/js/src/jit-test/tests/asm.js/bug923867.js b/js/src/jit-test/tests/asm.js/bug923867.js
new file mode 100644
index 000000000..59bd296b8
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug923867.js
@@ -0,0 +1,8 @@
+(function(a) {
+ "use asm"
+ var Infinity = a.Infinity
+ function f() {
+ Infinity - (2 ? (1. / .0) : +0)
+ }
+ return f
+})(this)()
diff --git a/js/src/jit-test/tests/asm.js/bug927389.js b/js/src/jit-test/tests/asm.js/bug927389.js
new file mode 100644
index 000000000..ad2ea74d7
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug927389.js
@@ -0,0 +1,6 @@
+(function() {
+ "use asm"
+ function f() {
+ +~~1.1
+ }
+})()
diff --git a/js/src/jit-test/tests/asm.js/bug928450.js b/js/src/jit-test/tests/asm.js/bug928450.js
new file mode 100644
index 000000000..a12036735
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug928450.js
@@ -0,0 +1,18 @@
+(function() {
+ "use asm";
+ function f() {
+ i((1.5 != 2.) ? 3 : 0);
+ }
+ return f;
+})();
+
+// Bug 933104
+(function() {
+ "use asm";
+ function f(x) {
+ x = +x;
+ x = -2.;
+ (x > -1.5) ? 0 : 0;
+ }
+ return f;
+})()
diff --git a/js/src/jit-test/tests/asm.js/bug940864.js b/js/src/jit-test/tests/asm.js/bug940864.js
new file mode 100644
index 000000000..4df37bb40
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug940864.js
@@ -0,0 +1,10 @@
+function a()
+{
+ "use asm";
+ function f()
+ {
+ return (((((-1) >>> (0+0)) | 0) % 10000) >> (0+0)) | 0;
+ }
+ return f;
+}
+assertEq(a()(), -1);
diff --git a/js/src/jit-test/tests/asm.js/bug941877.js b/js/src/jit-test/tests/asm.js/bug941877.js
new file mode 100644
index 000000000..c2033cf8d
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug941877.js
@@ -0,0 +1,164 @@
+load(libdir + "asm.js");
+
+function FunctionBody(f) {
+ var str = f.toString();
+ var firstBrace = str.indexOf('{');
+ var lastBrace = str.lastIndexOf('}');
+ return str.substr(firstBrace + 1, lastBrace - firstBrace - 1);
+}
+
+var F = (function (stdlib, n, heap) {
+ var Int16ArrayView = new stdlib.Int16Array(heap);
+ function f(i0, d1) {
+ i0 = i0 | 0
+ d1 = +d1
+ var d2 = 1.
+ var i3 = 0
+ Int16ArrayView[0] = i0
+ d2 = (.0 / .0)
+ switch ((i0 + i0) | 0) {
+ case 0:
+ d2 = .0
+ break
+ };
+ (((i3 - (0 < 0)) >>> ((.0 < -0) + (.0 > .0))) / 0) >> (0 + (((0 + 0) ^
+(9 > 0)) | 0))
+ }
+ return f;
+});
+
+var compiled = asmCompile('stdlib', 'n', 'heap', USE_ASM + FunctionBody(F));
+asmLink(compiled, this, null, new ArrayBuffer(BUF_MIN))();
+
+var F = (function(stdlib, n, heap) {
+ var Float64ArrayView = new stdlib.Float64Array(heap)
+ function f() {
+ Float64ArrayView[0] = +(0xffffffff / 0xffffffff >> 0)
+ }
+ return f;
+});
+
+var compiled = asmCompile('stdlib', 'n', 'heap', USE_ASM + FunctionBody(F));
+asmLink(compiled, this, null, new ArrayBuffer(BUF_MIN))();
+
+function test0(x)
+{
+ return (x >>> 0) % 10;
+}
+assertEq(test0(25), 5);
+assertEq(test0(24), 4);
+assertEq(test0(23), 3);
+assertEq(test0(0), 0);
+assertEq(test0(4294967295), 5);
+
+function test1(x)
+{
+ return (x >>> 2) % 10;
+}
+assertEq(test1(25), 6);
+assertEq(test1(24), 6);
+assertEq(test1(23), 5);
+assertEq(test1(4294967295), 3);
+
+function test2(x, y)
+{
+ return (x >>> 0) % (y >>> 0);
+}
+assertEq(test2(25, 3), 1);
+assertEq(test2(24, 4), 0);
+assertEq(test2(4294967295, 10), 5);
+assertEq(test2(23, 0), NaN);
+
+function test3()
+{
+ function f(x, y)
+ {
+ x = x|0;
+ y = y|0;
+ var t = 0;
+ t = (((x|0) % (y|0))|0) > -2;
+ return t|0;
+ }
+ return f;
+}
+var compiled = asmCompile(USE_ASM + FunctionBody(test3));
+var linked = asmLink(compiled);
+assertEq(linked(4294967290, 4294967295), 1);
+assertEq(linked(4294967290, 4294967295), 1);
+
+function test4()
+{
+ function f(x, y)
+ {
+ x = x|0;
+ y = y|0;
+ var t = 0;
+ t = (((x>>>0) % (y>>>0)) >>> 0) > 0;
+ return t|0;
+ }
+ return f;
+}
+var compiled = asmCompile(USE_ASM + FunctionBody(test4));
+var linked = asmLink(compiled);
+assertEq(linked(4294967290, 4294967295), 1);
+assertEq(linked(4294967290, 4294967295), 1);
+
+function test5()
+{
+ function f(x, y)
+ {
+ x = x|0;
+ y = y|0;
+ var t = 0.;
+ t = +(((x>>>0) % (y>>>0)) >>> 0) * 1.01;
+ return +t;
+ }
+ return f;
+}
+var compiled = asmCompile(USE_ASM + FunctionBody(test5));
+var linked = asmLink(compiled);
+assertEq(linked(4294967290, 4294967295), 4337916962.9);
+assertEq(linked(4294967290, 4294967295), 4337916962.9);
+
+function test6()
+{
+ function f(x, y)
+ {
+ x = x|0;
+ y = y|0;
+ return ((x>>>1) % (y>>>1))|0;
+ }
+ return f;
+}
+var compiled = asmCompile(USE_ASM + FunctionBody(test6));
+var linked = asmLink(compiled);
+assertEq(linked(23847, 7), 1);
+assertEq(linked(23848, 7), 2);
+
+function test7()
+{
+ function f(x)
+ {
+ x = x|0;
+ return ((x>>>0) / 8)|0;
+ }
+ return f;
+}
+var compiled = asmCompile(USE_ASM + FunctionBody(test7));
+var linked = asmLink(compiled);
+assertEq(linked(23847, 7), 2980);
+assertEq(linked(23848, 7), 2981);
+
+function test8()
+{
+ function f(i,j)
+ {
+ i=i|0;j=j|0;
+ return ((i>>>0)/(j>>>0))|0;
+ }
+ return f;
+}
+var compiled = asmCompile(USE_ASM + FunctionBody(test8));
+var linked = asmLink(compiled);
+assertEq(linked(2147483647, 0), 0);
+assertEq(linked(2147483646, 0), 0);
diff --git a/js/src/jit-test/tests/asm.js/directives.txt b/js/src/jit-test/tests/asm.js/directives.txt
new file mode 100644
index 000000000..bdc583321
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/directives.txt
@@ -0,0 +1 @@
+|jit-test| test-also-noasmjs; test-also-wasm-baseline
diff --git a/js/src/jit-test/tests/asm.js/gating.js b/js/src/jit-test/tests/asm.js/gating.js
new file mode 100644
index 000000000..8c2168fb6
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/gating.js
@@ -0,0 +1,79 @@
+// Check gating of shared memory features in asm.js (bug 1171540,
+// bug 1231624, bug 1231338, bug 1231335).
+//
+// In asm.js, importing any atomic is a signal that shared memory is
+// being used. If an atomic is imported, and if shared memory is
+// disabled in the build or in the run then an error should be
+// signaled for the module.
+//
+// We check these constraints during linking: the linker checks that
+// the buffer has the right type and that the Atomics - if used - have
+// their expected values; if shared memory is disabled then the
+// Atomics object will be absent from the global or it will have
+// values that are not the expected built-in values and the link will
+// fail as desired.
+
+load(libdir + "asm.js");
+
+if (!isAsmJSCompilationAvailable())
+ quit(0);
+
+setJitCompilerOption('asmjs.atomics.enable', 1);
+
+if (!this.Atomics) {
+ this.Atomics = { load: function (x, y) { return 0 },
+ store: function (x, y, z) { return 0 },
+ exchange: function (x, y, z) { return 0 },
+ add: function (x, y, z) { return 0 },
+ sub: function (x, y, z) { return 0 },
+ and: function (x, y, z) { return 0 },
+ or: function (x, y, z) { return 0 },
+ xor: function (x, y, z) { return 0 },
+ compareExchange: function (x, y, z, w) { return 0 }
+ };
+}
+
+
+var module_a = asmCompile("stdlib", "foreign", "heap", `
+ "use asm";
+
+ var ld = stdlib.Atomics.load;
+
+ function f() { return 0; }
+ return { f:f };
+`);
+
+var module_b = asmCompile("stdlib", "foreign", "heap", `
+ "use asm";
+
+ var ld = stdlib.Atomics.load;
+ var i32a = new stdlib.Int32Array(heap);
+
+ function f() { return 0; }
+ return { f:f };
+`);
+
+var module_c = asmCompile("stdlib", "foreign", "heap", `
+ "use asm";
+
+ var i32a = new stdlib.Int32Array(heap);
+
+ function f() { return 0; }
+ return { f:f };
+`);
+
+assertEq(isAsmJSModule(module_a), true);
+assertEq(isAsmJSModule(module_b), true);
+assertEq(isAsmJSModule(module_c), true);
+
+if (!this.SharedArrayBuffer) {
+ assertAsmLinkFail(module_a, this, {}, new ArrayBuffer(65536)); // Buffer is ignored, Atomics are bad
+} else {
+ asmLink(module_a, this, {}, new ArrayBuffer(65536)); // Buffer is ignored, Atomics are good
+ assertAsmLinkFail(module_b, this, {}, new ArrayBuffer(65536)); // Buffer is wrong type
+}
+
+asmLink(module_c, this, {}, new ArrayBuffer(65536)); // Buffer is right type
+
+if (this.SharedArrayBuffer)
+ assertAsmLinkFail(module_c, this, {}, new SharedArrayBuffer(65536)); // Buffer is wrong type
diff --git a/js/src/jit-test/tests/asm.js/neuter-during-arguments-coercion.js b/js/src/jit-test/tests/asm.js/neuter-during-arguments-coercion.js
new file mode 100644
index 000000000..bfe8913e7
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/neuter-during-arguments-coercion.js
@@ -0,0 +1,27 @@
+load(libdir + "asm.js");
+
+function f(stdlib, foreign, buffer)
+{
+ "use asm";
+ var i32 = new stdlib.Int32Array(buffer);
+ function set(v)
+ {
+ v=v|0;
+ i32[5] = v;
+ }
+ return set;
+}
+if (isAsmJSCompilationAvailable())
+ assertEq(isAsmJSModule(f), true);
+
+var i32 = new Int32Array(65536);
+var buffer = i32.buffer;
+var set = f(this, null, buffer);
+if (isAsmJSCompilationAvailable())
+ assertEq(isAsmJSFunction(set), true);
+
+try
+{
+ set({ valueOf() { detachArrayBuffer(buffer); return 17; } });
+}
+catch (e) { /* if an exception thrown, swallow */ }
diff --git a/js/src/jit-test/tests/asm.js/oom-helper-thread-plus-validation-error.js b/js/src/jit-test/tests/asm.js/oom-helper-thread-plus-validation-error.js
new file mode 100644
index 000000000..272337823
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/oom-helper-thread-plus-validation-error.js
@@ -0,0 +1,11 @@
+if (typeof oomAfterAllocations !== 'function' || typeof evaluate !== 'function')
+ quit();
+
+oomAfterAllocations(10, 2);
+evaluate(`function mod(stdlib, ffi, heap) {
+ "use asm";
+ function f3(k) {
+ k = k | 0;
+ }
+ function g3(k) {}
+}`);
diff --git a/js/src/jit-test/tests/asm.js/oom-helper-thread.js b/js/src/jit-test/tests/asm.js/oom-helper-thread.js
new file mode 100644
index 000000000..bb1550ba1
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/oom-helper-thread.js
@@ -0,0 +1,8 @@
+// |jit-test| exitstatus: 3
+
+if (typeof oomAfterAllocations !== 'function') {
+ quit(3);
+}
+
+oomAfterAllocations(50, 2);
+eval("(function() {'use asm'; function f() { return +pow(.0, .0) })")
diff --git a/js/src/jit-test/tests/asm.js/simd-fbirds.js b/js/src/jit-test/tests/asm.js/simd-fbirds.js
new file mode 100644
index 000000000..97b7e2974
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/simd-fbirds.js
@@ -0,0 +1,198 @@
+/* -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 ; js-indent-level : 2 ; js-curly-indent-offset: 0 -*- */
+/* vim: set ts=4 et sw=4 tw=80: */
+
+// Author: Peter Jensen
+
+load(libdir + "asm.js");
+if (!isSimdAvailable() || typeof SIMD === 'undefined') {
+ print("won't run tests as simd extensions aren't activated yet");
+ quit(0);
+}
+
+const NUM_BIRDS = 30;
+const NUM_UPDATES = 20;
+const ACCEL_DATA_STEPS = 30;
+
+var buffer = new ArrayBuffer(0x200000);
+var bufferF32 = new Float32Array(buffer);
+
+var actualBirds = 0;
+
+function init() {
+ actualBirds = 0;
+ // Make it a power of two, for quick modulo wrapping.
+ var accelDataValues = [10.0, 9.5, 9.0, 8.0, 7.0, 6.0, 5.5, 5.0, 5.0, 5.0, 5.5, 6.0, 7.0, 8.0, 9.0, 10.0];
+ accelDataValues = accelDataValues.map(function(v) { return 50*v; });
+ var accelDataValuesLength = accelDataValues.length;
+ assertEq(accelDataValuesLength, 16); // Hard coded in the asm.js module
+ for (i = 0; i < accelDataValuesLength; i++)
+ bufferF32[i + NUM_BIRDS * 2] = accelDataValues[i];
+}
+
+function addBird(pos, vel) {
+ bufferF32[actualBirds] = pos;
+ bufferF32[actualBirds + NUM_BIRDS] = vel;
+ actualBirds++;
+ return actualBirds - 1;
+}
+
+function getActualBirds() {
+ return actualBirds;
+}
+
+var code = `
+ "use asm";
+ var toF = global.Math.fround;
+ var u8 = new global.Uint8Array(buffer);
+ var f32 = new global.Float32Array(buffer);
+ const maxBirds = 100000;
+ const maxBirdsx4 = 400000;
+ const maxBirdsx8 = 800000;
+ const accelMask = 0x3c;
+ const mk4 = 0x000ffff0;
+
+ const getMaxPos = 1000.0;
+ const getAccelDataSteps = imp.accelDataSteps | 0;
+ var getActualBirds = imp.getActualBirds;
+
+ var i4 = global.SIMD.Int32x4;
+ var f4 = global.SIMD.Float32x4;
+ var b4 = global.SIMD.Bool32x4;
+ var i4add = i4.add;
+ var i4and = i4.and;
+ var f4select = f4.select;
+ var f4add = f4.add;
+ var f4sub = f4.sub;
+ var f4mul = f4.mul;
+ var f4greaterThan = f4.greaterThan;
+ var f4splat = f4.splat;
+ var f4load = f4.load;
+ var f4store = f4.store;
+ var b4any = b4.anyTrue;
+
+ const zerox4 = f4(0.0,0.0,0.0,0.0);
+
+ function declareHeapSize() {
+ f32[0x0007ffff] = toF(0.0);
+ }
+
+ function update(timeDelta) {
+ timeDelta = toF(timeDelta);
+ // var steps = Math.ceil(timeDelta/accelData.interval);
+ var steps = 0;
+ var subTimeDelta = toF(0.0);
+ var actualBirds = 0;
+ var maxPos = toF(0.0);
+ var maxPosx4 = f4(0.0,0.0,0.0,0.0);
+ var subTimeDeltax4 = f4(0.0,0.0,0.0,0.0);
+ var subTimeDeltaSquaredx4 = f4(0.0,0.0,0.0,0.0);
+ var point5x4 = f4(0.5, 0.5, 0.5, 0.5);
+ var i = 0;
+ var len = 0;
+ var accelIndex = 0;
+ var newPosx4 = f4(0.0,0.0,0.0,0.0);
+ var newVelx4 = f4(0.0,0.0,0.0,0.0);
+ var accel = toF(0.0);
+ var accelx4 = f4(0.0,0.0,0.0,0.0);
+ var a = 0;
+ var posDeltax4 = f4(0.0,0.0,0.0,0.0);
+ var cmpx4 = b4(0,0,0,0);
+ var newVelTruex4 = f4(0.0,0.0,0.0,0.0);
+
+ steps = getAccelDataSteps | 0;
+ subTimeDelta = toF(toF(timeDelta / toF(steps | 0)) / toF(1000.0));
+ actualBirds = getActualBirds() | 0;
+ maxPos = toF(+getMaxPos);
+ maxPosx4 = f4splat(maxPos);
+ subTimeDeltax4 = f4splat(subTimeDelta);
+ subTimeDeltaSquaredx4 = f4mul(subTimeDeltax4, subTimeDeltax4);
+
+ len = ((actualBirds + 3) >> 2) << 4;
+
+ for (i = 0; (i | 0) < (len | 0); i = (i + 16) | 0) {
+ accelIndex = 0;
+ newPosx4 = f4load(u8, i & mk4);
+ newVelx4 = f4load(u8, (i & mk4) + maxBirdsx4);
+ for (a = 0; (a | 0) < (steps | 0); a = (a + 1) | 0) {
+ accel = toF(f32[(accelIndex & accelMask) + maxBirdsx8 >> 2]);
+ accelx4 = f4splat(accel);
+ accelIndex = (accelIndex + 4) | 0;
+ posDeltax4 = f4mul(point5x4, f4mul(accelx4, subTimeDeltaSquaredx4));
+ posDeltax4 = f4add(posDeltax4, f4mul(newVelx4, subTimeDeltax4));
+ newPosx4 = f4add(newPosx4, posDeltax4);
+ newVelx4 = f4add(newVelx4, f4mul(accelx4, subTimeDeltax4));
+ cmpx4 = f4greaterThan(newPosx4, maxPosx4);
+
+ if (b4any(cmpx4)) {
+ // Work around unimplemented 'neg' operation, using 0 - x.
+ newVelTruex4 = f4sub(zerox4, newVelx4);
+ newVelx4 = f4select(cmpx4, newVelTruex4, newVelx4);
+ }
+ }
+ f4store(u8, i & mk4, newPosx4);
+ f4store(u8, (i & mk4) + maxBirdsx4, newVelx4);
+ }
+ }
+
+ return update;
+`
+
+var ffi = {
+ getActualBirds,
+ accelDataSteps: ACCEL_DATA_STEPS
+};
+
+var fbirds = asmLink(asmCompile('global', 'imp', 'buffer', code), this, ffi, buffer);
+
+init();
+for (var i = 0; i < NUM_BIRDS; i++) {
+ addBird(i / 10, Math.exp(2, NUM_BIRDS - i));
+}
+
+var b = dateNow();
+for (var j = 0; j < NUM_UPDATES; j++) {
+ fbirds(16);
+}
+print(dateNow() - b);
+
+assertEq(bufferF32[0], 0);
+assertEq(bufferF32[1], 0.10000000149011612);
+assertEq(bufferF32[2], 0.20000000298023224);
+assertEq(bufferF32[3], 0.30000001192092896);
+assertEq(bufferF32[4], 0.4000000059604645);
+assertEq(bufferF32[5], 0.5);
+assertEq(bufferF32[6], 0.6000000238418579);
+assertEq(bufferF32[7], 0.699999988079071);
+assertEq(bufferF32[8], 0.800000011920929);
+assertEq(bufferF32[9], 0.8999999761581421);
+assertEq(bufferF32[10], 1);
+assertEq(bufferF32[11], 1.100000023841858);
+assertEq(bufferF32[12], 1.2000000476837158);
+assertEq(bufferF32[13], 1.2999999523162842);
+assertEq(bufferF32[14], 1.399999976158142);
+assertEq(bufferF32[15], 1.5);
+assertEq(bufferF32[16], 1.600000023841858);
+assertEq(bufferF32[17], 1.7000000476837158);
+assertEq(bufferF32[18], 1.7999999523162842);
+assertEq(bufferF32[19], 1.899999976158142);
+assertEq(bufferF32[20], 2);
+assertEq(bufferF32[21], 2.0999999046325684);
+assertEq(bufferF32[22], 2.200000047683716);
+assertEq(bufferF32[23], 2.299999952316284);
+assertEq(bufferF32[24], 2.4000000953674316);
+assertEq(bufferF32[25], 2.5);
+assertEq(bufferF32[26], 2.5999999046325684);
+assertEq(bufferF32[27], 2.700000047683716);
+assertEq(bufferF32[28], 2.799999952316284);
+assertEq(bufferF32[29], 2.9000000953674316);
+
+
+// Code used to generate the assertEq list above.
+function generateAssertList() {
+ var buf = '';
+ for (var k = 0; k < NUM_BIRDS; k++) {
+ buf += 'assertEq(bufferF32['+ k + '], ' + bufferF32[k] + ');\n';
+ }
+ print(buf);
+}
+//generateAssertList();
diff --git a/js/src/jit-test/tests/asm.js/simd-mandelbrot.js b/js/src/jit-test/tests/asm.js/simd-mandelbrot.js
new file mode 100644
index 000000000..349f2062d
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/simd-mandelbrot.js
@@ -0,0 +1,1819 @@
+/* -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 ; js-indent-level : 2 ; js-curly-indent-offset: 0 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+// Mandelbrot using SIMD
+// Author: Peter Jensen, Intel Corporation
+
+load(libdir + "asm.js");
+if (!isSimdAvailable() || typeof SIMD === 'undefined') {
+ print("won't run tests as simd extensions aren't activated yet");
+ quit(0);
+}
+
+// global variables
+const MAX_ITERATIONS = 10;
+const DRAW_ITERATIONS = 10;
+
+const CANVAS_WIDTH = 20;
+const CANVAS_HEIGHT = 20;
+
+const LIMIT_SHOW = 20 * 20 * 4;
+
+// Asm.js module buffer.
+var buffer = new ArrayBuffer(16 * 1024 * 1024);
+var view = new Uint8Array(buffer);
+
+var moduleCode = `
+ "use asm"
+ var b8 = new global.Uint8Array(buffer);
+ var toF = global.Math.fround;
+ var i4 = global.SIMD.Int32x4;
+ var ci4 = i4.check;
+ var f4 = global.SIMD.Float32x4;
+ var i4add = i4.add;
+ var i4and = i4.and;
+ var i4ext = i4.extractLane;
+ var i4sel = i4.select;
+ var f4add = f4.add;
+ var f4sub = f4.sub;
+ var f4mul = f4.mul;
+ var f4lessThanOrEqual = f4.lessThanOrEqual;
+ var f4splat = f4.splat;
+ var imul = global.Math.imul;
+ var b4 = global.SIMD.Bool32x4;
+ var b4any = b4.anyTrue;
+ const zero4 = i4(0,0,0,0), one4 = i4(1,1,1,1), two4 = f4(2,2,2,2), four4 = f4(4,4,4,4);
+
+ const mk0 = 0x007fffff;
+
+ function declareHeapLength() {
+ b8[0x00ffffff] = 0;
+ }
+
+ function mapColorAndSetPixel (x, y, width, value, max_iterations) {
+ x = x | 0;
+ y = y | 0;
+ width = width | 0;
+ value = value | 0;
+ max_iterations = max_iterations | 0;
+
+ var rgb = 0, r = 0, g = 0, b = 0, index = 0;
+
+ index = (((imul((width >>> 0), (y >>> 0)) + x) | 0) * 4) | 0;
+ if ((value | 0) == (max_iterations | 0)) {
+ r = 0;
+ g = 0;
+ b = 0;
+ } else {
+ rgb = ~~toF(toF(toF(toF(value >>> 0) * toF(0xffff)) / toF(max_iterations >>> 0)) * toF(0xff));
+ r = rgb & 0xff;
+ g = (rgb >>> 8) & 0xff;
+ b = (rgb >>> 16) & 0xff;
+ }
+ b8[(index & mk0) >> 0] = r;
+ b8[(index & mk0) + 1 >> 0] = g;
+ b8[(index & mk0) + 2 >> 0] = b;
+ b8[(index & mk0) + 3 >> 0] = 255;
+ }
+
+ function mandelPixelX4 (xf, yf, yd, max_iterations) {
+ xf = toF(xf);
+ yf = toF(yf);
+ yd = toF(yd);
+ max_iterations = max_iterations | 0;
+ var c_re4 = f4(0,0,0,0), c_im4 = f4(0,0,0,0);
+ var z_re4 = f4(0,0,0,0), z_im4 = f4(0,0,0,0);
+ var count4 = i4(0,0,0,0);
+ var z_re24 = f4(0,0,0,0), z_im24 = f4(0,0,0,0);
+ var new_re4 = f4(0,0,0,0), new_im4 = f4(0,0,0,0);
+ var i = 0;
+ var mb4 = b4(0,0,0,0);
+
+ c_re4 = f4splat(xf);
+ c_im4 = f4(yf, toF(yd + yf), toF(yd + toF(yd + yf)), toF(yd + toF(yd + toF(yd + yf))));
+
+ z_re4 = c_re4;
+ z_im4 = c_im4;
+
+ for (i = 0; (i | 0) < (max_iterations | 0); i = (i + 1) | 0) {
+ z_re24 = f4mul(z_re4, z_re4);
+ z_im24 = f4mul(z_im4, z_im4);
+ mb4 = f4lessThanOrEqual(f4add(z_re24, z_im24), four4);
+ // If all 4 values are greater than 4.0, there's no reason to continue.
+ if (!b4any(mb4))
+ break;
+
+ new_re4 = f4sub(z_re24, z_im24);
+ new_im4 = f4mul(f4mul(two4, z_re4), z_im4);
+ z_re4 = f4add(c_re4, new_re4);
+ z_im4 = f4add(c_im4, new_im4);
+ count4 = i4add(count4, i4sel(mb4, one4, zero4));
+ }
+ return ci4(count4);
+ }
+
+ function mandelColumnX4 (x, width, height, xf, yf, yd, max_iterations) {
+ x = x | 0;
+ width = width | 0;
+ height = height | 0;
+ xf = toF(xf);
+ yf = toF(yf);
+ yd = toF(yd);
+ max_iterations = max_iterations | 0;
+
+ var y = 0;
+ var ydx4 = toF(0);
+ var m4 = i4(0,0,0,0);
+
+ ydx4 = toF(yd * toF(4));
+ for (y = 0; (y | 0) < (height | 0); y = (y + 4) | 0) {
+ m4 = ci4(mandelPixelX4(toF(xf), toF(yf), toF(yd), max_iterations));
+ mapColorAndSetPixel(x | 0, y | 0, width, i4ext(m4,0), max_iterations);
+ mapColorAndSetPixel(x | 0, (y + 1) | 0, width, i4ext(m4,1), max_iterations);
+ mapColorAndSetPixel(x | 0, (y + 2) | 0, width, i4ext(m4,2), max_iterations);
+ mapColorAndSetPixel(x | 0, (y + 3) | 0, width, i4ext(m4,3), max_iterations);
+ yf = toF(yf + ydx4);
+ }
+ }
+
+ function mandel (width, height, xc, yc, scale, max_iterations) {
+ width = width | 0;
+ height = height | 0;
+ xc = toF(xc);
+ yc = toF(yc);
+ scale = toF(scale);
+ max_iterations = max_iterations | 0;
+
+ var x0 = toF(0), y0 = toF(0);
+ var xd = toF(0), yd = toF(0);
+ var xf = toF(0);
+ var x = 0;
+
+ x0 = toF(xc - toF(scale * toF(1.5)));
+ y0 = toF(yc - scale);
+ xd = toF(toF(scale * toF(3)) / toF(width >>> 0));
+ yd = toF(toF(scale * toF(2)) / toF(height >>> 0));
+ xf = x0;
+
+ for (x = 0; (x | 0) < (width | 0); x = (x + 1) | 0) {
+ mandelColumnX4(x, width, height, xf, y0, yd, max_iterations);
+ xf = toF(xf + xd);
+ }
+ }
+
+ return mandel;
+`;
+
+var FFI = {};
+var mandelbro = asmLink(asmCompile('global', 'ffi', 'buffer', moduleCode), this, FFI, buffer);
+
+function animateMandelbrot () {
+ var scale_start = 1.0;
+ var scale_end = 0.0005;
+ var xc_start = -0.5;
+ var yc_start = 0.0;
+ var xc_end = 0.0;
+ var yc_end = 0.75;
+ var steps = 200.0;
+ var scale_step = (scale_end - scale_start)/steps;
+ var xc_step = (xc_end - xc_start)/steps;
+ var yc_step = (yc_end - yc_start)/steps;
+ var scale = scale_start;
+ var xc = xc_start;
+ var yc = yc_start;
+ var i = 0;
+ var now = dateNow();
+
+ function draw1 () {
+ mandelbro(CANVAS_WIDTH, CANVAS_HEIGHT, xc, yc, scale, MAX_ITERATIONS);
+ if (scale < scale_end || scale > scale_start) {
+ scale_step = -scale_step;
+ xc_step = -xc_step;
+ yc_step = -yc_step;
+ }
+ scale += scale_step;
+ xc += xc_step;
+ yc += yc_step;
+ i++;
+ }
+
+ var b = dateNow();
+ for (var j = DRAW_ITERATIONS; j --> 0;)
+ draw1();
+ print(dateNow() - b);
+}
+
+animateMandelbrot();
+
+assertEq(view[0], 0, "0th value should be 0");
+assertEq(view[1], 0, "1th value should be 0");
+assertEq(view[2], 0, "2th value should be 0");
+assertEq(view[3], 255, "3th value should be 255");
+assertEq(view[4], 230, "4th value should be 230");
+assertEq(view[5], 127, "5th value should be 127");
+assertEq(view[6], 25, "6th value should be 25");
+assertEq(view[7], 255, "7th value should be 255");
+assertEq(view[8], 230, "8th value should be 230");
+assertEq(view[9], 127, "9th value should be 127");
+assertEq(view[10], 25, "10th value should be 25");
+assertEq(view[11], 255, "11th value should be 255");
+assertEq(view[12], 205, "12th value should be 205");
+assertEq(view[13], 255, "13th value should be 255");
+assertEq(view[14], 50, "14th value should be 50");
+assertEq(view[15], 255, "15th value should be 255");
+assertEq(view[16], 205, "16th value should be 205");
+assertEq(view[17], 255, "17th value should be 255");
+assertEq(view[18], 50, "18th value should be 50");
+assertEq(view[19], 255, "19th value should be 255");
+assertEq(view[20], 205, "20th value should be 205");
+assertEq(view[21], 255, "21th value should be 255");
+assertEq(view[22], 50, "22th value should be 50");
+assertEq(view[23], 255, "23th value should be 255");
+assertEq(view[24], 205, "24th value should be 205");
+assertEq(view[25], 255, "25th value should be 255");
+assertEq(view[26], 50, "26th value should be 50");
+assertEq(view[27], 255, "27th value should be 255");
+assertEq(view[28], 205, "28th value should be 205");
+assertEq(view[29], 255, "29th value should be 255");
+assertEq(view[30], 50, "30th value should be 50");
+assertEq(view[31], 255, "31th value should be 255");
+assertEq(view[32], 179, "32th value should be 179");
+assertEq(view[33], 127, "33th value should be 127");
+assertEq(view[34], 76, "34th value should be 76");
+assertEq(view[35], 255, "35th value should be 255");
+assertEq(view[36], 179, "36th value should be 179");
+assertEq(view[37], 127, "37th value should be 127");
+assertEq(view[38], 76, "38th value should be 76");
+assertEq(view[39], 255, "39th value should be 255");
+assertEq(view[40], 179, "40th value should be 179");
+assertEq(view[41], 127, "41th value should be 127");
+assertEq(view[42], 76, "42th value should be 76");
+assertEq(view[43], 255, "43th value should be 255");
+assertEq(view[44], 154, "44th value should be 154");
+assertEq(view[45], 255, "45th value should be 255");
+assertEq(view[46], 101, "46th value should be 101");
+assertEq(view[47], 255, "47th value should be 255");
+assertEq(view[48], 78, "48th value should be 78");
+assertEq(view[49], 127, "49th value should be 127");
+assertEq(view[50], 178, "50th value should be 178");
+assertEq(view[51], 255, "51th value should be 255");
+assertEq(view[52], 52, "52th value should be 52");
+assertEq(view[53], 255, "53th value should be 255");
+assertEq(view[54], 203, "54th value should be 203");
+assertEq(view[55], 255, "55th value should be 255");
+assertEq(view[56], 154, "56th value should be 154");
+assertEq(view[57], 255, "57th value should be 255");
+assertEq(view[58], 101, "58th value should be 101");
+assertEq(view[59], 255, "59th value should be 255");
+assertEq(view[60], 179, "60th value should be 179");
+assertEq(view[61], 127, "61th value should be 127");
+assertEq(view[62], 76, "62th value should be 76");
+assertEq(view[63], 255, "63th value should be 255");
+assertEq(view[64], 205, "64th value should be 205");
+assertEq(view[65], 255, "65th value should be 255");
+assertEq(view[66], 50, "66th value should be 50");
+assertEq(view[67], 255, "67th value should be 255");
+assertEq(view[68], 205, "68th value should be 205");
+assertEq(view[69], 255, "69th value should be 255");
+assertEq(view[70], 50, "70th value should be 50");
+assertEq(view[71], 255, "71th value should be 255");
+assertEq(view[72], 230, "72th value should be 230");
+assertEq(view[73], 127, "73th value should be 127");
+assertEq(view[74], 25, "74th value should be 25");
+assertEq(view[75], 255, "75th value should be 255");
+assertEq(view[76], 230, "76th value should be 230");
+assertEq(view[77], 127, "77th value should be 127");
+assertEq(view[78], 25, "78th value should be 25");
+assertEq(view[79], 255, "79th value should be 255");
+assertEq(view[80], 0, "80th value should be 0");
+assertEq(view[81], 0, "81th value should be 0");
+assertEq(view[82], 0, "82th value should be 0");
+assertEq(view[83], 255, "83th value should be 255");
+assertEq(view[84], 230, "84th value should be 230");
+assertEq(view[85], 127, "85th value should be 127");
+assertEq(view[86], 25, "86th value should be 25");
+assertEq(view[87], 255, "87th value should be 255");
+assertEq(view[88], 205, "88th value should be 205");
+assertEq(view[89], 255, "89th value should be 255");
+assertEq(view[90], 50, "90th value should be 50");
+assertEq(view[91], 255, "91th value should be 255");
+assertEq(view[92], 205, "92th value should be 205");
+assertEq(view[93], 255, "93th value should be 255");
+assertEq(view[94], 50, "94th value should be 50");
+assertEq(view[95], 255, "95th value should be 255");
+assertEq(view[96], 205, "96th value should be 205");
+assertEq(view[97], 255, "97th value should be 255");
+assertEq(view[98], 50, "98th value should be 50");
+assertEq(view[99], 255, "99th value should be 255");
+assertEq(view[100], 205, "100th value should be 205");
+assertEq(view[101], 255, "101th value should be 255");
+assertEq(view[102], 50, "102th value should be 50");
+assertEq(view[103], 255, "103th value should be 255");
+assertEq(view[104], 205, "104th value should be 205");
+assertEq(view[105], 255, "105th value should be 255");
+assertEq(view[106], 50, "106th value should be 50");
+assertEq(view[107], 255, "107th value should be 255");
+assertEq(view[108], 205, "108th value should be 205");
+assertEq(view[109], 255, "109th value should be 255");
+assertEq(view[110], 50, "110th value should be 50");
+assertEq(view[111], 255, "111th value should be 255");
+assertEq(view[112], 179, "112th value should be 179");
+assertEq(view[113], 127, "113th value should be 127");
+assertEq(view[114], 76, "114th value should be 76");
+assertEq(view[115], 255, "115th value should be 255");
+assertEq(view[116], 179, "116th value should be 179");
+assertEq(view[117], 127, "117th value should be 127");
+assertEq(view[118], 76, "118th value should be 76");
+assertEq(view[119], 255, "119th value should be 255");
+assertEq(view[120], 154, "120th value should be 154");
+assertEq(view[121], 255, "121th value should be 255");
+assertEq(view[122], 101, "122th value should be 101");
+assertEq(view[123], 255, "123th value should be 255");
+assertEq(view[124], 103, "124th value should be 103");
+assertEq(view[125], 255, "125th value should be 255");
+assertEq(view[126], 152, "126th value should be 152");
+assertEq(view[127], 255, "127th value should be 255");
+assertEq(view[128], 0, "128th value should be 0");
+assertEq(view[129], 0, "129th value should be 0");
+assertEq(view[130], 0, "130th value should be 0");
+assertEq(view[131], 255, "131th value should be 255");
+assertEq(view[132], 0, "132th value should be 0");
+assertEq(view[133], 0, "133th value should be 0");
+assertEq(view[134], 0, "134th value should be 0");
+assertEq(view[135], 255, "135th value should be 255");
+assertEq(view[136], 128, "136th value should be 128");
+assertEq(view[137], 127, "137th value should be 127");
+assertEq(view[138], 127, "138th value should be 127");
+assertEq(view[139], 255, "139th value should be 255");
+assertEq(view[140], 154, "140th value should be 154");
+assertEq(view[141], 255, "141th value should be 255");
+assertEq(view[142], 101, "142th value should be 101");
+assertEq(view[143], 255, "143th value should be 255");
+assertEq(view[144], 179, "144th value should be 179");
+assertEq(view[145], 127, "145th value should be 127");
+assertEq(view[146], 76, "146th value should be 76");
+assertEq(view[147], 255, "147th value should be 255");
+assertEq(view[148], 205, "148th value should be 205");
+assertEq(view[149], 255, "149th value should be 255");
+assertEq(view[150], 50, "150th value should be 50");
+assertEq(view[151], 255, "151th value should be 255");
+assertEq(view[152], 205, "152th value should be 205");
+assertEq(view[153], 255, "153th value should be 255");
+assertEq(view[154], 50, "154th value should be 50");
+assertEq(view[155], 255, "155th value should be 255");
+assertEq(view[156], 230, "156th value should be 230");
+assertEq(view[157], 127, "157th value should be 127");
+assertEq(view[158], 25, "158th value should be 25");
+assertEq(view[159], 255, "159th value should be 255");
+assertEq(view[160], 0, "160th value should be 0");
+assertEq(view[161], 0, "161th value should be 0");
+assertEq(view[162], 0, "162th value should be 0");
+assertEq(view[163], 255, "163th value should be 255");
+assertEq(view[164], 230, "164th value should be 230");
+assertEq(view[165], 127, "165th value should be 127");
+assertEq(view[166], 25, "166th value should be 25");
+assertEq(view[167], 255, "167th value should be 255");
+assertEq(view[168], 205, "168th value should be 205");
+assertEq(view[169], 255, "169th value should be 255");
+assertEq(view[170], 50, "170th value should be 50");
+assertEq(view[171], 255, "171th value should be 255");
+assertEq(view[172], 205, "172th value should be 205");
+assertEq(view[173], 255, "173th value should be 255");
+assertEq(view[174], 50, "174th value should be 50");
+assertEq(view[175], 255, "175th value should be 255");
+assertEq(view[176], 205, "176th value should be 205");
+assertEq(view[177], 255, "177th value should be 255");
+assertEq(view[178], 50, "178th value should be 50");
+assertEq(view[179], 255, "179th value should be 255");
+assertEq(view[180], 205, "180th value should be 205");
+assertEq(view[181], 255, "181th value should be 255");
+assertEq(view[182], 50, "182th value should be 50");
+assertEq(view[183], 255, "183th value should be 255");
+assertEq(view[184], 205, "184th value should be 205");
+assertEq(view[185], 255, "185th value should be 255");
+assertEq(view[186], 50, "186th value should be 50");
+assertEq(view[187], 255, "187th value should be 255");
+assertEq(view[188], 179, "188th value should be 179");
+assertEq(view[189], 127, "189th value should be 127");
+assertEq(view[190], 76, "190th value should be 76");
+assertEq(view[191], 255, "191th value should be 255");
+assertEq(view[192], 179, "192th value should be 179");
+assertEq(view[193], 127, "193th value should be 127");
+assertEq(view[194], 76, "194th value should be 76");
+assertEq(view[195], 255, "195th value should be 255");
+assertEq(view[196], 154, "196th value should be 154");
+assertEq(view[197], 255, "197th value should be 255");
+assertEq(view[198], 101, "198th value should be 101");
+assertEq(view[199], 255, "199th value should be 255");
+assertEq(view[200], 103, "200th value should be 103");
+assertEq(view[201], 255, "201th value should be 255");
+assertEq(view[202], 152, "202th value should be 152");
+assertEq(view[203], 255, "203th value should be 255");
+assertEq(view[204], 78, "204th value should be 78");
+assertEq(view[205], 127, "205th value should be 127");
+assertEq(view[206], 178, "206th value should be 178");
+assertEq(view[207], 255, "207th value should be 255");
+assertEq(view[208], 0, "208th value should be 0");
+assertEq(view[209], 0, "209th value should be 0");
+assertEq(view[210], 0, "210th value should be 0");
+assertEq(view[211], 255, "211th value should be 255");
+assertEq(view[212], 0, "212th value should be 0");
+assertEq(view[213], 0, "213th value should be 0");
+assertEq(view[214], 0, "214th value should be 0");
+assertEq(view[215], 255, "215th value should be 255");
+assertEq(view[216], 78, "216th value should be 78");
+assertEq(view[217], 127, "217th value should be 127");
+assertEq(view[218], 178, "218th value should be 178");
+assertEq(view[219], 255, "219th value should be 255");
+assertEq(view[220], 128, "220th value should be 128");
+assertEq(view[221], 127, "221th value should be 127");
+assertEq(view[222], 127, "222th value should be 127");
+assertEq(view[223], 255, "223th value should be 255");
+assertEq(view[224], 154, "224th value should be 154");
+assertEq(view[225], 255, "225th value should be 255");
+assertEq(view[226], 101, "226th value should be 101");
+assertEq(view[227], 255, "227th value should be 255");
+assertEq(view[228], 205, "228th value should be 205");
+assertEq(view[229], 255, "229th value should be 255");
+assertEq(view[230], 50, "230th value should be 50");
+assertEq(view[231], 255, "231th value should be 255");
+assertEq(view[232], 205, "232th value should be 205");
+assertEq(view[233], 255, "233th value should be 255");
+assertEq(view[234], 50, "234th value should be 50");
+assertEq(view[235], 255, "235th value should be 255");
+assertEq(view[236], 230, "236th value should be 230");
+assertEq(view[237], 127, "237th value should be 127");
+assertEq(view[238], 25, "238th value should be 25");
+assertEq(view[239], 255, "239th value should be 255");
+assertEq(view[240], 0, "240th value should be 0");
+assertEq(view[241], 0, "241th value should be 0");
+assertEq(view[242], 0, "242th value should be 0");
+assertEq(view[243], 255, "243th value should be 255");
+assertEq(view[244], 205, "244th value should be 205");
+assertEq(view[245], 255, "245th value should be 255");
+assertEq(view[246], 50, "246th value should be 50");
+assertEq(view[247], 255, "247th value should be 255");
+assertEq(view[248], 205, "248th value should be 205");
+assertEq(view[249], 255, "249th value should be 255");
+assertEq(view[250], 50, "250th value should be 50");
+assertEq(view[251], 255, "251th value should be 255");
+assertEq(view[252], 205, "252th value should be 205");
+assertEq(view[253], 255, "253th value should be 255");
+assertEq(view[254], 50, "254th value should be 50");
+assertEq(view[255], 255, "255th value should be 255");
+assertEq(view[256], 205, "256th value should be 205");
+assertEq(view[257], 255, "257th value should be 255");
+assertEq(view[258], 50, "258th value should be 50");
+assertEq(view[259], 255, "259th value should be 255");
+assertEq(view[260], 205, "260th value should be 205");
+assertEq(view[261], 255, "261th value should be 255");
+assertEq(view[262], 50, "262th value should be 50");
+assertEq(view[263], 255, "263th value should be 255");
+assertEq(view[264], 179, "264th value should be 179");
+assertEq(view[265], 127, "265th value should be 127");
+assertEq(view[266], 76, "266th value should be 76");
+assertEq(view[267], 255, "267th value should be 255");
+assertEq(view[268], 179, "268th value should be 179");
+assertEq(view[269], 127, "269th value should be 127");
+assertEq(view[270], 76, "270th value should be 76");
+assertEq(view[271], 255, "271th value should be 255");
+assertEq(view[272], 154, "272th value should be 154");
+assertEq(view[273], 255, "273th value should be 255");
+assertEq(view[274], 101, "274th value should be 101");
+assertEq(view[275], 255, "275th value should be 255");
+assertEq(view[276], 52, "276th value should be 52");
+assertEq(view[277], 255, "277th value should be 255");
+assertEq(view[278], 203, "278th value should be 203");
+assertEq(view[279], 255, "279th value should be 255");
+assertEq(view[280], 0, "280th value should be 0");
+assertEq(view[281], 0, "281th value should be 0");
+assertEq(view[282], 0, "282th value should be 0");
+assertEq(view[283], 255, "283th value should be 255");
+assertEq(view[284], 0, "284th value should be 0");
+assertEq(view[285], 0, "285th value should be 0");
+assertEq(view[286], 0, "286th value should be 0");
+assertEq(view[287], 255, "287th value should be 255");
+assertEq(view[288], 0, "288th value should be 0");
+assertEq(view[289], 0, "289th value should be 0");
+assertEq(view[290], 0, "290th value should be 0");
+assertEq(view[291], 255, "291th value should be 255");
+assertEq(view[292], 0, "292th value should be 0");
+assertEq(view[293], 0, "293th value should be 0");
+assertEq(view[294], 0, "294th value should be 0");
+assertEq(view[295], 255, "295th value should be 255");
+assertEq(view[296], 0, "296th value should be 0");
+assertEq(view[297], 0, "297th value should be 0");
+assertEq(view[298], 0, "298th value should be 0");
+assertEq(view[299], 255, "299th value should be 255");
+assertEq(view[300], 52, "300th value should be 52");
+assertEq(view[301], 255, "301th value should be 255");
+assertEq(view[302], 203, "302th value should be 203");
+assertEq(view[303], 255, "303th value should be 255");
+assertEq(view[304], 52, "304th value should be 52");
+assertEq(view[305], 255, "305th value should be 255");
+assertEq(view[306], 203, "306th value should be 203");
+assertEq(view[307], 255, "307th value should be 255");
+assertEq(view[308], 179, "308th value should be 179");
+assertEq(view[309], 127, "309th value should be 127");
+assertEq(view[310], 76, "310th value should be 76");
+assertEq(view[311], 255, "311th value should be 255");
+assertEq(view[312], 205, "312th value should be 205");
+assertEq(view[313], 255, "313th value should be 255");
+assertEq(view[314], 50, "314th value should be 50");
+assertEq(view[315], 255, "315th value should be 255");
+assertEq(view[316], 205, "316th value should be 205");
+assertEq(view[317], 255, "317th value should be 255");
+assertEq(view[318], 50, "318th value should be 50");
+assertEq(view[319], 255, "319th value should be 255");
+assertEq(view[320], 230, "320th value should be 230");
+assertEq(view[321], 127, "321th value should be 127");
+assertEq(view[322], 25, "322th value should be 25");
+assertEq(view[323], 255, "323th value should be 255");
+assertEq(view[324], 205, "324th value should be 205");
+assertEq(view[325], 255, "325th value should be 255");
+assertEq(view[326], 50, "326th value should be 50");
+assertEq(view[327], 255, "327th value should be 255");
+assertEq(view[328], 205, "328th value should be 205");
+assertEq(view[329], 255, "329th value should be 255");
+assertEq(view[330], 50, "330th value should be 50");
+assertEq(view[331], 255, "331th value should be 255");
+assertEq(view[332], 205, "332th value should be 205");
+assertEq(view[333], 255, "333th value should be 255");
+assertEq(view[334], 50, "334th value should be 50");
+assertEq(view[335], 255, "335th value should be 255");
+assertEq(view[336], 205, "336th value should be 205");
+assertEq(view[337], 255, "337th value should be 255");
+assertEq(view[338], 50, "338th value should be 50");
+assertEq(view[339], 255, "339th value should be 255");
+assertEq(view[340], 179, "340th value should be 179");
+assertEq(view[341], 127, "341th value should be 127");
+assertEq(view[342], 76, "342th value should be 76");
+assertEq(view[343], 255, "343th value should be 255");
+assertEq(view[344], 154, "344th value should be 154");
+assertEq(view[345], 255, "345th value should be 255");
+assertEq(view[346], 101, "346th value should be 101");
+assertEq(view[347], 255, "347th value should be 255");
+assertEq(view[348], 154, "348th value should be 154");
+assertEq(view[349], 255, "349th value should be 255");
+assertEq(view[350], 101, "350th value should be 101");
+assertEq(view[351], 255, "351th value should be 255");
+assertEq(view[352], 128, "352th value should be 128");
+assertEq(view[353], 127, "353th value should be 127");
+assertEq(view[354], 127, "354th value should be 127");
+assertEq(view[355], 255, "355th value should be 255");
+assertEq(view[356], 52, "356th value should be 52");
+assertEq(view[357], 255, "357th value should be 255");
+assertEq(view[358], 203, "358th value should be 203");
+assertEq(view[359], 255, "359th value should be 255");
+assertEq(view[360], 0, "360th value should be 0");
+assertEq(view[361], 0, "361th value should be 0");
+assertEq(view[362], 0, "362th value should be 0");
+assertEq(view[363], 255, "363th value should be 255");
+assertEq(view[364], 0, "364th value should be 0");
+assertEq(view[365], 0, "365th value should be 0");
+assertEq(view[366], 0, "366th value should be 0");
+assertEq(view[367], 255, "367th value should be 255");
+assertEq(view[368], 0, "368th value should be 0");
+assertEq(view[369], 0, "369th value should be 0");
+assertEq(view[370], 0, "370th value should be 0");
+assertEq(view[371], 255, "371th value should be 255");
+assertEq(view[372], 0, "372th value should be 0");
+assertEq(view[373], 0, "373th value should be 0");
+assertEq(view[374], 0, "374th value should be 0");
+assertEq(view[375], 255, "375th value should be 255");
+assertEq(view[376], 0, "376th value should be 0");
+assertEq(view[377], 0, "377th value should be 0");
+assertEq(view[378], 0, "378th value should be 0");
+assertEq(view[379], 255, "379th value should be 255");
+assertEq(view[380], 0, "380th value should be 0");
+assertEq(view[381], 0, "381th value should be 0");
+assertEq(view[382], 0, "382th value should be 0");
+assertEq(view[383], 255, "383th value should be 255");
+assertEq(view[384], 52, "384th value should be 52");
+assertEq(view[385], 255, "385th value should be 255");
+assertEq(view[386], 203, "386th value should be 203");
+assertEq(view[387], 255, "387th value should be 255");
+assertEq(view[388], 179, "388th value should be 179");
+assertEq(view[389], 127, "389th value should be 127");
+assertEq(view[390], 76, "390th value should be 76");
+assertEq(view[391], 255, "391th value should be 255");
+assertEq(view[392], 205, "392th value should be 205");
+assertEq(view[393], 255, "393th value should be 255");
+assertEq(view[394], 50, "394th value should be 50");
+assertEq(view[395], 255, "395th value should be 255");
+assertEq(view[396], 205, "396th value should be 205");
+assertEq(view[397], 255, "397th value should be 255");
+assertEq(view[398], 50, "398th value should be 50");
+assertEq(view[399], 255, "399th value should be 255");
+assertEq(view[400], 205, "400th value should be 205");
+assertEq(view[401], 255, "401th value should be 255");
+assertEq(view[402], 50, "402th value should be 50");
+assertEq(view[403], 255, "403th value should be 255");
+assertEq(view[404], 205, "404th value should be 205");
+assertEq(view[405], 255, "405th value should be 255");
+assertEq(view[406], 50, "406th value should be 50");
+assertEq(view[407], 255, "407th value should be 255");
+assertEq(view[408], 205, "408th value should be 205");
+assertEq(view[409], 255, "409th value should be 255");
+assertEq(view[410], 50, "410th value should be 50");
+assertEq(view[411], 255, "411th value should be 255");
+assertEq(view[412], 205, "412th value should be 205");
+assertEq(view[413], 255, "413th value should be 255");
+assertEq(view[414], 50, "414th value should be 50");
+assertEq(view[415], 255, "415th value should be 255");
+assertEq(view[416], 154, "416th value should be 154");
+assertEq(view[417], 255, "417th value should be 255");
+assertEq(view[418], 101, "418th value should be 101");
+assertEq(view[419], 255, "419th value should be 255");
+assertEq(view[420], 128, "420th value should be 128");
+assertEq(view[421], 127, "421th value should be 127");
+assertEq(view[422], 127, "422th value should be 127");
+assertEq(view[423], 255, "423th value should be 255");
+assertEq(view[424], 154, "424th value should be 154");
+assertEq(view[425], 255, "425th value should be 255");
+assertEq(view[426], 101, "426th value should be 101");
+assertEq(view[427], 255, "427th value should be 255");
+assertEq(view[428], 128, "428th value should be 128");
+assertEq(view[429], 127, "429th value should be 127");
+assertEq(view[430], 127, "430th value should be 127");
+assertEq(view[431], 255, "431th value should be 255");
+assertEq(view[432], 103, "432th value should be 103");
+assertEq(view[433], 255, "433th value should be 255");
+assertEq(view[434], 152, "434th value should be 152");
+assertEq(view[435], 255, "435th value should be 255");
+assertEq(view[436], 0, "436th value should be 0");
+assertEq(view[437], 0, "437th value should be 0");
+assertEq(view[438], 0, "438th value should be 0");
+assertEq(view[439], 255, "439th value should be 255");
+assertEq(view[440], 0, "440th value should be 0");
+assertEq(view[441], 0, "441th value should be 0");
+assertEq(view[442], 0, "442th value should be 0");
+assertEq(view[443], 255, "443th value should be 255");
+assertEq(view[444], 0, "444th value should be 0");
+assertEq(view[445], 0, "445th value should be 0");
+assertEq(view[446], 0, "446th value should be 0");
+assertEq(view[447], 255, "447th value should be 255");
+assertEq(view[448], 0, "448th value should be 0");
+assertEq(view[449], 0, "449th value should be 0");
+assertEq(view[450], 0, "450th value should be 0");
+assertEq(view[451], 255, "451th value should be 255");
+assertEq(view[452], 0, "452th value should be 0");
+assertEq(view[453], 0, "453th value should be 0");
+assertEq(view[454], 0, "454th value should be 0");
+assertEq(view[455], 255, "455th value should be 255");
+assertEq(view[456], 0, "456th value should be 0");
+assertEq(view[457], 0, "457th value should be 0");
+assertEq(view[458], 0, "458th value should be 0");
+assertEq(view[459], 255, "459th value should be 255");
+assertEq(view[460], 0, "460th value should be 0");
+assertEq(view[461], 0, "461th value should be 0");
+assertEq(view[462], 0, "462th value should be 0");
+assertEq(view[463], 255, "463th value should be 255");
+assertEq(view[464], 78, "464th value should be 78");
+assertEq(view[465], 127, "465th value should be 127");
+assertEq(view[466], 178, "466th value should be 178");
+assertEq(view[467], 255, "467th value should be 255");
+assertEq(view[468], 154, "468th value should be 154");
+assertEq(view[469], 255, "469th value should be 255");
+assertEq(view[470], 101, "470th value should be 101");
+assertEq(view[471], 255, "471th value should be 255");
+assertEq(view[472], 205, "472th value should be 205");
+assertEq(view[473], 255, "473th value should be 255");
+assertEq(view[474], 50, "474th value should be 50");
+assertEq(view[475], 255, "475th value should be 255");
+assertEq(view[476], 205, "476th value should be 205");
+assertEq(view[477], 255, "477th value should be 255");
+assertEq(view[478], 50, "478th value should be 50");
+assertEq(view[479], 255, "479th value should be 255");
+assertEq(view[480], 205, "480th value should be 205");
+assertEq(view[481], 255, "481th value should be 255");
+assertEq(view[482], 50, "482th value should be 50");
+assertEq(view[483], 255, "483th value should be 255");
+assertEq(view[484], 205, "484th value should be 205");
+assertEq(view[485], 255, "485th value should be 255");
+assertEq(view[486], 50, "486th value should be 50");
+assertEq(view[487], 255, "487th value should be 255");
+assertEq(view[488], 179, "488th value should be 179");
+assertEq(view[489], 127, "489th value should be 127");
+assertEq(view[490], 76, "490th value should be 76");
+assertEq(view[491], 255, "491th value should be 255");
+assertEq(view[492], 179, "492th value should be 179");
+assertEq(view[493], 127, "493th value should be 127");
+assertEq(view[494], 76, "494th value should be 76");
+assertEq(view[495], 255, "495th value should be 255");
+assertEq(view[496], 128, "496th value should be 128");
+assertEq(view[497], 127, "497th value should be 127");
+assertEq(view[498], 127, "498th value should be 127");
+assertEq(view[499], 255, "499th value should be 255");
+assertEq(view[500], 52, "500th value should be 52");
+assertEq(view[501], 255, "501th value should be 255");
+assertEq(view[502], 203, "502th value should be 203");
+assertEq(view[503], 255, "503th value should be 255");
+assertEq(view[504], 0, "504th value should be 0");
+assertEq(view[505], 0, "505th value should be 0");
+assertEq(view[506], 0, "506th value should be 0");
+assertEq(view[507], 255, "507th value should be 255");
+assertEq(view[508], 78, "508th value should be 78");
+assertEq(view[509], 127, "509th value should be 127");
+assertEq(view[510], 178, "510th value should be 178");
+assertEq(view[511], 255, "511th value should be 255");
+assertEq(view[512], 52, "512th value should be 52");
+assertEq(view[513], 255, "513th value should be 255");
+assertEq(view[514], 203, "514th value should be 203");
+assertEq(view[515], 255, "515th value should be 255");
+assertEq(view[516], 0, "516th value should be 0");
+assertEq(view[517], 0, "517th value should be 0");
+assertEq(view[518], 0, "518th value should be 0");
+assertEq(view[519], 255, "519th value should be 255");
+assertEq(view[520], 0, "520th value should be 0");
+assertEq(view[521], 0, "521th value should be 0");
+assertEq(view[522], 0, "522th value should be 0");
+assertEq(view[523], 255, "523th value should be 255");
+assertEq(view[524], 0, "524th value should be 0");
+assertEq(view[525], 0, "525th value should be 0");
+assertEq(view[526], 0, "526th value should be 0");
+assertEq(view[527], 255, "527th value should be 255");
+assertEq(view[528], 0, "528th value should be 0");
+assertEq(view[529], 0, "529th value should be 0");
+assertEq(view[530], 0, "530th value should be 0");
+assertEq(view[531], 255, "531th value should be 255");
+assertEq(view[532], 0, "532th value should be 0");
+assertEq(view[533], 0, "533th value should be 0");
+assertEq(view[534], 0, "534th value should be 0");
+assertEq(view[535], 255, "535th value should be 255");
+assertEq(view[536], 0, "536th value should be 0");
+assertEq(view[537], 0, "537th value should be 0");
+assertEq(view[538], 0, "538th value should be 0");
+assertEq(view[539], 255, "539th value should be 255");
+assertEq(view[540], 0, "540th value should be 0");
+assertEq(view[541], 0, "541th value should be 0");
+assertEq(view[542], 0, "542th value should be 0");
+assertEq(view[543], 255, "543th value should be 255");
+assertEq(view[544], 0, "544th value should be 0");
+assertEq(view[545], 0, "545th value should be 0");
+assertEq(view[546], 0, "546th value should be 0");
+assertEq(view[547], 255, "547th value should be 255");
+assertEq(view[548], 154, "548th value should be 154");
+assertEq(view[549], 255, "549th value should be 255");
+assertEq(view[550], 101, "550th value should be 101");
+assertEq(view[551], 255, "551th value should be 255");
+assertEq(view[552], 205, "552th value should be 205");
+assertEq(view[553], 255, "553th value should be 255");
+assertEq(view[554], 50, "554th value should be 50");
+assertEq(view[555], 255, "555th value should be 255");
+assertEq(view[556], 205, "556th value should be 205");
+assertEq(view[557], 255, "557th value should be 255");
+assertEq(view[558], 50, "558th value should be 50");
+assertEq(view[559], 255, "559th value should be 255");
+assertEq(view[560], 205, "560th value should be 205");
+assertEq(view[561], 255, "561th value should be 255");
+assertEq(view[562], 50, "562th value should be 50");
+assertEq(view[563], 255, "563th value should be 255");
+assertEq(view[564], 179, "564th value should be 179");
+assertEq(view[565], 127, "565th value should be 127");
+assertEq(view[566], 76, "566th value should be 76");
+assertEq(view[567], 255, "567th value should be 255");
+assertEq(view[568], 179, "568th value should be 179");
+assertEq(view[569], 127, "569th value should be 127");
+assertEq(view[570], 76, "570th value should be 76");
+assertEq(view[571], 255, "571th value should be 255");
+assertEq(view[572], 154, "572th value should be 154");
+assertEq(view[573], 255, "573th value should be 255");
+assertEq(view[574], 101, "574th value should be 101");
+assertEq(view[575], 255, "575th value should be 255");
+assertEq(view[576], 103, "576th value should be 103");
+assertEq(view[577], 255, "577th value should be 255");
+assertEq(view[578], 152, "578th value should be 152");
+assertEq(view[579], 255, "579th value should be 255");
+assertEq(view[580], 0, "580th value should be 0");
+assertEq(view[581], 0, "581th value should be 0");
+assertEq(view[582], 0, "582th value should be 0");
+assertEq(view[583], 255, "583th value should be 255");
+assertEq(view[584], 0, "584th value should be 0");
+assertEq(view[585], 0, "585th value should be 0");
+assertEq(view[586], 0, "586th value should be 0");
+assertEq(view[587], 255, "587th value should be 255");
+assertEq(view[588], 0, "588th value should be 0");
+assertEq(view[589], 0, "589th value should be 0");
+assertEq(view[590], 0, "590th value should be 0");
+assertEq(view[591], 255, "591th value should be 255");
+assertEq(view[592], 0, "592th value should be 0");
+assertEq(view[593], 0, "593th value should be 0");
+assertEq(view[594], 0, "594th value should be 0");
+assertEq(view[595], 255, "595th value should be 255");
+assertEq(view[596], 0, "596th value should be 0");
+assertEq(view[597], 0, "597th value should be 0");
+assertEq(view[598], 0, "598th value should be 0");
+assertEq(view[599], 255, "599th value should be 255");
+assertEq(view[600], 0, "600th value should be 0");
+assertEq(view[601], 0, "601th value should be 0");
+assertEq(view[602], 0, "602th value should be 0");
+assertEq(view[603], 255, "603th value should be 255");
+assertEq(view[604], 0, "604th value should be 0");
+assertEq(view[605], 0, "605th value should be 0");
+assertEq(view[606], 0, "606th value should be 0");
+assertEq(view[607], 255, "607th value should be 255");
+assertEq(view[608], 0, "608th value should be 0");
+assertEq(view[609], 0, "609th value should be 0");
+assertEq(view[610], 0, "610th value should be 0");
+assertEq(view[611], 255, "611th value should be 255");
+assertEq(view[612], 0, "612th value should be 0");
+assertEq(view[613], 0, "613th value should be 0");
+assertEq(view[614], 0, "614th value should be 0");
+assertEq(view[615], 255, "615th value should be 255");
+assertEq(view[616], 0, "616th value should be 0");
+assertEq(view[617], 0, "617th value should be 0");
+assertEq(view[618], 0, "618th value should be 0");
+assertEq(view[619], 255, "619th value should be 255");
+assertEq(view[620], 0, "620th value should be 0");
+assertEq(view[621], 0, "621th value should be 0");
+assertEq(view[622], 0, "622th value should be 0");
+assertEq(view[623], 255, "623th value should be 255");
+assertEq(view[624], 0, "624th value should be 0");
+assertEq(view[625], 0, "625th value should be 0");
+assertEq(view[626], 0, "626th value should be 0");
+assertEq(view[627], 255, "627th value should be 255");
+assertEq(view[628], 154, "628th value should be 154");
+assertEq(view[629], 255, "629th value should be 255");
+assertEq(view[630], 101, "630th value should be 101");
+assertEq(view[631], 255, "631th value should be 255");
+assertEq(view[632], 205, "632th value should be 205");
+assertEq(view[633], 255, "633th value should be 255");
+assertEq(view[634], 50, "634th value should be 50");
+assertEq(view[635], 255, "635th value should be 255");
+assertEq(view[636], 205, "636th value should be 205");
+assertEq(view[637], 255, "637th value should be 255");
+assertEq(view[638], 50, "638th value should be 50");
+assertEq(view[639], 255, "639th value should be 255");
+assertEq(view[640], 179, "640th value should be 179");
+assertEq(view[641], 127, "641th value should be 127");
+assertEq(view[642], 76, "642th value should be 76");
+assertEq(view[643], 255, "643th value should be 255");
+assertEq(view[644], 179, "644th value should be 179");
+assertEq(view[645], 127, "645th value should be 127");
+assertEq(view[646], 76, "646th value should be 76");
+assertEq(view[647], 255, "647th value should be 255");
+assertEq(view[648], 154, "648th value should be 154");
+assertEq(view[649], 255, "649th value should be 255");
+assertEq(view[650], 101, "650th value should be 101");
+assertEq(view[651], 255, "651th value should be 255");
+assertEq(view[652], 128, "652th value should be 128");
+assertEq(view[653], 127, "653th value should be 127");
+assertEq(view[654], 127, "654th value should be 127");
+assertEq(view[655], 255, "655th value should be 255");
+assertEq(view[656], 52, "656th value should be 52");
+assertEq(view[657], 255, "657th value should be 255");
+assertEq(view[658], 203, "658th value should be 203");
+assertEq(view[659], 255, "659th value should be 255");
+assertEq(view[660], 0, "660th value should be 0");
+assertEq(view[661], 0, "661th value should be 0");
+assertEq(view[662], 0, "662th value should be 0");
+assertEq(view[663], 255, "663th value should be 255");
+assertEq(view[664], 0, "664th value should be 0");
+assertEq(view[665], 0, "665th value should be 0");
+assertEq(view[666], 0, "666th value should be 0");
+assertEq(view[667], 255, "667th value should be 255");
+assertEq(view[668], 0, "668th value should be 0");
+assertEq(view[669], 0, "669th value should be 0");
+assertEq(view[670], 0, "670th value should be 0");
+assertEq(view[671], 255, "671th value should be 255");
+assertEq(view[672], 0, "672th value should be 0");
+assertEq(view[673], 0, "673th value should be 0");
+assertEq(view[674], 0, "674th value should be 0");
+assertEq(view[675], 255, "675th value should be 255");
+assertEq(view[676], 0, "676th value should be 0");
+assertEq(view[677], 0, "677th value should be 0");
+assertEq(view[678], 0, "678th value should be 0");
+assertEq(view[679], 255, "679th value should be 255");
+assertEq(view[680], 0, "680th value should be 0");
+assertEq(view[681], 0, "681th value should be 0");
+assertEq(view[682], 0, "682th value should be 0");
+assertEq(view[683], 255, "683th value should be 255");
+assertEq(view[684], 0, "684th value should be 0");
+assertEq(view[685], 0, "685th value should be 0");
+assertEq(view[686], 0, "686th value should be 0");
+assertEq(view[687], 255, "687th value should be 255");
+assertEq(view[688], 0, "688th value should be 0");
+assertEq(view[689], 0, "689th value should be 0");
+assertEq(view[690], 0, "690th value should be 0");
+assertEq(view[691], 255, "691th value should be 255");
+assertEq(view[692], 0, "692th value should be 0");
+assertEq(view[693], 0, "693th value should be 0");
+assertEq(view[694], 0, "694th value should be 0");
+assertEq(view[695], 255, "695th value should be 255");
+assertEq(view[696], 0, "696th value should be 0");
+assertEq(view[697], 0, "697th value should be 0");
+assertEq(view[698], 0, "698th value should be 0");
+assertEq(view[699], 255, "699th value should be 255");
+assertEq(view[700], 0, "700th value should be 0");
+assertEq(view[701], 0, "701th value should be 0");
+assertEq(view[702], 0, "702th value should be 0");
+assertEq(view[703], 255, "703th value should be 255");
+assertEq(view[704], 0, "704th value should be 0");
+assertEq(view[705], 0, "705th value should be 0");
+assertEq(view[706], 0, "706th value should be 0");
+assertEq(view[707], 255, "707th value should be 255");
+assertEq(view[708], 154, "708th value should be 154");
+assertEq(view[709], 255, "709th value should be 255");
+assertEq(view[710], 101, "710th value should be 101");
+assertEq(view[711], 255, "711th value should be 255");
+assertEq(view[712], 179, "712th value should be 179");
+assertEq(view[713], 127, "713th value should be 127");
+assertEq(view[714], 76, "714th value should be 76");
+assertEq(view[715], 255, "715th value should be 255");
+assertEq(view[716], 205, "716th value should be 205");
+assertEq(view[717], 255, "717th value should be 255");
+assertEq(view[718], 50, "718th value should be 50");
+assertEq(view[719], 255, "719th value should be 255");
+assertEq(view[720], 154, "720th value should be 154");
+assertEq(view[721], 255, "721th value should be 255");
+assertEq(view[722], 101, "722th value should be 101");
+assertEq(view[723], 255, "723th value should be 255");
+assertEq(view[724], 52, "724th value should be 52");
+assertEq(view[725], 255, "725th value should be 255");
+assertEq(view[726], 203, "726th value should be 203");
+assertEq(view[727], 255, "727th value should be 255");
+assertEq(view[728], 128, "728th value should be 128");
+assertEq(view[729], 127, "729th value should be 127");
+assertEq(view[730], 127, "730th value should be 127");
+assertEq(view[731], 255, "731th value should be 255");
+assertEq(view[732], 78, "732th value should be 78");
+assertEq(view[733], 127, "733th value should be 127");
+assertEq(view[734], 178, "734th value should be 178");
+assertEq(view[735], 255, "735th value should be 255");
+assertEq(view[736], 0, "736th value should be 0");
+assertEq(view[737], 0, "737th value should be 0");
+assertEq(view[738], 0, "738th value should be 0");
+assertEq(view[739], 255, "739th value should be 255");
+assertEq(view[740], 0, "740th value should be 0");
+assertEq(view[741], 0, "741th value should be 0");
+assertEq(view[742], 0, "742th value should be 0");
+assertEq(view[743], 255, "743th value should be 255");
+assertEq(view[744], 0, "744th value should be 0");
+assertEq(view[745], 0, "745th value should be 0");
+assertEq(view[746], 0, "746th value should be 0");
+assertEq(view[747], 255, "747th value should be 255");
+assertEq(view[748], 0, "748th value should be 0");
+assertEq(view[749], 0, "749th value should be 0");
+assertEq(view[750], 0, "750th value should be 0");
+assertEq(view[751], 255, "751th value should be 255");
+assertEq(view[752], 0, "752th value should be 0");
+assertEq(view[753], 0, "753th value should be 0");
+assertEq(view[754], 0, "754th value should be 0");
+assertEq(view[755], 255, "755th value should be 255");
+assertEq(view[756], 0, "756th value should be 0");
+assertEq(view[757], 0, "757th value should be 0");
+assertEq(view[758], 0, "758th value should be 0");
+assertEq(view[759], 255, "759th value should be 255");
+assertEq(view[760], 0, "760th value should be 0");
+assertEq(view[761], 0, "761th value should be 0");
+assertEq(view[762], 0, "762th value should be 0");
+assertEq(view[763], 255, "763th value should be 255");
+assertEq(view[764], 0, "764th value should be 0");
+assertEq(view[765], 0, "765th value should be 0");
+assertEq(view[766], 0, "766th value should be 0");
+assertEq(view[767], 255, "767th value should be 255");
+assertEq(view[768], 0, "768th value should be 0");
+assertEq(view[769], 0, "769th value should be 0");
+assertEq(view[770], 0, "770th value should be 0");
+assertEq(view[771], 255, "771th value should be 255");
+assertEq(view[772], 0, "772th value should be 0");
+assertEq(view[773], 0, "773th value should be 0");
+assertEq(view[774], 0, "774th value should be 0");
+assertEq(view[775], 255, "775th value should be 255");
+assertEq(view[776], 0, "776th value should be 0");
+assertEq(view[777], 0, "777th value should be 0");
+assertEq(view[778], 0, "778th value should be 0");
+assertEq(view[779], 255, "779th value should be 255");
+assertEq(view[780], 0, "780th value should be 0");
+assertEq(view[781], 0, "781th value should be 0");
+assertEq(view[782], 0, "782th value should be 0");
+assertEq(view[783], 255, "783th value should be 255");
+assertEq(view[784], 78, "784th value should be 78");
+assertEq(view[785], 127, "785th value should be 127");
+assertEq(view[786], 178, "786th value should be 178");
+assertEq(view[787], 255, "787th value should be 255");
+assertEq(view[788], 154, "788th value should be 154");
+assertEq(view[789], 255, "789th value should be 255");
+assertEq(view[790], 101, "790th value should be 101");
+assertEq(view[791], 255, "791th value should be 255");
+assertEq(view[792], 179, "792th value should be 179");
+assertEq(view[793], 127, "793th value should be 127");
+assertEq(view[794], 76, "794th value should be 76");
+assertEq(view[795], 255, "795th value should be 255");
+assertEq(view[796], 205, "796th value should be 205");
+assertEq(view[797], 255, "797th value should be 255");
+assertEq(view[798], 50, "798th value should be 50");
+assertEq(view[799], 255, "799th value should be 255");
+assertEq(view[800], 128, "800th value should be 128");
+assertEq(view[801], 127, "801th value should be 127");
+assertEq(view[802], 127, "802th value should be 127");
+assertEq(view[803], 255, "803th value should be 255");
+assertEq(view[804], 0, "804th value should be 0");
+assertEq(view[805], 0, "805th value should be 0");
+assertEq(view[806], 0, "806th value should be 0");
+assertEq(view[807], 255, "807th value should be 255");
+assertEq(view[808], 26, "808th value should be 26");
+assertEq(view[809], 127, "809th value should be 127");
+assertEq(view[810], 229, "810th value should be 229");
+assertEq(view[811], 255, "811th value should be 255");
+assertEq(view[812], 0, "812th value should be 0");
+assertEq(view[813], 0, "813th value should be 0");
+assertEq(view[814], 0, "814th value should be 0");
+assertEq(view[815], 255, "815th value should be 255");
+assertEq(view[816], 0, "816th value should be 0");
+assertEq(view[817], 0, "817th value should be 0");
+assertEq(view[818], 0, "818th value should be 0");
+assertEq(view[819], 255, "819th value should be 255");
+assertEq(view[820], 0, "820th value should be 0");
+assertEq(view[821], 0, "821th value should be 0");
+assertEq(view[822], 0, "822th value should be 0");
+assertEq(view[823], 255, "823th value should be 255");
+assertEq(view[824], 0, "824th value should be 0");
+assertEq(view[825], 0, "825th value should be 0");
+assertEq(view[826], 0, "826th value should be 0");
+assertEq(view[827], 255, "827th value should be 255");
+assertEq(view[828], 0, "828th value should be 0");
+assertEq(view[829], 0, "829th value should be 0");
+assertEq(view[830], 0, "830th value should be 0");
+assertEq(view[831], 255, "831th value should be 255");
+assertEq(view[832], 0, "832th value should be 0");
+assertEq(view[833], 0, "833th value should be 0");
+assertEq(view[834], 0, "834th value should be 0");
+assertEq(view[835], 255, "835th value should be 255");
+assertEq(view[836], 0, "836th value should be 0");
+assertEq(view[837], 0, "837th value should be 0");
+assertEq(view[838], 0, "838th value should be 0");
+assertEq(view[839], 255, "839th value should be 255");
+assertEq(view[840], 0, "840th value should be 0");
+assertEq(view[841], 0, "841th value should be 0");
+assertEq(view[842], 0, "842th value should be 0");
+assertEq(view[843], 255, "843th value should be 255");
+assertEq(view[844], 0, "844th value should be 0");
+assertEq(view[845], 0, "845th value should be 0");
+assertEq(view[846], 0, "846th value should be 0");
+assertEq(view[847], 255, "847th value should be 255");
+assertEq(view[848], 0, "848th value should be 0");
+assertEq(view[849], 0, "849th value should be 0");
+assertEq(view[850], 0, "850th value should be 0");
+assertEq(view[851], 255, "851th value should be 255");
+assertEq(view[852], 0, "852th value should be 0");
+assertEq(view[853], 0, "853th value should be 0");
+assertEq(view[854], 0, "854th value should be 0");
+assertEq(view[855], 255, "855th value should be 255");
+assertEq(view[856], 0, "856th value should be 0");
+assertEq(view[857], 0, "857th value should be 0");
+assertEq(view[858], 0, "858th value should be 0");
+assertEq(view[859], 255, "859th value should be 255");
+assertEq(view[860], 0, "860th value should be 0");
+assertEq(view[861], 0, "861th value should be 0");
+assertEq(view[862], 0, "862th value should be 0");
+assertEq(view[863], 255, "863th value should be 255");
+assertEq(view[864], 103, "864th value should be 103");
+assertEq(view[865], 255, "865th value should be 255");
+assertEq(view[866], 152, "866th value should be 152");
+assertEq(view[867], 255, "867th value should be 255");
+assertEq(view[868], 154, "868th value should be 154");
+assertEq(view[869], 255, "869th value should be 255");
+assertEq(view[870], 101, "870th value should be 101");
+assertEq(view[871], 255, "871th value should be 255");
+assertEq(view[872], 179, "872th value should be 179");
+assertEq(view[873], 127, "873th value should be 127");
+assertEq(view[874], 76, "874th value should be 76");
+assertEq(view[875], 255, "875th value should be 255");
+assertEq(view[876], 205, "876th value should be 205");
+assertEq(view[877], 255, "877th value should be 255");
+assertEq(view[878], 50, "878th value should be 50");
+assertEq(view[879], 255, "879th value should be 255");
+assertEq(view[880], 179, "880th value should be 179");
+assertEq(view[881], 127, "881th value should be 127");
+assertEq(view[882], 76, "882th value should be 76");
+assertEq(view[883], 255, "883th value should be 255");
+assertEq(view[884], 179, "884th value should be 179");
+assertEq(view[885], 127, "885th value should be 127");
+assertEq(view[886], 76, "886th value should be 76");
+assertEq(view[887], 255, "887th value should be 255");
+assertEq(view[888], 128, "888th value should be 128");
+assertEq(view[889], 127, "889th value should be 127");
+assertEq(view[890], 127, "890th value should be 127");
+assertEq(view[891], 255, "891th value should be 255");
+assertEq(view[892], 103, "892th value should be 103");
+assertEq(view[893], 255, "893th value should be 255");
+assertEq(view[894], 152, "894th value should be 152");
+assertEq(view[895], 255, "895th value should be 255");
+assertEq(view[896], 26, "896th value should be 26");
+assertEq(view[897], 127, "897th value should be 127");
+assertEq(view[898], 229, "898th value should be 229");
+assertEq(view[899], 255, "899th value should be 255");
+assertEq(view[900], 0, "900th value should be 0");
+assertEq(view[901], 0, "901th value should be 0");
+assertEq(view[902], 0, "902th value should be 0");
+assertEq(view[903], 255, "903th value should be 255");
+assertEq(view[904], 0, "904th value should be 0");
+assertEq(view[905], 0, "905th value should be 0");
+assertEq(view[906], 0, "906th value should be 0");
+assertEq(view[907], 255, "907th value should be 255");
+assertEq(view[908], 0, "908th value should be 0");
+assertEq(view[909], 0, "909th value should be 0");
+assertEq(view[910], 0, "910th value should be 0");
+assertEq(view[911], 255, "911th value should be 255");
+assertEq(view[912], 0, "912th value should be 0");
+assertEq(view[913], 0, "913th value should be 0");
+assertEq(view[914], 0, "914th value should be 0");
+assertEq(view[915], 255, "915th value should be 255");
+assertEq(view[916], 0, "916th value should be 0");
+assertEq(view[917], 0, "917th value should be 0");
+assertEq(view[918], 0, "918th value should be 0");
+assertEq(view[919], 255, "919th value should be 255");
+assertEq(view[920], 0, "920th value should be 0");
+assertEq(view[921], 0, "921th value should be 0");
+assertEq(view[922], 0, "922th value should be 0");
+assertEq(view[923], 255, "923th value should be 255");
+assertEq(view[924], 0, "924th value should be 0");
+assertEq(view[925], 0, "925th value should be 0");
+assertEq(view[926], 0, "926th value should be 0");
+assertEq(view[927], 255, "927th value should be 255");
+assertEq(view[928], 0, "928th value should be 0");
+assertEq(view[929], 0, "929th value should be 0");
+assertEq(view[930], 0, "930th value should be 0");
+assertEq(view[931], 255, "931th value should be 255");
+assertEq(view[932], 0, "932th value should be 0");
+assertEq(view[933], 0, "933th value should be 0");
+assertEq(view[934], 0, "934th value should be 0");
+assertEq(view[935], 255, "935th value should be 255");
+assertEq(view[936], 0, "936th value should be 0");
+assertEq(view[937], 0, "937th value should be 0");
+assertEq(view[938], 0, "938th value should be 0");
+assertEq(view[939], 255, "939th value should be 255");
+assertEq(view[940], 0, "940th value should be 0");
+assertEq(view[941], 0, "941th value should be 0");
+assertEq(view[942], 0, "942th value should be 0");
+assertEq(view[943], 255, "943th value should be 255");
+assertEq(view[944], 0, "944th value should be 0");
+assertEq(view[945], 0, "945th value should be 0");
+assertEq(view[946], 0, "946th value should be 0");
+assertEq(view[947], 255, "947th value should be 255");
+assertEq(view[948], 154, "948th value should be 154");
+assertEq(view[949], 255, "949th value should be 255");
+assertEq(view[950], 101, "950th value should be 101");
+assertEq(view[951], 255, "951th value should be 255");
+assertEq(view[952], 179, "952th value should be 179");
+assertEq(view[953], 127, "953th value should be 127");
+assertEq(view[954], 76, "954th value should be 76");
+assertEq(view[955], 255, "955th value should be 255");
+assertEq(view[956], 205, "956th value should be 205");
+assertEq(view[957], 255, "957th value should be 255");
+assertEq(view[958], 50, "958th value should be 50");
+assertEq(view[959], 255, "959th value should be 255");
+assertEq(view[960], 179, "960th value should be 179");
+assertEq(view[961], 127, "961th value should be 127");
+assertEq(view[962], 76, "962th value should be 76");
+assertEq(view[963], 255, "963th value should be 255");
+assertEq(view[964], 179, "964th value should be 179");
+assertEq(view[965], 127, "965th value should be 127");
+assertEq(view[966], 76, "966th value should be 76");
+assertEq(view[967], 255, "967th value should be 255");
+assertEq(view[968], 179, "968th value should be 179");
+assertEq(view[969], 127, "969th value should be 127");
+assertEq(view[970], 76, "970th value should be 76");
+assertEq(view[971], 255, "971th value should be 255");
+assertEq(view[972], 154, "972th value should be 154");
+assertEq(view[973], 255, "973th value should be 255");
+assertEq(view[974], 101, "974th value should be 101");
+assertEq(view[975], 255, "975th value should be 255");
+assertEq(view[976], 103, "976th value should be 103");
+assertEq(view[977], 255, "977th value should be 255");
+assertEq(view[978], 152, "978th value should be 152");
+assertEq(view[979], 255, "979th value should be 255");
+assertEq(view[980], 0, "980th value should be 0");
+assertEq(view[981], 0, "981th value should be 0");
+assertEq(view[982], 0, "982th value should be 0");
+assertEq(view[983], 255, "983th value should be 255");
+assertEq(view[984], 0, "984th value should be 0");
+assertEq(view[985], 0, "985th value should be 0");
+assertEq(view[986], 0, "986th value should be 0");
+assertEq(view[987], 255, "987th value should be 255");
+assertEq(view[988], 0, "988th value should be 0");
+assertEq(view[989], 0, "989th value should be 0");
+assertEq(view[990], 0, "990th value should be 0");
+assertEq(view[991], 255, "991th value should be 255");
+assertEq(view[992], 0, "992th value should be 0");
+assertEq(view[993], 0, "993th value should be 0");
+assertEq(view[994], 0, "994th value should be 0");
+assertEq(view[995], 255, "995th value should be 255");
+assertEq(view[996], 0, "996th value should be 0");
+assertEq(view[997], 0, "997th value should be 0");
+assertEq(view[998], 0, "998th value should be 0");
+assertEq(view[999], 255, "999th value should be 255");
+assertEq(view[1000], 0, "1000th value should be 0");
+assertEq(view[1001], 0, "1001th value should be 0");
+assertEq(view[1002], 0, "1002th value should be 0");
+assertEq(view[1003], 255, "1003th value should be 255");
+assertEq(view[1004], 0, "1004th value should be 0");
+assertEq(view[1005], 0, "1005th value should be 0");
+assertEq(view[1006], 0, "1006th value should be 0");
+assertEq(view[1007], 255, "1007th value should be 255");
+assertEq(view[1008], 0, "1008th value should be 0");
+assertEq(view[1009], 0, "1009th value should be 0");
+assertEq(view[1010], 0, "1010th value should be 0");
+assertEq(view[1011], 255, "1011th value should be 255");
+assertEq(view[1012], 0, "1012th value should be 0");
+assertEq(view[1013], 0, "1013th value should be 0");
+assertEq(view[1014], 0, "1014th value should be 0");
+assertEq(view[1015], 255, "1015th value should be 255");
+assertEq(view[1016], 0, "1016th value should be 0");
+assertEq(view[1017], 0, "1017th value should be 0");
+assertEq(view[1018], 0, "1018th value should be 0");
+assertEq(view[1019], 255, "1019th value should be 255");
+assertEq(view[1020], 0, "1020th value should be 0");
+assertEq(view[1021], 0, "1021th value should be 0");
+assertEq(view[1022], 0, "1022th value should be 0");
+assertEq(view[1023], 255, "1023th value should be 255");
+assertEq(view[1024], 0, "1024th value should be 0");
+assertEq(view[1025], 0, "1025th value should be 0");
+assertEq(view[1026], 0, "1026th value should be 0");
+assertEq(view[1027], 255, "1027th value should be 255");
+assertEq(view[1028], 154, "1028th value should be 154");
+assertEq(view[1029], 255, "1029th value should be 255");
+assertEq(view[1030], 101, "1030th value should be 101");
+assertEq(view[1031], 255, "1031th value should be 255");
+assertEq(view[1032], 205, "1032th value should be 205");
+assertEq(view[1033], 255, "1033th value should be 255");
+assertEq(view[1034], 50, "1034th value should be 50");
+assertEq(view[1035], 255, "1035th value should be 255");
+assertEq(view[1036], 205, "1036th value should be 205");
+assertEq(view[1037], 255, "1037th value should be 255");
+assertEq(view[1038], 50, "1038th value should be 50");
+assertEq(view[1039], 255, "1039th value should be 255");
+assertEq(view[1040], 205, "1040th value should be 205");
+assertEq(view[1041], 255, "1041th value should be 255");
+assertEq(view[1042], 50, "1042th value should be 50");
+assertEq(view[1043], 255, "1043th value should be 255");
+assertEq(view[1044], 179, "1044th value should be 179");
+assertEq(view[1045], 127, "1045th value should be 127");
+assertEq(view[1046], 76, "1046th value should be 76");
+assertEq(view[1047], 255, "1047th value should be 255");
+assertEq(view[1048], 179, "1048th value should be 179");
+assertEq(view[1049], 127, "1049th value should be 127");
+assertEq(view[1050], 76, "1050th value should be 76");
+assertEq(view[1051], 255, "1051th value should be 255");
+assertEq(view[1052], 154, "1052th value should be 154");
+assertEq(view[1053], 255, "1053th value should be 255");
+assertEq(view[1054], 101, "1054th value should be 101");
+assertEq(view[1055], 255, "1055th value should be 255");
+assertEq(view[1056], 128, "1056th value should be 128");
+assertEq(view[1057], 127, "1057th value should be 127");
+assertEq(view[1058], 127, "1058th value should be 127");
+assertEq(view[1059], 255, "1059th value should be 255");
+assertEq(view[1060], 0, "1060th value should be 0");
+assertEq(view[1061], 0, "1061th value should be 0");
+assertEq(view[1062], 0, "1062th value should be 0");
+assertEq(view[1063], 255, "1063th value should be 255");
+assertEq(view[1064], 0, "1064th value should be 0");
+assertEq(view[1065], 0, "1065th value should be 0");
+assertEq(view[1066], 0, "1066th value should be 0");
+assertEq(view[1067], 255, "1067th value should be 255");
+assertEq(view[1068], 26, "1068th value should be 26");
+assertEq(view[1069], 127, "1069th value should be 127");
+assertEq(view[1070], 229, "1070th value should be 229");
+assertEq(view[1071], 255, "1071th value should be 255");
+assertEq(view[1072], 26, "1072th value should be 26");
+assertEq(view[1073], 127, "1073th value should be 127");
+assertEq(view[1074], 229, "1074th value should be 229");
+assertEq(view[1075], 255, "1075th value should be 255");
+assertEq(view[1076], 0, "1076th value should be 0");
+assertEq(view[1077], 0, "1077th value should be 0");
+assertEq(view[1078], 0, "1078th value should be 0");
+assertEq(view[1079], 255, "1079th value should be 255");
+assertEq(view[1080], 0, "1080th value should be 0");
+assertEq(view[1081], 0, "1081th value should be 0");
+assertEq(view[1082], 0, "1082th value should be 0");
+assertEq(view[1083], 255, "1083th value should be 255");
+assertEq(view[1084], 0, "1084th value should be 0");
+assertEq(view[1085], 0, "1085th value should be 0");
+assertEq(view[1086], 0, "1086th value should be 0");
+assertEq(view[1087], 255, "1087th value should be 255");
+assertEq(view[1088], 0, "1088th value should be 0");
+assertEq(view[1089], 0, "1089th value should be 0");
+assertEq(view[1090], 0, "1090th value should be 0");
+assertEq(view[1091], 255, "1091th value should be 255");
+assertEq(view[1092], 0, "1092th value should be 0");
+assertEq(view[1093], 0, "1093th value should be 0");
+assertEq(view[1094], 0, "1094th value should be 0");
+assertEq(view[1095], 255, "1095th value should be 255");
+assertEq(view[1096], 0, "1096th value should be 0");
+assertEq(view[1097], 0, "1097th value should be 0");
+assertEq(view[1098], 0, "1098th value should be 0");
+assertEq(view[1099], 255, "1099th value should be 255");
+assertEq(view[1100], 0, "1100th value should be 0");
+assertEq(view[1101], 0, "1101th value should be 0");
+assertEq(view[1102], 0, "1102th value should be 0");
+assertEq(view[1103], 255, "1103th value should be 255");
+assertEq(view[1104], 0, "1104th value should be 0");
+assertEq(view[1105], 0, "1105th value should be 0");
+assertEq(view[1106], 0, "1106th value should be 0");
+assertEq(view[1107], 255, "1107th value should be 255");
+assertEq(view[1108], 154, "1108th value should be 154");
+assertEq(view[1109], 255, "1109th value should be 255");
+assertEq(view[1110], 101, "1110th value should be 101");
+assertEq(view[1111], 255, "1111th value should be 255");
+assertEq(view[1112], 205, "1112th value should be 205");
+assertEq(view[1113], 255, "1113th value should be 255");
+assertEq(view[1114], 50, "1114th value should be 50");
+assertEq(view[1115], 255, "1115th value should be 255");
+assertEq(view[1116], 205, "1116th value should be 205");
+assertEq(view[1117], 255, "1117th value should be 255");
+assertEq(view[1118], 50, "1118th value should be 50");
+assertEq(view[1119], 255, "1119th value should be 255");
+assertEq(view[1120], 205, "1120th value should be 205");
+assertEq(view[1121], 255, "1121th value should be 255");
+assertEq(view[1122], 50, "1122th value should be 50");
+assertEq(view[1123], 255, "1123th value should be 255");
+assertEq(view[1124], 205, "1124th value should be 205");
+assertEq(view[1125], 255, "1125th value should be 255");
+assertEq(view[1126], 50, "1126th value should be 50");
+assertEq(view[1127], 255, "1127th value should be 255");
+assertEq(view[1128], 205, "1128th value should be 205");
+assertEq(view[1129], 255, "1129th value should be 255");
+assertEq(view[1130], 50, "1130th value should be 50");
+assertEq(view[1131], 255, "1131th value should be 255");
+assertEq(view[1132], 179, "1132th value should be 179");
+assertEq(view[1133], 127, "1133th value should be 127");
+assertEq(view[1134], 76, "1134th value should be 76");
+assertEq(view[1135], 255, "1135th value should be 255");
+assertEq(view[1136], 154, "1136th value should be 154");
+assertEq(view[1137], 255, "1137th value should be 255");
+assertEq(view[1138], 101, "1138th value should be 101");
+assertEq(view[1139], 255, "1139th value should be 255");
+assertEq(view[1140], 128, "1140th value should be 128");
+assertEq(view[1141], 127, "1141th value should be 127");
+assertEq(view[1142], 127, "1142th value should be 127");
+assertEq(view[1143], 255, "1143th value should be 255");
+assertEq(view[1144], 128, "1144th value should be 128");
+assertEq(view[1145], 127, "1145th value should be 127");
+assertEq(view[1146], 127, "1146th value should be 127");
+assertEq(view[1147], 255, "1147th value should be 255");
+assertEq(view[1148], 103, "1148th value should be 103");
+assertEq(view[1149], 255, "1149th value should be 255");
+assertEq(view[1150], 152, "1150th value should be 152");
+assertEq(view[1151], 255, "1151th value should be 255");
+assertEq(view[1152], 78, "1152th value should be 78");
+assertEq(view[1153], 127, "1153th value should be 127");
+assertEq(view[1154], 178, "1154th value should be 178");
+assertEq(view[1155], 255, "1155th value should be 255");
+assertEq(view[1156], 0, "1156th value should be 0");
+assertEq(view[1157], 0, "1157th value should be 0");
+assertEq(view[1158], 0, "1158th value should be 0");
+assertEq(view[1159], 255, "1159th value should be 255");
+assertEq(view[1160], 0, "1160th value should be 0");
+assertEq(view[1161], 0, "1161th value should be 0");
+assertEq(view[1162], 0, "1162th value should be 0");
+assertEq(view[1163], 255, "1163th value should be 255");
+assertEq(view[1164], 0, "1164th value should be 0");
+assertEq(view[1165], 0, "1165th value should be 0");
+assertEq(view[1166], 0, "1166th value should be 0");
+assertEq(view[1167], 255, "1167th value should be 255");
+assertEq(view[1168], 0, "1168th value should be 0");
+assertEq(view[1169], 0, "1169th value should be 0");
+assertEq(view[1170], 0, "1170th value should be 0");
+assertEq(view[1171], 255, "1171th value should be 255");
+assertEq(view[1172], 0, "1172th value should be 0");
+assertEq(view[1173], 0, "1173th value should be 0");
+assertEq(view[1174], 0, "1174th value should be 0");
+assertEq(view[1175], 255, "1175th value should be 255");
+assertEq(view[1176], 0, "1176th value should be 0");
+assertEq(view[1177], 0, "1177th value should be 0");
+assertEq(view[1178], 0, "1178th value should be 0");
+assertEq(view[1179], 255, "1179th value should be 255");
+assertEq(view[1180], 0, "1180th value should be 0");
+assertEq(view[1181], 0, "1181th value should be 0");
+assertEq(view[1182], 0, "1182th value should be 0");
+assertEq(view[1183], 255, "1183th value should be 255");
+assertEq(view[1184], 26, "1184th value should be 26");
+assertEq(view[1185], 127, "1185th value should be 127");
+assertEq(view[1186], 229, "1186th value should be 229");
+assertEq(view[1187], 255, "1187th value should be 255");
+assertEq(view[1188], 154, "1188th value should be 154");
+assertEq(view[1189], 255, "1189th value should be 255");
+assertEq(view[1190], 101, "1190th value should be 101");
+assertEq(view[1191], 255, "1191th value should be 255");
+assertEq(view[1192], 205, "1192th value should be 205");
+assertEq(view[1193], 255, "1193th value should be 255");
+assertEq(view[1194], 50, "1194th value should be 50");
+assertEq(view[1195], 255, "1195th value should be 255");
+assertEq(view[1196], 205, "1196th value should be 205");
+assertEq(view[1197], 255, "1197th value should be 255");
+assertEq(view[1198], 50, "1198th value should be 50");
+assertEq(view[1199], 255, "1199th value should be 255");
+assertEq(view[1200], 230, "1200th value should be 230");
+assertEq(view[1201], 127, "1201th value should be 127");
+assertEq(view[1202], 25, "1202th value should be 25");
+assertEq(view[1203], 255, "1203th value should be 255");
+assertEq(view[1204], 205, "1204th value should be 205");
+assertEq(view[1205], 255, "1205th value should be 255");
+assertEq(view[1206], 50, "1206th value should be 50");
+assertEq(view[1207], 255, "1207th value should be 255");
+assertEq(view[1208], 205, "1208th value should be 205");
+assertEq(view[1209], 255, "1209th value should be 255");
+assertEq(view[1210], 50, "1210th value should be 50");
+assertEq(view[1211], 255, "1211th value should be 255");
+assertEq(view[1212], 205, "1212th value should be 205");
+assertEq(view[1213], 255, "1213th value should be 255");
+assertEq(view[1214], 50, "1214th value should be 50");
+assertEq(view[1215], 255, "1215th value should be 255");
+assertEq(view[1216], 205, "1216th value should be 205");
+assertEq(view[1217], 255, "1217th value should be 255");
+assertEq(view[1218], 50, "1218th value should be 50");
+assertEq(view[1219], 255, "1219th value should be 255");
+assertEq(view[1220], 154, "1220th value should be 154");
+assertEq(view[1221], 255, "1221th value should be 255");
+assertEq(view[1222], 101, "1222th value should be 101");
+assertEq(view[1223], 255, "1223th value should be 255");
+assertEq(view[1224], 154, "1224th value should be 154");
+assertEq(view[1225], 255, "1225th value should be 255");
+assertEq(view[1226], 101, "1226th value should be 101");
+assertEq(view[1227], 255, "1227th value should be 255");
+assertEq(view[1228], 154, "1228th value should be 154");
+assertEq(view[1229], 255, "1229th value should be 255");
+assertEq(view[1230], 101, "1230th value should be 101");
+assertEq(view[1231], 255, "1231th value should be 255");
+assertEq(view[1232], 128, "1232th value should be 128");
+assertEq(view[1233], 127, "1233th value should be 127");
+assertEq(view[1234], 127, "1234th value should be 127");
+assertEq(view[1235], 255, "1235th value should be 255");
+assertEq(view[1236], 26, "1236th value should be 26");
+assertEq(view[1237], 127, "1237th value should be 127");
+assertEq(view[1238], 229, "1238th value should be 229");
+assertEq(view[1239], 255, "1239th value should be 255");
+assertEq(view[1240], 0, "1240th value should be 0");
+assertEq(view[1241], 0, "1241th value should be 0");
+assertEq(view[1242], 0, "1242th value should be 0");
+assertEq(view[1243], 255, "1243th value should be 255");
+assertEq(view[1244], 0, "1244th value should be 0");
+assertEq(view[1245], 0, "1245th value should be 0");
+assertEq(view[1246], 0, "1246th value should be 0");
+assertEq(view[1247], 255, "1247th value should be 255");
+assertEq(view[1248], 0, "1248th value should be 0");
+assertEq(view[1249], 0, "1249th value should be 0");
+assertEq(view[1250], 0, "1250th value should be 0");
+assertEq(view[1251], 255, "1251th value should be 255");
+assertEq(view[1252], 0, "1252th value should be 0");
+assertEq(view[1253], 0, "1253th value should be 0");
+assertEq(view[1254], 0, "1254th value should be 0");
+assertEq(view[1255], 255, "1255th value should be 255");
+assertEq(view[1256], 0, "1256th value should be 0");
+assertEq(view[1257], 0, "1257th value should be 0");
+assertEq(view[1258], 0, "1258th value should be 0");
+assertEq(view[1259], 255, "1259th value should be 255");
+assertEq(view[1260], 0, "1260th value should be 0");
+assertEq(view[1261], 0, "1261th value should be 0");
+assertEq(view[1262], 0, "1262th value should be 0");
+assertEq(view[1263], 255, "1263th value should be 255");
+assertEq(view[1264], 78, "1264th value should be 78");
+assertEq(view[1265], 127, "1265th value should be 127");
+assertEq(view[1266], 178, "1266th value should be 178");
+assertEq(view[1267], 255, "1267th value should be 255");
+assertEq(view[1268], 179, "1268th value should be 179");
+assertEq(view[1269], 127, "1269th value should be 127");
+assertEq(view[1270], 76, "1270th value should be 76");
+assertEq(view[1271], 255, "1271th value should be 255");
+assertEq(view[1272], 205, "1272th value should be 205");
+assertEq(view[1273], 255, "1273th value should be 255");
+assertEq(view[1274], 50, "1274th value should be 50");
+assertEq(view[1275], 255, "1275th value should be 255");
+assertEq(view[1276], 205, "1276th value should be 205");
+assertEq(view[1277], 255, "1277th value should be 255");
+assertEq(view[1278], 50, "1278th value should be 50");
+assertEq(view[1279], 255, "1279th value should be 255");
+assertEq(view[1280], 0, "1280th value should be 0");
+assertEq(view[1281], 0, "1281th value should be 0");
+assertEq(view[1282], 0, "1282th value should be 0");
+assertEq(view[1283], 255, "1283th value should be 255");
+assertEq(view[1284], 205, "1284th value should be 205");
+assertEq(view[1285], 255, "1285th value should be 255");
+assertEq(view[1286], 50, "1286th value should be 50");
+assertEq(view[1287], 255, "1287th value should be 255");
+assertEq(view[1288], 205, "1288th value should be 205");
+assertEq(view[1289], 255, "1289th value should be 255");
+assertEq(view[1290], 50, "1290th value should be 50");
+assertEq(view[1291], 255, "1291th value should be 255");
+assertEq(view[1292], 205, "1292th value should be 205");
+assertEq(view[1293], 255, "1293th value should be 255");
+assertEq(view[1294], 50, "1294th value should be 50");
+assertEq(view[1295], 255, "1295th value should be 255");
+assertEq(view[1296], 205, "1296th value should be 205");
+assertEq(view[1297], 255, "1297th value should be 255");
+assertEq(view[1298], 50, "1298th value should be 50");
+assertEq(view[1299], 255, "1299th value should be 255");
+assertEq(view[1300], 205, "1300th value should be 205");
+assertEq(view[1301], 255, "1301th value should be 255");
+assertEq(view[1302], 50, "1302th value should be 50");
+assertEq(view[1303], 255, "1303th value should be 255");
+assertEq(view[1304], 179, "1304th value should be 179");
+assertEq(view[1305], 127, "1305th value should be 127");
+assertEq(view[1306], 76, "1306th value should be 76");
+assertEq(view[1307], 255, "1307th value should be 255");
+assertEq(view[1308], 154, "1308th value should be 154");
+assertEq(view[1309], 255, "1309th value should be 255");
+assertEq(view[1310], 101, "1310th value should be 101");
+assertEq(view[1311], 255, "1311th value should be 255");
+assertEq(view[1312], 154, "1312th value should be 154");
+assertEq(view[1313], 255, "1313th value should be 255");
+assertEq(view[1314], 101, "1314th value should be 101");
+assertEq(view[1315], 255, "1315th value should be 255");
+assertEq(view[1316], 0, "1316th value should be 0");
+assertEq(view[1317], 0, "1317th value should be 0");
+assertEq(view[1318], 0, "1318th value should be 0");
+assertEq(view[1319], 255, "1319th value should be 255");
+assertEq(view[1320], 0, "1320th value should be 0");
+assertEq(view[1321], 0, "1321th value should be 0");
+assertEq(view[1322], 0, "1322th value should be 0");
+assertEq(view[1323], 255, "1323th value should be 255");
+assertEq(view[1324], 0, "1324th value should be 0");
+assertEq(view[1325], 0, "1325th value should be 0");
+assertEq(view[1326], 0, "1326th value should be 0");
+assertEq(view[1327], 255, "1327th value should be 255");
+assertEq(view[1328], 0, "1328th value should be 0");
+assertEq(view[1329], 0, "1329th value should be 0");
+assertEq(view[1330], 0, "1330th value should be 0");
+assertEq(view[1331], 255, "1331th value should be 255");
+assertEq(view[1332], 0, "1332th value should be 0");
+assertEq(view[1333], 0, "1333th value should be 0");
+assertEq(view[1334], 0, "1334th value should be 0");
+assertEq(view[1335], 255, "1335th value should be 255");
+assertEq(view[1336], 0, "1336th value should be 0");
+assertEq(view[1337], 0, "1337th value should be 0");
+assertEq(view[1338], 0, "1338th value should be 0");
+assertEq(view[1339], 255, "1339th value should be 255");
+assertEq(view[1340], 0, "1340th value should be 0");
+assertEq(view[1341], 0, "1341th value should be 0");
+assertEq(view[1342], 0, "1342th value should be 0");
+assertEq(view[1343], 255, "1343th value should be 255");
+assertEq(view[1344], 0, "1344th value should be 0");
+assertEq(view[1345], 0, "1345th value should be 0");
+assertEq(view[1346], 0, "1346th value should be 0");
+assertEq(view[1347], 255, "1347th value should be 255");
+assertEq(view[1348], 179, "1348th value should be 179");
+assertEq(view[1349], 127, "1349th value should be 127");
+assertEq(view[1350], 76, "1350th value should be 76");
+assertEq(view[1351], 255, "1351th value should be 255");
+assertEq(view[1352], 205, "1352th value should be 205");
+assertEq(view[1353], 255, "1353th value should be 255");
+assertEq(view[1354], 50, "1354th value should be 50");
+assertEq(view[1355], 255, "1355th value should be 255");
+assertEq(view[1356], 205, "1356th value should be 205");
+assertEq(view[1357], 255, "1357th value should be 255");
+assertEq(view[1358], 50, "1358th value should be 50");
+assertEq(view[1359], 255, "1359th value should be 255");
+assertEq(view[1360], 0, "1360th value should be 0");
+assertEq(view[1361], 0, "1361th value should be 0");
+assertEq(view[1362], 0, "1362th value should be 0");
+assertEq(view[1363], 255, "1363th value should be 255");
+assertEq(view[1364], 205, "1364th value should be 205");
+assertEq(view[1365], 255, "1365th value should be 255");
+assertEq(view[1366], 50, "1366th value should be 50");
+assertEq(view[1367], 255, "1367th value should be 255");
+assertEq(view[1368], 205, "1368th value should be 205");
+assertEq(view[1369], 255, "1369th value should be 255");
+assertEq(view[1370], 50, "1370th value should be 50");
+assertEq(view[1371], 255, "1371th value should be 255");
+assertEq(view[1372], 205, "1372th value should be 205");
+assertEq(view[1373], 255, "1373th value should be 255");
+assertEq(view[1374], 50, "1374th value should be 50");
+assertEq(view[1375], 255, "1375th value should be 255");
+assertEq(view[1376], 205, "1376th value should be 205");
+assertEq(view[1377], 255, "1377th value should be 255");
+assertEq(view[1378], 50, "1378th value should be 50");
+assertEq(view[1379], 255, "1379th value should be 255");
+assertEq(view[1380], 205, "1380th value should be 205");
+assertEq(view[1381], 255, "1381th value should be 255");
+assertEq(view[1382], 50, "1382th value should be 50");
+assertEq(view[1383], 255, "1383th value should be 255");
+assertEq(view[1384], 205, "1384th value should be 205");
+assertEq(view[1385], 255, "1385th value should be 255");
+assertEq(view[1386], 50, "1386th value should be 50");
+assertEq(view[1387], 255, "1387th value should be 255");
+assertEq(view[1388], 179, "1388th value should be 179");
+assertEq(view[1389], 127, "1389th value should be 127");
+assertEq(view[1390], 76, "1390th value should be 76");
+assertEq(view[1391], 255, "1391th value should be 255");
+assertEq(view[1392], 179, "1392th value should be 179");
+assertEq(view[1393], 127, "1393th value should be 127");
+assertEq(view[1394], 76, "1394th value should be 76");
+assertEq(view[1395], 255, "1395th value should be 255");
+assertEq(view[1396], 103, "1396th value should be 103");
+assertEq(view[1397], 255, "1397th value should be 255");
+assertEq(view[1398], 152, "1398th value should be 152");
+assertEq(view[1399], 255, "1399th value should be 255");
+assertEq(view[1400], 78, "1400th value should be 78");
+assertEq(view[1401], 127, "1401th value should be 127");
+assertEq(view[1402], 178, "1402th value should be 178");
+assertEq(view[1403], 255, "1403th value should be 255");
+assertEq(view[1404], 52, "1404th value should be 52");
+assertEq(view[1405], 255, "1405th value should be 255");
+assertEq(view[1406], 203, "1406th value should be 203");
+assertEq(view[1407], 255, "1407th value should be 255");
+assertEq(view[1408], 0, "1408th value should be 0");
+assertEq(view[1409], 0, "1409th value should be 0");
+assertEq(view[1410], 0, "1410th value should be 0");
+assertEq(view[1411], 255, "1411th value should be 255");
+assertEq(view[1412], 0, "1412th value should be 0");
+assertEq(view[1413], 0, "1413th value should be 0");
+assertEq(view[1414], 0, "1414th value should be 0");
+assertEq(view[1415], 255, "1415th value should be 255");
+assertEq(view[1416], 52, "1416th value should be 52");
+assertEq(view[1417], 255, "1417th value should be 255");
+assertEq(view[1418], 203, "1418th value should be 203");
+assertEq(view[1419], 255, "1419th value should be 255");
+assertEq(view[1420], 128, "1420th value should be 128");
+assertEq(view[1421], 127, "1421th value should be 127");
+assertEq(view[1422], 127, "1422th value should be 127");
+assertEq(view[1423], 255, "1423th value should be 255");
+assertEq(view[1424], 128, "1424th value should be 128");
+assertEq(view[1425], 127, "1425th value should be 127");
+assertEq(view[1426], 127, "1426th value should be 127");
+assertEq(view[1427], 255, "1427th value should be 255");
+assertEq(view[1428], 205, "1428th value should be 205");
+assertEq(view[1429], 255, "1429th value should be 255");
+assertEq(view[1430], 50, "1430th value should be 50");
+assertEq(view[1431], 255, "1431th value should be 255");
+assertEq(view[1432], 205, "1432th value should be 205");
+assertEq(view[1433], 255, "1433th value should be 255");
+assertEq(view[1434], 50, "1434th value should be 50");
+assertEq(view[1435], 255, "1435th value should be 255");
+assertEq(view[1436], 230, "1436th value should be 230");
+assertEq(view[1437], 127, "1437th value should be 127");
+assertEq(view[1438], 25, "1438th value should be 25");
+assertEq(view[1439], 255, "1439th value should be 255");
+assertEq(view[1440], 0, "1440th value should be 0");
+assertEq(view[1441], 0, "1441th value should be 0");
+assertEq(view[1442], 0, "1442th value should be 0");
+assertEq(view[1443], 255, "1443th value should be 255");
+assertEq(view[1444], 230, "1444th value should be 230");
+assertEq(view[1445], 127, "1445th value should be 127");
+assertEq(view[1446], 25, "1446th value should be 25");
+assertEq(view[1447], 255, "1447th value should be 255");
+assertEq(view[1448], 205, "1448th value should be 205");
+assertEq(view[1449], 255, "1449th value should be 255");
+assertEq(view[1450], 50, "1450th value should be 50");
+assertEq(view[1451], 255, "1451th value should be 255");
+assertEq(view[1452], 205, "1452th value should be 205");
+assertEq(view[1453], 255, "1453th value should be 255");
+assertEq(view[1454], 50, "1454th value should be 50");
+assertEq(view[1455], 255, "1455th value should be 255");
+assertEq(view[1456], 205, "1456th value should be 205");
+assertEq(view[1457], 255, "1457th value should be 255");
+assertEq(view[1458], 50, "1458th value should be 50");
+assertEq(view[1459], 255, "1459th value should be 255");
+assertEq(view[1460], 205, "1460th value should be 205");
+assertEq(view[1461], 255, "1461th value should be 255");
+assertEq(view[1462], 50, "1462th value should be 50");
+assertEq(view[1463], 255, "1463th value should be 255");
+assertEq(view[1464], 205, "1464th value should be 205");
+assertEq(view[1465], 255, "1465th value should be 255");
+assertEq(view[1466], 50, "1466th value should be 50");
+assertEq(view[1467], 255, "1467th value should be 255");
+assertEq(view[1468], 179, "1468th value should be 179");
+assertEq(view[1469], 127, "1469th value should be 127");
+assertEq(view[1470], 76, "1470th value should be 76");
+assertEq(view[1471], 255, "1471th value should be 255");
+assertEq(view[1472], 179, "1472th value should be 179");
+assertEq(view[1473], 127, "1473th value should be 127");
+assertEq(view[1474], 76, "1474th value should be 76");
+assertEq(view[1475], 255, "1475th value should be 255");
+assertEq(view[1476], 179, "1476th value should be 179");
+assertEq(view[1477], 127, "1477th value should be 127");
+assertEq(view[1478], 76, "1478th value should be 76");
+assertEq(view[1479], 255, "1479th value should be 255");
+assertEq(view[1480], 128, "1480th value should be 128");
+assertEq(view[1481], 127, "1481th value should be 127");
+assertEq(view[1482], 127, "1482th value should be 127");
+assertEq(view[1483], 255, "1483th value should be 255");
+assertEq(view[1484], 103, "1484th value should be 103");
+assertEq(view[1485], 255, "1485th value should be 255");
+assertEq(view[1486], 152, "1486th value should be 152");
+assertEq(view[1487], 255, "1487th value should be 255");
+assertEq(view[1488], 0, "1488th value should be 0");
+assertEq(view[1489], 0, "1489th value should be 0");
+assertEq(view[1490], 0, "1490th value should be 0");
+assertEq(view[1491], 255, "1491th value should be 255");
+assertEq(view[1492], 0, "1492th value should be 0");
+assertEq(view[1493], 0, "1493th value should be 0");
+assertEq(view[1494], 0, "1494th value should be 0");
+assertEq(view[1495], 255, "1495th value should be 255");
+assertEq(view[1496], 128, "1496th value should be 128");
+assertEq(view[1497], 127, "1497th value should be 127");
+assertEq(view[1498], 127, "1498th value should be 127");
+assertEq(view[1499], 255, "1499th value should be 255");
+assertEq(view[1500], 154, "1500th value should be 154");
+assertEq(view[1501], 255, "1501th value should be 255");
+assertEq(view[1502], 101, "1502th value should be 101");
+assertEq(view[1503], 255, "1503th value should be 255");
+assertEq(view[1504], 179, "1504th value should be 179");
+assertEq(view[1505], 127, "1505th value should be 127");
+assertEq(view[1506], 76, "1506th value should be 76");
+assertEq(view[1507], 255, "1507th value should be 255");
+assertEq(view[1508], 205, "1508th value should be 205");
+assertEq(view[1509], 255, "1509th value should be 255");
+assertEq(view[1510], 50, "1510th value should be 50");
+assertEq(view[1511], 255, "1511th value should be 255");
+assertEq(view[1512], 205, "1512th value should be 205");
+assertEq(view[1513], 255, "1513th value should be 255");
+assertEq(view[1514], 50, "1514th value should be 50");
+assertEq(view[1515], 255, "1515th value should be 255");
+assertEq(view[1516], 230, "1516th value should be 230");
+assertEq(view[1517], 127, "1517th value should be 127");
+assertEq(view[1518], 25, "1518th value should be 25");
+assertEq(view[1519], 255, "1519th value should be 255");
+assertEq(view[1520], 0, "1520th value should be 0");
+assertEq(view[1521], 0, "1521th value should be 0");
+assertEq(view[1522], 0, "1522th value should be 0");
+assertEq(view[1523], 255, "1523th value should be 255");
+assertEq(view[1524], 230, "1524th value should be 230");
+assertEq(view[1525], 127, "1525th value should be 127");
+assertEq(view[1526], 25, "1526th value should be 25");
+assertEq(view[1527], 255, "1527th value should be 255");
+assertEq(view[1528], 230, "1528th value should be 230");
+assertEq(view[1529], 127, "1529th value should be 127");
+assertEq(view[1530], 25, "1530th value should be 25");
+assertEq(view[1531], 255, "1531th value should be 255");
+assertEq(view[1532], 205, "1532th value should be 205");
+assertEq(view[1533], 255, "1533th value should be 255");
+assertEq(view[1534], 50, "1534th value should be 50");
+assertEq(view[1535], 255, "1535th value should be 255");
+assertEq(view[1536], 205, "1536th value should be 205");
+assertEq(view[1537], 255, "1537th value should be 255");
+assertEq(view[1538], 50, "1538th value should be 50");
+assertEq(view[1539], 255, "1539th value should be 255");
+assertEq(view[1540], 205, "1540th value should be 205");
+assertEq(view[1541], 255, "1541th value should be 255");
+assertEq(view[1542], 50, "1542th value should be 50");
+assertEq(view[1543], 255, "1543th value should be 255");
+assertEq(view[1544], 205, "1544th value should be 205");
+assertEq(view[1545], 255, "1545th value should be 255");
+assertEq(view[1546], 50, "1546th value should be 50");
+assertEq(view[1547], 255, "1547th value should be 255");
+assertEq(view[1548], 205, "1548th value should be 205");
+assertEq(view[1549], 255, "1549th value should be 255");
+assertEq(view[1550], 50, "1550th value should be 50");
+assertEq(view[1551], 255, "1551th value should be 255");
+assertEq(view[1552], 179, "1552th value should be 179");
+assertEq(view[1553], 127, "1553th value should be 127");
+assertEq(view[1554], 76, "1554th value should be 76");
+assertEq(view[1555], 255, "1555th value should be 255");
+assertEq(view[1556], 179, "1556th value should be 179");
+assertEq(view[1557], 127, "1557th value should be 127");
+assertEq(view[1558], 76, "1558th value should be 76");
+assertEq(view[1559], 255, "1559th value should be 255");
+assertEq(view[1560], 179, "1560th value should be 179");
+assertEq(view[1561], 127, "1561th value should be 127");
+assertEq(view[1562], 76, "1562th value should be 76");
+assertEq(view[1563], 255, "1563th value should be 255");
+assertEq(view[1564], 154, "1564th value should be 154");
+assertEq(view[1565], 255, "1565th value should be 255");
+assertEq(view[1566], 101, "1566th value should be 101");
+assertEq(view[1567], 255, "1567th value should be 255");
+assertEq(view[1568], 26, "1568th value should be 26");
+assertEq(view[1569], 127, "1569th value should be 127");
+assertEq(view[1570], 229, "1570th value should be 229");
+assertEq(view[1571], 255, "1571th value should be 255");
+assertEq(view[1572], 0, "1572th value should be 0");
+assertEq(view[1573], 0, "1573th value should be 0");
+assertEq(view[1574], 0, "1574th value should be 0");
+assertEq(view[1575], 255, "1575th value should be 255");
+assertEq(view[1576], 154, "1576th value should be 154");
+assertEq(view[1577], 255, "1577th value should be 255");
+assertEq(view[1578], 101, "1578th value should be 101");
+assertEq(view[1579], 255, "1579th value should be 255");
+assertEq(view[1580], 179, "1580th value should be 179");
+assertEq(view[1581], 127, "1581th value should be 127");
+assertEq(view[1582], 76, "1582th value should be 76");
+assertEq(view[1583], 255, "1583th value should be 255");
+assertEq(view[1584], 205, "1584th value should be 205");
+assertEq(view[1585], 255, "1585th value should be 255");
+assertEq(view[1586], 50, "1586th value should be 50");
+assertEq(view[1587], 255, "1587th value should be 255");
+assertEq(view[1588], 205, "1588th value should be 205");
+assertEq(view[1589], 255, "1589th value should be 255");
+assertEq(view[1590], 50, "1590th value should be 50");
+assertEq(view[1591], 255, "1591th value should be 255");
+assertEq(view[1592], 230, "1592th value should be 230");
+assertEq(view[1593], 127, "1593th value should be 127");
+assertEq(view[1594], 25, "1594th value should be 25");
+assertEq(view[1595], 255, "1595th value should be 255");
+assertEq(view[1596], 230, "1596th value should be 230");
+assertEq(view[1597], 127, "1597th value should be 127");
+assertEq(view[1598], 25, "1598th value should be 25");
+assertEq(view[1599], 255, "1599th value should be 255");
+
+// Code used to generate the assertEq list above.
+function generateAssertList() {
+ function template(i, x) {
+ return 'assertEq(view[' + i + '], ' + x + ', "' + i + 'th value should be ' + x + '");\n';
+ }
+ var buf = ''
+ for (var i = 0; i < LIMIT_SHOW; i++)
+ buf += template(i, view[i]);
+ print(buf);
+}
+//generateAssertList();
diff --git a/js/src/jit-test/tests/asm.js/sta-transition.js b/js/src/jit-test/tests/asm.js/sta-transition.js
new file mode 100644
index 000000000..9c33da5e2
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/sta-transition.js
@@ -0,0 +1,63 @@
+// Test the inference of shared memory in asm.js.
+//
+// These should not be run with --no-asmjs, the guard below checks this.
+
+load(libdir + "asm.js");
+
+if (!this.SharedArrayBuffer || !isAsmJSCompilationAvailable())
+ quit(0);
+
+setJitCompilerOption('asmjs.atomics.enable', 1);
+
+//////////////////////////////////////////////////////////////////////
+//
+// Int8Array can be used on SharedArrayBuffer, if atomics are present
+
+var m1 = asmCompile("stdlib", "ffi", "heap", `
+ "use asm";
+
+ var i8 = new stdlib.Int8Array(heap);
+ var add = stdlib.Atomics.add;
+
+ function f() {
+ add(i8, 0, 1);
+ return 37;
+ }
+
+ return { f:f }
+`);
+
+assertEq(isAsmJSModule(m1), true);
+
+var { f } = m1(this, {}, new SharedArrayBuffer(65536));
+assertEq(f(), 37);
+
+//////////////////////////////////////////////////////////////////////
+//
+// Int8Array cannot be used on SharedArrayBuffer if atomics are not imported.
+// One argument for the restriction is that there are some optimizations
+// that are legal if the memory is known not to be shared that are illegal
+// when it is shared.
+
+var m4 = asmCompile("stdlib", "ffi", "heap", `
+ "use asm";
+
+ var i8 = new stdlib.Int8Array(heap);
+
+ function i() {
+ return i8[0]|0;
+ }
+
+ return { i:i }
+`);
+
+assertEq(isAsmJSModule(m4), true);
+
+// An error is not actually thrown because the link failure drops us
+// back to JS execution and then the Int8Array constructor will copy data
+// from the SharedArrayBuffer.
+//
+// Running the shell with -w you should see an error here.
+
+var { i } = m4(this, {}, new SharedArrayBuffer(65536));
+assertEq(isAsmJSFunction(i), false);
diff --git a/js/src/jit-test/tests/asm.js/testAddressErrors.js b/js/src/jit-test/tests/asm.js/testAddressErrors.js
new file mode 100644
index 000000000..063939f43
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testAddressErrors.js
@@ -0,0 +1,47 @@
+load(libdir + "asm.js");
+
+setIonCheckGraphCoherency(false);
+setCachingEnabled(false);
+
+// constants
+var buf = new ArrayBuffer(BUF_MIN);
+
+// An unshifted literal constant byte index in the range 0 to 2^31-1 inclusive should give a link failure.
+assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0x7fffffff]|0 } return f'), this, null, buf);
+assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x1fffffff]|0 } return f'), this, null, buf);
+
+
+// An unshifted literal constant byte index outside the range 0 to 2^31-1 inclusive should cause an error compiling.
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x20000000]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x3fffffff]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x40000000]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x7fffffff]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x80000000]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x8fffffff]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0xffffffff]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x100000000]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0x80000000]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0xffffffff]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0x100000000]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int16Array(b); function f() {return arr[-1]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[-2]|0 } return f');
+
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[10-12]|0 } return f');
+
+// An intish shifted literal constant index should not fail to compile or link.
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0x3fffffff>>0]|0 } return f'), this, null, buf)(), 0);
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x3fffffff>>2]|0 } return f'), this, null, buf)(), 0);
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0xffffffff>>0]|0 } return f'), this, null, buf)(), 0);
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0xffffffff>>2]|0 } return f'), this, null, buf)(), 0);
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[-1>>0]|0 } return f'), this, null, buf)(), 0);
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[-1>>2]|0 } return f'), this, null, buf)(), 0);
+// Unsigned (intish) folded constant index.
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0xffffffff>>>0]|0 } return f'), this, null, buf)(), 0);
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {arr[0] = 1; return arr[(0xffffffff+1)>>>0]|0 } return f'), this, null, buf)(), 1);
+
+// A non-intish shifted literal constant index should cause an error compiling.
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0x100000000>>0]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int32Array(b); function f() {return arr[0x100000000>>2]|0 } return f');
+
+// Folded non-intish constant expressions should cause an error compiling.
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0xffffffff+1]|0 } return f');
diff --git a/js/src/jit-test/tests/asm.js/testAsmJSWasmMixing.js b/js/src/jit-test/tests/asm.js/testAsmJSWasmMixing.js
new file mode 100644
index 000000000..e82b3e417
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testAsmJSWasmMixing.js
@@ -0,0 +1,25 @@
+load(libdir + "asm.js");
+load(libdir + "wasm.js");
+
+const Module = WebAssembly.Module;
+const Instance = WebAssembly.Instance;
+const Memory = WebAssembly.Memory;
+
+var asmJS = asmCompile('stdlib', 'ffis', 'buf', USE_ASM + 'var i32 = new stdlib.Int32Array(buf); return {}');
+
+var asmJSBuf = new ArrayBuffer(BUF_MIN);
+asmLink(asmJS, this, null, asmJSBuf);
+
+var wasmMem = wasmEvalText('(module (memory 1 1) (export "mem" memory))').exports.mem;
+assertAsmLinkFail(asmJS, this, null, wasmMem.buffer);
+
+if (!getBuildConfiguration().x64 && isSimdAvailable() && this["SIMD"]) {
+ var simdJS = asmCompile('stdlib', 'ffis', 'buf', USE_ASM + 'var i32 = new stdlib.Int32Array(buf); var i32x4 = stdlib.SIMD.Int32x4; return {}');
+ assertAsmLinkFail(simdJS, this, null, asmJSBuf);
+ assertAsmLinkFail(simdJS, this, null, wasmMem.buffer);
+
+ var simdJSBuf = new ArrayBuffer(BUF_MIN);
+ asmLink(simdJS, this, null, simdJSBuf);
+ asmLink(simdJS, this, null, simdJSBuf); // multiple SIMD.js instantiations succeed
+ assertAsmLinkFail(asmJS, this, null, simdJSBuf); // but not asm.js
+}
diff --git a/js/src/jit-test/tests/asm.js/testAtomic-effect.js b/js/src/jit-test/tests/asm.js/testAtomic-effect.js
new file mode 100644
index 000000000..8db4b1fb9
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testAtomic-effect.js
@@ -0,0 +1,49 @@
+if (!this.Atomics)
+ quit();
+
+load(libdir + "asm.js");
+setJitCompilerOption('asmjs.atomics.enable', 1);
+
+var code = `
+ "use asm";
+
+ var HEAP32 = new stdlib.Int32Array(heap);
+ var add = stdlib.Atomics.add;
+ var load = stdlib.Atomics.load;
+ var _emscripten_asm_const_int=ffi._emscripten_asm_const_int;
+
+ // Regression test for bug 1154858 - Atomics.add for effect did
+ // not get compiled properly because of an assembler bug. This
+ // kernel is derived from the large test case in that bug.
+
+ function add_sharedEv(i1) {
+ i1 = i1 | 0;
+ var i2 = 0;
+ var xx = 0;
+ i2 = i1 + 4 | 0;
+ i1 = load(HEAP32, i2 >> 2) | 0;
+ _emscripten_asm_const_int(7, i2 | 0, i1 | 0) | 0;
+ add(HEAP32, i2 >> 2, 1) | 0;
+ _emscripten_asm_const_int(8, i2 | 0, load(HEAP32, i2 >> 2) | 0, i1 + 1 | 0) | 0;
+ return xx|0;
+ }
+
+ return {add_sharedEv:add_sharedEv};
+`;
+
+var x;
+
+var sab = new SharedArrayBuffer(65536);
+var ffi =
+ { _emscripten_asm_const_int:
+ function (...rest) {
+ //print("OUT: " + rest.join(" "));
+ if (rest[0] == 8)
+ x = rest[2];
+ }
+ };
+var m = asmCompile('stdlib', 'ffi', 'heap', code);
+var {add_sharedEv} = asmLink(m, this, ffi, sab);
+add_sharedEv(13812);
+
+assertEq(x, 1);
diff --git a/js/src/jit-test/tests/asm.js/testAtomics.js b/js/src/jit-test/tests/asm.js/testAtomics.js
new file mode 100644
index 000000000..5b30fb622
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testAtomics.js
@@ -0,0 +1,1886 @@
+if (!this.SharedArrayBuffer || !this.Atomics || !isAsmJSCompilationAvailable())
+ quit();
+
+// The code duplication below is very far from elegant but provides
+// flexibility that comes in handy several places.
+
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+setJitCompilerOption('asmjs.atomics.enable', 1);
+
+const RuntimeError = WebAssembly.RuntimeError;
+const outOfBounds = /index out of bounds/;
+
+var loadModule_int32_code =
+ USE_ASM + `
+ var atomic_load = stdlib.Atomics.load;
+ var atomic_store = stdlib.Atomics.store;
+ var atomic_cmpxchg = stdlib.Atomics.compareExchange;
+ var atomic_exchange = stdlib.Atomics.exchange;
+ var atomic_add = stdlib.Atomics.add;
+ var atomic_sub = stdlib.Atomics.sub;
+ var atomic_and = stdlib.Atomics.and;
+ var atomic_or = stdlib.Atomics.or;
+ var atomic_xor = stdlib.Atomics.xor;
+
+ var i32a = new stdlib.Int32Array(heap);
+
+ // Load element 0
+ function do_load() {
+ var v = 0;
+ v = atomic_load(i32a, 0);
+ return v|0;
+ }
+
+ // Load element i
+ function do_load_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_load(i32a, i>>2);
+ return v|0;
+ }
+
+ // Store 37 in element 0
+ function do_store() {
+ var v = 0;
+ v = atomic_store(i32a, 0, 37);
+ return v|0;
+ }
+
+ // Store 37 in element i
+ function do_store_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_store(i32a, i>>2, 37);
+ return v|0;
+ }
+
+ // Exchange 37 into element 200
+ function do_xchg() {
+ var v = 0;
+ v = atomic_exchange(i32a, 200, 37);
+ return v|0;
+ }
+
+ // Exchange 42 into element i
+ function do_xchg_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_exchange(i32a, i>>2, 42);
+ return v|0;
+ }
+
+ // Exchange 1+2 into element 200. This is not called; all we're
+ // checking is that the compilation succeeds, since 1+2 has type
+ // "intish" (asm.js spec "AdditiveExpression") and this should be
+ // allowed.
+ function do_xchg_intish() {
+ var v = 0;
+ v = atomic_exchange(i32a, 200, 1+2);
+ return v|0;
+ }
+
+ // Add 37 to element 10
+ function do_add() {
+ var v = 0;
+ v = atomic_add(i32a, 10, 37);
+ return v|0;
+ }
+
+ // Add 37 to element i
+ function do_add_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_add(i32a, i>>2, 37);
+ return v|0;
+ }
+
+ // As for do_xchg_intish, above. Given the structure of the
+ // compiler, this covers all the binops.
+ function do_add_intish() {
+ var v = 0;
+ v = atomic_add(i32a, 10, 1+2);
+ return v|0;
+ }
+
+ // Subtract 148 from element 20
+ function do_sub() {
+ var v = 0;
+ v = atomic_sub(i32a, 20, 148);
+ return v|0;
+ }
+
+ // Subtract 148 from element i
+ function do_sub_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_sub(i32a, i>>2, 148);
+ return v|0;
+ }
+
+ // AND 0x33333333 into element 30
+ function do_and() {
+ var v = 0;
+ v = atomic_and(i32a, 30, 0x33333333);
+ return v|0;
+ }
+
+ // AND 0x33333333 into element i
+ function do_and_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_and(i32a, i>>2, 0x33333333);
+ return v|0;
+ }
+
+ // OR 0x33333333 into element 40
+ function do_or() {
+ var v = 0;
+ v = atomic_or(i32a, 40, 0x33333333);
+ return v|0;
+ }
+
+ // OR 0x33333333 into element i
+ function do_or_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_or(i32a, i>>2, 0x33333333);
+ return v|0;
+ }
+
+ // XOR 0x33333333 into element 50
+ function do_xor() {
+ var v = 0;
+ v = atomic_xor(i32a, 50, 0x33333333);
+ return v|0;
+ }
+
+ // XOR 0x33333333 into element i
+ function do_xor_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_xor(i32a, i>>2, 0x33333333);
+ return v|0;
+ }
+
+ // CAS element 100: 0 -> -1
+ function do_cas1() {
+ var v = 0;
+ v = atomic_cmpxchg(i32a, 100, 0, -1);
+ return v|0;
+ }
+
+ // As for do_xchg_intish, above. Will not be called, is here just
+ // to test that the compiler allows intish arguments.
+ function do_cas_intish() {
+ var v = 0;
+ v = atomic_cmpxchg(i32a, 100, 1+2, 2+3);
+ return v|0;
+ }
+
+ // CAS element 100: -1 -> 0x5A5A5A5A
+ function do_cas2() {
+ var v = 0;
+ v = atomic_cmpxchg(i32a, 100, -1, 0x5A5A5A5A);
+ return v|0;
+ }
+
+ // CAS element i: 0 -> -1
+ function do_cas1_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_cmpxchg(i32a, i>>2, 0, -1);
+ return v|0;
+ }
+
+ // CAS element i: -1 -> 0x5A5A5A5A
+ function do_cas2_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_cmpxchg(i32a, i>>2, -1, 0x5A5A5A5A);
+ return v|0;
+ }
+
+ return { load: do_load,
+ load_i: do_load_i,
+ store: do_store,
+ store_i: do_store_i,
+ xchg: do_xchg,
+ xchg_i: do_xchg_i,
+ xchg_intish: do_xchg_intish,
+ add: do_add,
+ add_i: do_add_i,
+ add_intish: do_add_intish,
+ sub: do_sub,
+ sub_i: do_sub_i,
+ and: do_and,
+ and_i: do_and_i,
+ or: do_or,
+ or_i: do_or_i,
+ xor: do_xor,
+ xor_i: do_xor_i,
+ cas1: do_cas1,
+ cas2: do_cas2,
+ cas_intish: do_cas_intish,
+ cas1_i: do_cas1_i,
+ cas2_i: do_cas2_i };
+`;
+
+var loadModule_int32 = asmCompile('stdlib', 'foreign', 'heap', loadModule_int32_code);
+
+function test_int32(heap) {
+ var i32a = new Int32Array(heap);
+ var i32m = asmLink(loadModule_int32, this, {}, heap);
+
+ var size = Int32Array.BYTES_PER_ELEMENT;
+
+ i32a[0] = 12345;
+ assertEq(i32m.load(), 12345);
+ assertEq(i32m.load_i(size*0), 12345);
+
+ assertEq(i32m.store(), 37);
+ assertEq(i32a[0], 37);
+ assertEq(i32m.store_i(size*0), 37);
+
+ i32a[200] = 78;
+ assertEq(i32m.xchg(), 78); // 37 into #200
+ assertEq(i32a[0], 37);
+ assertEq(i32m.xchg_i(size*200), 37); // 42 into #200
+ assertEq(i32a[200], 42);
+
+ i32a[10] = 18;
+ assertEq(i32m.add(), 18);
+ assertEq(i32a[10], 18+37);
+ assertEq(i32m.add_i(size*10), 18+37);
+ assertEq(i32a[10], 18+37+37);
+
+ i32a[20] = 4972;
+ assertEq(i32m.sub(), 4972);
+ assertEq(i32a[20], 4972 - 148);
+ assertEq(i32m.sub_i(size*20), 4972 - 148);
+ assertEq(i32a[20], 4972 - 148 - 148);
+
+ i32a[30] = 0x66666666;
+ assertEq(i32m.and(), 0x66666666);
+ assertEq(i32a[30], 0x22222222);
+ i32a[30] = 0x66666666;
+ assertEq(i32m.and_i(size*30), 0x66666666);
+ assertEq(i32a[30], 0x22222222);
+
+ i32a[40] = 0x22222222;
+ assertEq(i32m.or(), 0x22222222);
+ assertEq(i32a[40], 0x33333333);
+ i32a[40] = 0x22222222;
+ assertEq(i32m.or_i(size*40), 0x22222222);
+ assertEq(i32a[40], 0x33333333);
+
+ i32a[50] = 0x22222222;
+ assertEq(i32m.xor(), 0x22222222);
+ assertEq(i32a[50], 0x11111111);
+ i32a[50] = 0x22222222;
+ assertEq(i32m.xor_i(size*50), 0x22222222);
+ assertEq(i32a[50], 0x11111111);
+
+ i32a[100] = 0;
+ assertEq(i32m.cas1(), 0);
+ assertEq(i32m.cas2(), -1);
+ assertEq(i32a[100], 0x5A5A5A5A);
+
+ i32a[100] = 0;
+ assertEq(i32m.cas1_i(size*100), 0);
+ assertEq(i32m.cas2_i(size*100), -1);
+ assertEq(i32a[100], 0x5A5A5A5A);
+
+ // Out-of-bounds accesses.
+
+ var oob = (heap.byteLength * 2) & ~7;
+
+ assertErrorMessage(() => i32m.cas1_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.cas2_i(oob), RuntimeError, outOfBounds);
+
+ assertErrorMessage(() => i32m.or_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.xor_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.and_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.add_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.sub_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.load_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.store_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.xchg_i(oob), RuntimeError, outOfBounds);
+
+ // Edge cases
+ const INT32_MAX = Math.pow(2, 31);
+ const UINT32_MAX = Math.pow(2, 32);
+ for (var i of [i32a.length*4, INT32_MAX - 4, INT32_MAX, UINT32_MAX - 4]) {
+ assertErrorMessage(() => i32m.load_i(i), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.store_i(i), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.add_i(i), RuntimeError, outOfBounds);
+ }
+
+ i32a[i32a.length-1] = 88;
+ assertEq(i32m.load_i((i32a.length-1)*4), 88);
+ assertEq(i32m.store_i((i32a.length-1)*4), 37);
+ assertEq(i32m.add_i((i32a.length-1)*4), 37);
+ assertEq(i32m.load_i((i32a.length-1)*4), 37+37);
+ i32a[i32a.length-1] = 0;
+}
+
+var loadModule_uint32_code =
+ USE_ASM + `
+ var atomic_load = stdlib.Atomics.load;
+ var atomic_store = stdlib.Atomics.store;
+ var atomic_cmpxchg = stdlib.Atomics.compareExchange;
+ var atomic_exchange = stdlib.Atomics.exchange;
+ var atomic_add = stdlib.Atomics.add;
+ var atomic_sub = stdlib.Atomics.sub;
+ var atomic_and = stdlib.Atomics.and;
+ var atomic_or = stdlib.Atomics.or;
+ var atomic_xor = stdlib.Atomics.xor;
+
+ var i32a = new stdlib.Uint32Array(heap);
+
+ // Load element 0
+ function do_load() {
+ var v = 0;
+ v = atomic_load(i32a, 0);
+ return +(v>>>0);
+ }
+
+ // Load element i
+ function do_load_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_load(i32a, i>>2);
+ return +(v>>>0);
+ }
+
+ // Store 37 in element 0
+ function do_store() {
+ var v = 0;
+ v = atomic_store(i32a, 0, 37);
+ return +(v>>>0);
+ }
+
+ // Store 37 in element i
+ function do_store_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_store(i32a, i>>2, 37);
+ return +(v>>>0);
+ }
+
+ // Exchange 37 into element 200
+ function do_xchg() {
+ var v = 0;
+ v = atomic_exchange(i32a, 200, 37);
+ return v|0;
+ }
+
+ // Exchange 42 into element i
+ function do_xchg_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_exchange(i32a, i>>2, 42);
+ return v|0;
+ }
+
+ // Add 37 to element 10
+ function do_add() {
+ var v = 0;
+ v = atomic_add(i32a, 10, 37);
+ return +(v>>>0);
+ }
+
+ // Add 37 to element i
+ function do_add_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_add(i32a, i>>2, 37);
+ return +(v>>>0);
+ }
+
+ // Subtract 148 from element 20
+ function do_sub() {
+ var v = 0;
+ v = atomic_sub(i32a, 20, 148);
+ return +(v>>>0);
+ }
+
+ // Subtract 148 from element i
+ function do_sub_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_sub(i32a, i>>2, 148);
+ return +(v>>>0);
+ }
+
+ // AND 0x33333333 into element 30
+ function do_and() {
+ var v = 0;
+ v = atomic_and(i32a, 30, 0x33333333);
+ return +(v>>>0);
+ }
+
+ // AND 0x33333333 into element i
+ function do_and_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_and(i32a, i>>2, 0x33333333);
+ return +(v>>>0);
+ }
+
+ // OR 0x33333333 into element 40
+ function do_or() {
+ var v = 0;
+ v = atomic_or(i32a, 40, 0x33333333);
+ return +(v>>>0);
+ }
+
+ // OR 0x33333333 into element i
+ function do_or_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_or(i32a, i>>2, 0x33333333);
+ return +(v>>>0);
+ }
+
+ // XOR 0x33333333 into element 50
+ function do_xor() {
+ var v = 0;
+ v = atomic_xor(i32a, 50, 0x33333333);
+ return +(v>>>0);
+ }
+
+ // XOR 0x33333333 into element i
+ function do_xor_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_xor(i32a, i>>2, 0x33333333);
+ return +(v>>>0);
+ }
+
+ // CAS element 100: 0 -> -1
+ function do_cas1() {
+ var v = 0;
+ v = atomic_cmpxchg(i32a, 100, 0, -1);
+ return +(v>>>0);
+ }
+
+ // CAS element 100: -1 -> 0x5A5A5A5A
+ function do_cas2() {
+ var v = 0;
+ v = atomic_cmpxchg(i32a, 100, -1, 0x5A5A5A5A);
+ return +(v>>>0);
+ }
+
+ // CAS element i: 0 -> -1
+ function do_cas1_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_cmpxchg(i32a, i>>2, 0, -1);
+ return +(v>>>0);
+ }
+
+ // CAS element i: -1 -> 0x5A5A5A5A
+ function do_cas2_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_cmpxchg(i32a, i>>2, -1, 0x5A5A5A5A);
+ return +(v>>>0);
+ }
+
+ return { load: do_load,
+ load_i: do_load_i,
+ store: do_store,
+ store_i: do_store_i,
+ xchg: do_xchg,
+ xchg_i: do_xchg_i,
+ add: do_add,
+ add_i: do_add_i,
+ sub: do_sub,
+ sub_i: do_sub_i,
+ and: do_and,
+ and_i: do_and_i,
+ or: do_or,
+ or_i: do_or_i,
+ xor: do_xor,
+ xor_i: do_xor_i,
+ cas1: do_cas1,
+ cas2: do_cas2,
+ cas1_i: do_cas1_i,
+ cas2_i: do_cas2_i };
+`;
+
+var loadModule_uint32 = asmCompile('stdlib', 'foreign', 'heap', loadModule_uint32_code);
+
+function test_uint32(heap) {
+ var i32a = new Uint32Array(heap);
+ var i32m = loadModule_uint32(this, {}, heap);
+
+ var size = Uint32Array.BYTES_PER_ELEMENT;
+
+ i32a[0] = 12345;
+ assertEq(i32m.load(), 12345);
+ assertEq(i32m.load_i(size*0), 12345);
+
+ assertEq(i32m.store(), 37);
+ assertEq(i32a[0], 37);
+ assertEq(i32m.store_i(size*0), 37);
+
+ i32a[200] = 78;
+ assertEq(i32m.xchg(), 78); // 37 into #200
+ assertEq(i32a[0], 37);
+ assertEq(i32m.xchg_i(size*200), 37); // 42 into #200
+ assertEq(i32a[200], 42);
+
+ i32a[10] = 18;
+ assertEq(i32m.add(), 18);
+ assertEq(i32a[10], 18+37);
+ assertEq(i32m.add_i(size*10), 18+37);
+ assertEq(i32a[10], 18+37+37);
+
+ i32a[20] = 4972;
+ assertEq(i32m.sub(), 4972);
+ assertEq(i32a[20], 4972 - 148);
+ assertEq(i32m.sub_i(size*20), 4972 - 148);
+ assertEq(i32a[20], 4972 - 148 - 148);
+
+ i32a[30] = 0x66666666;
+ assertEq(i32m.and(), 0x66666666);
+ assertEq(i32a[30], 0x22222222);
+ i32a[30] = 0x66666666;
+ assertEq(i32m.and_i(size*30), 0x66666666);
+ assertEq(i32a[30], 0x22222222);
+
+ i32a[40] = 0x22222222;
+ assertEq(i32m.or(), 0x22222222);
+ assertEq(i32a[40], 0x33333333);
+ i32a[40] = 0x22222222;
+ assertEq(i32m.or_i(size*40), 0x22222222);
+ assertEq(i32a[40], 0x33333333);
+
+ i32a[50] = 0x22222222;
+ assertEq(i32m.xor(), 0x22222222);
+ assertEq(i32a[50], 0x11111111);
+ i32a[50] = 0x22222222;
+ assertEq(i32m.xor_i(size*50), 0x22222222);
+ assertEq(i32a[50], 0x11111111);
+
+ i32a[100] = 0;
+ assertEq(i32m.cas1(), 0);
+ assertEq(i32m.cas2(), 0xFFFFFFFF);
+ assertEq(i32a[100], 0x5A5A5A5A);
+
+ i32a[100] = 0;
+ assertEq(i32m.cas1_i(size*100), 0);
+ assertEq(i32m.cas2_i(size*100), 0xFFFFFFFF);
+ assertEq(i32a[100], 0x5A5A5A5A);
+
+ // Out-of-bounds accesses.
+
+ var oob = (heap.byteLength * 2) & ~7;
+
+ assertErrorMessage(() => i32m.cas1_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.cas2_i(oob), RuntimeError, outOfBounds);
+
+ assertErrorMessage(() => i32m.or_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.xor_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.and_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.add_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.sub_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.load_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.store_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.xchg_i(oob), RuntimeError, outOfBounds);
+
+ // Edge cases
+ const INT32_MAX = Math.pow(2, 31);
+ const UINT32_MAX = Math.pow(2, 32);
+ for (var i of [i32a.length*4, INT32_MAX - 4, INT32_MAX, UINT32_MAX - 4]) {
+ assertErrorMessage(() => i32m.load_i(i), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.store_i(i), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i32m.add_i(i), RuntimeError, outOfBounds);
+ }
+
+ i32a[i32a.length-1] = 88;
+ assertEq(i32m.load_i((i32a.length-1)*4), 88);
+ assertEq(i32m.store_i((i32a.length-1)*4), 37);
+ assertEq(i32m.add_i((i32a.length-1)*4), 37);
+ assertEq(i32m.load_i((i32a.length-1)*4), 37+37);
+ i32a[i32a.length-1] = 0;
+}
+
+var loadModule_int16_code =
+ USE_ASM + `
+ var atomic_load = stdlib.Atomics.load;
+ var atomic_store = stdlib.Atomics.store;
+ var atomic_cmpxchg = stdlib.Atomics.compareExchange;
+ var atomic_exchange = stdlib.Atomics.exchange;
+ var atomic_add = stdlib.Atomics.add;
+ var atomic_sub = stdlib.Atomics.sub;
+ var atomic_and = stdlib.Atomics.and;
+ var atomic_or = stdlib.Atomics.or;
+ var atomic_xor = stdlib.Atomics.xor;
+
+ var i16a = new stdlib.Int16Array(heap);
+
+ // Load element 0
+ function do_load() {
+ var v = 0;
+ v = atomic_load(i16a, 0);
+ return v|0;
+ }
+
+ // Load element i
+ function do_load_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_load(i16a, i>>1);
+ return v|0;
+ }
+
+ // Store 37 in element 0
+ function do_store() {
+ var v = 0;
+ v = atomic_store(i16a, 0, 37);
+ return v|0;
+ }
+
+ // Store 37 in element i
+ function do_store_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_store(i16a, i>>1, 37);
+ return v|0;
+ }
+
+ // Exchange 37 into element 200
+ function do_xchg() {
+ var v = 0;
+ v = atomic_exchange(i16a, 200, 37);
+ return v|0;
+ }
+
+ // Exchange 42 into element i
+ function do_xchg_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_exchange(i16a, i>>1, 42);
+ return v|0;
+ }
+
+ // Add 37 to element 10
+ function do_add() {
+ var v = 0;
+ v = atomic_add(i16a, 10, 37);
+ return v|0;
+ }
+
+ // Add 37 to element i
+ function do_add_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_add(i16a, i>>1, 37);
+ return v|0;
+ }
+
+ // Subtract 148 from element 20
+ function do_sub() {
+ var v = 0;
+ v = atomic_sub(i16a, 20, 148);
+ return v|0;
+ }
+
+ // Subtract 148 from element i
+ function do_sub_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_sub(i16a, i>>1, 148);
+ return v|0;
+ }
+
+ // AND 0x3333 into element 30
+ function do_and() {
+ var v = 0;
+ v = atomic_and(i16a, 30, 0x3333);
+ return v|0;
+ }
+
+ // AND 0x3333 into element i
+ function do_and_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_and(i16a, i>>1, 0x3333);
+ return v|0;
+ }
+
+ // OR 0x3333 into element 40
+ function do_or() {
+ var v = 0;
+ v = atomic_or(i16a, 40, 0x3333);
+ return v|0;
+ }
+
+ // OR 0x3333 into element i
+ function do_or_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_or(i16a, i>>1, 0x3333);
+ return v|0;
+ }
+
+ // XOR 0x3333 into element 50
+ function do_xor() {
+ var v = 0;
+ v = atomic_xor(i16a, 50, 0x3333);
+ return v|0;
+ }
+
+ // XOR 0x3333 into element i
+ function do_xor_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_xor(i16a, i>>1, 0x3333);
+ return v|0;
+ }
+
+ // CAS element 100: 0 -> -1
+ function do_cas1() {
+ var v = 0;
+ v = atomic_cmpxchg(i16a, 100, 0, -1);
+ return v|0;
+ }
+
+ // CAS element 100: -1 -> 0x5A5A
+ function do_cas2() {
+ var v = 0;
+ v = atomic_cmpxchg(i16a, 100, -1, 0x5A5A);
+ return v|0;
+ }
+
+ // CAS element i: 0 -> -1
+ function do_cas1_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_cmpxchg(i16a, i>>1, 0, -1);
+ return v|0;
+ }
+
+ // CAS element i: -1 -> 0x5A5A
+ function do_cas2_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_cmpxchg(i16a, i>>1, -1, 0x5A5A);
+ return v|0;
+ }
+
+ return { load: do_load,
+ load_i: do_load_i,
+ store: do_store,
+ store_i: do_store_i,
+ xchg: do_xchg,
+ xchg_i: do_xchg_i,
+ add: do_add,
+ add_i: do_add_i,
+ sub: do_sub,
+ sub_i: do_sub_i,
+ and: do_and,
+ and_i: do_and_i,
+ or: do_or,
+ or_i: do_or_i,
+ xor: do_xor,
+ xor_i: do_xor_i,
+ cas1: do_cas1,
+ cas2: do_cas2,
+ cas1_i: do_cas1_i,
+ cas2_i: do_cas2_i };
+`
+
+var loadModule_int16 = asmCompile('stdlib', 'foreign', 'heap', loadModule_int16_code);
+
+function test_int16(heap) {
+ var i16a = new Int16Array(heap);
+ var i16m = loadModule_int16(this, {}, heap);
+
+ var size = Int16Array.BYTES_PER_ELEMENT;
+
+ i16a[0] = 12345;
+ assertEq(i16m.load(), 12345);
+ assertEq(i16m.load_i(size*0), 12345);
+
+ i16a[0] = -38;
+ assertEq(i16m.load(), -38);
+ assertEq(i16m.load_i(size*0), -38);
+
+ assertEq(i16m.store(), 37);
+ assertEq(i16a[0], 37);
+ assertEq(i16m.store_i(size*0), 37);
+
+ i16a[200] = 78;
+ assertEq(i16m.xchg(), 78); // 37 into #200
+ assertEq(i16a[0], 37);
+ assertEq(i16m.xchg_i(size*200), 37); // 42 into #200
+ assertEq(i16a[200], 42);
+
+ i16a[10] = 18;
+ assertEq(i16m.add(), 18);
+ assertEq(i16a[10], 18+37);
+ assertEq(i16m.add_i(size*10), 18+37);
+ assertEq(i16a[10], 18+37+37);
+
+ i16a[10] = -38;
+ assertEq(i16m.add(), -38);
+ assertEq(i16a[10], -38+37);
+ assertEq(i16m.add_i(size*10), -38+37);
+ assertEq(i16a[10], -38+37+37);
+
+ i16a[20] = 4972;
+ assertEq(i16m.sub(), 4972);
+ assertEq(i16a[20], 4972 - 148);
+ assertEq(i16m.sub_i(size*20), 4972 - 148);
+ assertEq(i16a[20], 4972 - 148 - 148);
+
+ i16a[30] = 0x6666;
+ assertEq(i16m.and(), 0x6666);
+ assertEq(i16a[30], 0x2222);
+ i16a[30] = 0x6666;
+ assertEq(i16m.and_i(size*30), 0x6666);
+ assertEq(i16a[30], 0x2222);
+
+ i16a[40] = 0x2222;
+ assertEq(i16m.or(), 0x2222);
+ assertEq(i16a[40], 0x3333);
+ i16a[40] = 0x2222;
+ assertEq(i16m.or_i(size*40), 0x2222);
+ assertEq(i16a[40], 0x3333);
+
+ i16a[50] = 0x2222;
+ assertEq(i16m.xor(), 0x2222);
+ assertEq(i16a[50], 0x1111);
+ i16a[50] = 0x2222;
+ assertEq(i16m.xor_i(size*50), 0x2222);
+ assertEq(i16a[50], 0x1111);
+
+ i16a[100] = 0;
+ assertEq(i16m.cas1(), 0);
+ assertEq(i16m.cas2(), -1);
+ assertEq(i16a[100], 0x5A5A);
+
+ i16a[100] = 0;
+ assertEq(i16m.cas1_i(size*100), 0);
+ assertEq(i16m.cas2_i(size*100), -1);
+ assertEq(i16a[100], 0x5A5A);
+
+ var oob = (heap.byteLength * 2) & ~7;
+
+ assertErrorMessage(() => i16m.cas1_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.cas2_i(oob), RuntimeError, outOfBounds);
+
+ assertErrorMessage(() => i16m.or_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.xor_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.and_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.add_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.sub_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.load_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.store_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.xchg_i(oob), RuntimeError, outOfBounds);
+
+ // Edge cases
+ const INT32_MAX = Math.pow(2, 31);
+ const UINT32_MAX = Math.pow(2, 32);
+ for (var i of [i16a.length*2, INT32_MAX - 2, INT32_MAX, UINT32_MAX - 2]) {
+ assertErrorMessage(() => i16m.load_i(i), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.store_i(i), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.add_i(i), RuntimeError, outOfBounds);
+ }
+
+ i16a[i16a.length-1] = 88;
+ assertEq(i16m.load_i((i16a.length-1)*2), 88);
+ assertEq(i16m.store_i((i16a.length-1)*2), 37);
+ assertEq(i16m.add_i((i16a.length-1)*2), 37);
+ assertEq(i16m.load_i((i16a.length-1)*2), 37+37);
+ i16a[i16a.length-1] = 0;
+}
+
+var loadModule_uint16_code =
+ USE_ASM + `
+ var atomic_load = stdlib.Atomics.load;
+ var atomic_store = stdlib.Atomics.store;
+ var atomic_cmpxchg = stdlib.Atomics.compareExchange;
+ var atomic_exchange = stdlib.Atomics.exchange;
+ var atomic_add = stdlib.Atomics.add;
+ var atomic_sub = stdlib.Atomics.sub;
+ var atomic_and = stdlib.Atomics.and;
+ var atomic_or = stdlib.Atomics.or;
+ var atomic_xor = stdlib.Atomics.xor;
+
+ var i16a = new stdlib.Uint16Array(heap);
+
+ // Load element 0
+ function do_load() {
+ var v = 0;
+ v = atomic_load(i16a, 0);
+ return v|0;
+ }
+
+ // Load element i
+ function do_load_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_load(i16a, i>>1);
+ return v|0;
+ }
+
+ // Store 37 in element 0
+ function do_store() {
+ var v = 0;
+ v = atomic_store(i16a, 0, 37);
+ return v|0;
+ }
+
+ // Store 37 in element i
+ function do_store_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_store(i16a, i>>1, 37);
+ return v|0;
+ }
+
+ // Exchange 37 into element 200
+ function do_xchg() {
+ var v = 0;
+ v = atomic_exchange(i16a, 200, 37);
+ return v|0;
+ }
+
+ // Exchange 42 into element i
+ function do_xchg_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_exchange(i16a, i>>1, 42);
+ return v|0;
+ }
+
+ // Add 37 to element 10
+ function do_add() {
+ var v = 0;
+ v = atomic_add(i16a, 10, 37);
+ return v|0;
+ }
+
+ // Add 37 to element i
+ function do_add_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_add(i16a, i>>1, 37);
+ return v|0;
+ }
+
+ // Subtract 148 from element 20
+ function do_sub() {
+ var v = 0;
+ v = atomic_sub(i16a, 20, 148);
+ return v|0;
+ }
+
+ // Subtract 148 from element i
+ function do_sub_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_sub(i16a, i>>1, 148);
+ return v|0;
+ }
+
+ // AND 0x3333 into element 30
+ function do_and() {
+ var v = 0;
+ v = atomic_and(i16a, 30, 0x3333);
+ return v|0;
+ }
+
+ // AND 0x3333 into element i
+ function do_and_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_and(i16a, i>>1, 0x3333);
+ return v|0;
+ }
+
+ // OR 0x3333 into element 40
+ function do_or() {
+ var v = 0;
+ v = atomic_or(i16a, 40, 0x3333);
+ return v|0;
+ }
+
+ // OR 0x3333 into element i
+ function do_or_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_or(i16a, i>>1, 0x3333);
+ return v|0;
+ }
+
+ // XOR 0x3333 into element 50
+ function do_xor() {
+ var v = 0;
+ v = atomic_xor(i16a, 50, 0x3333);
+ return v|0;
+ }
+
+ // XOR 0x3333 into element i
+ function do_xor_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_xor(i16a, i>>1, 0x3333);
+ return v|0;
+ }
+
+ // CAS element 100: 0 -> -1
+ function do_cas1() {
+ var v = 0;
+ v = atomic_cmpxchg(i16a, 100, 0, -1);
+ return v|0;
+ }
+
+ // CAS element 100: -1 -> 0x5A5A
+ function do_cas2() {
+ var v = 0;
+ v = atomic_cmpxchg(i16a, 100, -1, 0x5A5A);
+ return v|0;
+ }
+
+ // CAS element i: 0 -> -1
+ function do_cas1_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_cmpxchg(i16a, i>>1, 0, -1);
+ return v|0;
+ }
+
+ // CAS element i: -1 -> 0x5A5A
+ function do_cas2_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_cmpxchg(i16a, i>>1, -1, 0x5A5A);
+ return v|0;
+ }
+
+ return { load: do_load,
+ load_i: do_load_i,
+ store: do_store,
+ store_i: do_store_i,
+ xchg: do_xchg,
+ xchg_i: do_xchg_i,
+ add: do_add,
+ add_i: do_add_i,
+ sub: do_sub,
+ sub_i: do_sub_i,
+ and: do_and,
+ and_i: do_and_i,
+ or: do_or,
+ or_i: do_or_i,
+ xor: do_xor,
+ xor_i: do_xor_i,
+ cas1: do_cas1,
+ cas2: do_cas2,
+ cas1_i: do_cas1_i,
+ cas2_i: do_cas2_i };
+`
+
+var loadModule_uint16 = asmCompile('stdlib', 'foreign', 'heap', loadModule_uint16_code);
+
+function test_uint16(heap) {
+ var i16a = new Uint16Array(heap);
+ var i16m = loadModule_uint16(this, {}, heap);
+
+ var size = Uint16Array.BYTES_PER_ELEMENT;
+
+ i16a[0] = 12345;
+ assertEq(i16m.load(), 12345);
+ assertEq(i16m.load_i(size*0), 12345);
+
+ i16a[0] = -38;
+ assertEq(i16m.load(), (0x10000-38));
+ assertEq(i16m.load_i(size*0), (0x10000-38));
+
+ assertEq(i16m.store(), 37);
+ assertEq(i16a[0], 37);
+ assertEq(i16m.store_i(size*0), 37);
+
+ i16a[200] = 78;
+ assertEq(i16m.xchg(), 78); // 37 into #200
+ assertEq(i16a[0], 37);
+ assertEq(i16m.xchg_i(size*200), 37); // 42 into #200
+ assertEq(i16a[200], 42);
+
+ i16a[10] = 18;
+ assertEq(i16m.add(), 18);
+ assertEq(i16a[10], 18+37);
+ assertEq(i16m.add_i(size*10), 18+37);
+ assertEq(i16a[10], 18+37+37);
+
+ i16a[10] = -38;
+ assertEq(i16m.add(), (0x10000-38));
+ assertEq(i16a[10], (0x10000-38)+37);
+ assertEq(i16m.add_i(size*10), (0x10000-38)+37);
+ assertEq(i16a[10], ((0x10000-38)+37+37) & 0xFFFF);
+
+ i16a[20] = 4972;
+ assertEq(i16m.sub(), 4972);
+ assertEq(i16a[20], 4972 - 148);
+ assertEq(i16m.sub_i(size*20), 4972 - 148);
+ assertEq(i16a[20], 4972 - 148 - 148);
+
+ i16a[30] = 0x6666;
+ assertEq(i16m.and(), 0x6666);
+ assertEq(i16a[30], 0x2222);
+ i16a[30] = 0x6666;
+ assertEq(i16m.and_i(size*30), 0x6666);
+ assertEq(i16a[30], 0x2222);
+
+ i16a[40] = 0x2222;
+ assertEq(i16m.or(), 0x2222);
+ assertEq(i16a[40], 0x3333);
+ i16a[40] = 0x2222;
+ assertEq(i16m.or_i(size*40), 0x2222);
+ assertEq(i16a[40], 0x3333);
+
+ i16a[50] = 0x2222;
+ assertEq(i16m.xor(), 0x2222);
+ assertEq(i16a[50], 0x1111);
+ i16a[50] = 0x2222;
+ assertEq(i16m.xor_i(size*50), 0x2222);
+ assertEq(i16a[50], 0x1111);
+
+ i16a[100] = 0;
+ assertEq(i16m.cas1(), 0);
+ assertEq(i16m.cas2(), -1 & 0xFFFF);
+ assertEq(i16a[100], 0x5A5A);
+
+ i16a[100] = 0;
+ assertEq(i16m.cas1_i(size*100), 0);
+ assertEq(i16m.cas2_i(size*100), -1 & 0xFFFF);
+ assertEq(i16a[100], 0x5A5A);
+
+ var oob = (heap.byteLength * 2) & ~7;
+
+ assertErrorMessage(() => i16m.cas1_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.cas2_i(oob), RuntimeError, outOfBounds);
+
+ assertErrorMessage(() => i16m.or_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.xor_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.and_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.add_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.sub_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.load_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.store_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.xchg_i(oob), RuntimeError, outOfBounds);
+
+ // Edge cases
+ const INT32_MAX = Math.pow(2, 31);
+ const UINT32_MAX = Math.pow(2, 32);
+ for (var i of [i16a.length*2, INT32_MAX - 2, INT32_MAX, UINT32_MAX - 2]) {
+ assertErrorMessage(() => i16m.load_i(i), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.store_i(i), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i16m.add_i(i), RuntimeError, outOfBounds);
+ }
+
+ i16a[i16a.length-1] = 88;
+ assertEq(i16m.load_i((i16a.length-1)*2), 88);
+ assertEq(i16m.store_i((i16a.length-1)*2), 37);
+ assertEq(i16m.add_i((i16a.length-1)*2), 37);
+ assertEq(i16m.load_i((i16a.length-1)*2), 37+37);
+ i16a[i16a.length-1] = 0;
+}
+
+var loadModule_int8_code =
+ USE_ASM + `
+ var atomic_load = stdlib.Atomics.load;
+ var atomic_store = stdlib.Atomics.store;
+ var atomic_cmpxchg = stdlib.Atomics.compareExchange;
+ var atomic_exchange = stdlib.Atomics.exchange;
+ var atomic_add = stdlib.Atomics.add;
+ var atomic_sub = stdlib.Atomics.sub;
+ var atomic_and = stdlib.Atomics.and;
+ var atomic_or = stdlib.Atomics.or;
+ var atomic_xor = stdlib.Atomics.xor;
+
+ var i8a = new stdlib.Int8Array(heap);
+
+ // Load element 0
+ function do_load() {
+ var v = 0;
+ v = atomic_load(i8a, 0);
+ return v|0;
+ }
+
+ // Load element i
+ function do_load_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_load(i8a, i);
+ return v|0;
+ }
+
+ // Store 37 in element 0
+ function do_store() {
+ var v = 0;
+ v = atomic_store(i8a, 0, 37);
+ return v|0;
+ }
+
+ // Store 37 in element i
+ function do_store_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_store(i8a, i, 37);
+ return v|0;
+ }
+
+ // Exchange 37 into element 200
+ function do_xchg() {
+ var v = 0;
+ v = atomic_exchange(i8a, 200, 37);
+ return v|0;
+ }
+
+ // Exchange 42 into element i
+ function do_xchg_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_exchange(i8a, i, 42);
+ return v|0;
+ }
+
+ // Add 37 to element 10
+ function do_add() {
+ var v = 0;
+ v = atomic_add(i8a, 10, 37);
+ return v|0;
+ }
+
+ // Add 37 to element i
+ function do_add_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_add(i8a, i, 37);
+ return v|0;
+ }
+
+ // Subtract 108 from element 20
+ function do_sub() {
+ var v = 0;
+ v = atomic_sub(i8a, 20, 108);
+ return v|0;
+ }
+
+ // Subtract 108 from element i
+ function do_sub_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_sub(i8a, i, 108);
+ return v|0;
+ }
+
+ // AND 0x33 into element 30
+ function do_and() {
+ var v = 0;
+ v = atomic_and(i8a, 30, 0x33);
+ return v|0;
+ }
+
+ // AND 0x33 into element i
+ function do_and_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_and(i8a, i, 0x33);
+ return v|0;
+ }
+
+ // OR 0x33 into element 40
+ function do_or() {
+ var v = 0;
+ v = atomic_or(i8a, 40, 0x33);
+ return v|0;
+ }
+
+ // OR 0x33 into element i
+ function do_or_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_or(i8a, i, 0x33);
+ return v|0;
+ }
+
+ // XOR 0x33 into element 50
+ function do_xor() {
+ var v = 0;
+ v = atomic_xor(i8a, 50, 0x33);
+ return v|0;
+ }
+
+ // XOR 0x33 into element i
+ function do_xor_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_xor(i8a, i, 0x33);
+ return v|0;
+ }
+
+ // CAS element 100: 0 -> -1
+ function do_cas1() {
+ var v = 0;
+ v = atomic_cmpxchg(i8a, 100, 0, -1);
+ return v|0;
+ }
+
+ // CAS element 100: -1 -> 0x5A
+ function do_cas2() {
+ var v = 0;
+ v = atomic_cmpxchg(i8a, 100, -1, 0x5A);
+ return v|0;
+ }
+
+ // CAS element i: 0 -> -1
+ function do_cas1_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_cmpxchg(i8a, i, 0, -1);
+ return v|0;
+ }
+
+ // CAS element i: -1 -> 0x5A
+ function do_cas2_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_cmpxchg(i8a, i, -1, 0x5A);
+ return v|0;
+ }
+
+ return { load: do_load,
+ load_i: do_load_i,
+ store: do_store,
+ store_i: do_store_i,
+ xchg: do_xchg,
+ xchg_i: do_xchg_i,
+ add: do_add,
+ add_i: do_add_i,
+ sub: do_sub,
+ sub_i: do_sub_i,
+ and: do_and,
+ and_i: do_and_i,
+ or: do_or,
+ or_i: do_or_i,
+ xor: do_xor,
+ xor_i: do_xor_i,
+ cas1: do_cas1,
+ cas2: do_cas2,
+ cas1_i: do_cas1_i,
+ cas2_i: do_cas2_i };
+`
+
+var loadModule_int8 = asmCompile('stdlib', 'foreign', 'heap', loadModule_int8_code);
+
+function test_int8(heap) {
+ var i8a = new Int8Array(heap);
+ var i8m = loadModule_int8(this, {}, heap);
+
+ for ( var i=0 ; i < i8a.length ; i++ )
+ i8a[i] = 0;
+
+ var size = Int8Array.BYTES_PER_ELEMENT;
+
+ i8a[0] = 123;
+ assertEq(i8m.load(), 123);
+ assertEq(i8m.load_i(0), 123);
+
+ assertEq(i8m.store(), 37);
+ assertEq(i8a[0], 37);
+ assertEq(i8m.store_i(0), 37);
+
+ i8a[200] = 78;
+ assertEq(i8m.xchg(), 78); // 37 into #200
+ assertEq(i8a[0], 37);
+ assertEq(i8m.xchg_i(size*200), 37); // 42 into #200
+ assertEq(i8a[200], 42);
+
+ i8a[10] = 18;
+ assertEq(i8m.add(), 18);
+ assertEq(i8a[10], 18+37);
+ assertEq(i8m.add_i(10), 18+37);
+ assertEq(i8a[10], 18+37+37);
+
+ i8a[20] = 49;
+ assertEq(i8m.sub(), 49);
+ assertEq(i8a[20], 49 - 108);
+ assertEq(i8m.sub_i(20), 49 - 108);
+ assertEq(i8a[20], ((49 - 108 - 108) << 24) >> 24); // Byte, sign extended
+
+ i8a[30] = 0x66;
+ assertEq(i8m.and(), 0x66);
+ assertEq(i8a[30], 0x22);
+ i8a[30] = 0x66;
+ assertEq(i8m.and_i(30), 0x66);
+ assertEq(i8a[30], 0x22);
+
+ i8a[40] = 0x22;
+ assertEq(i8m.or(), 0x22);
+ assertEq(i8a[40], 0x33);
+ i8a[40] = 0x22;
+ assertEq(i8m.or_i(40), 0x22);
+ assertEq(i8a[40], 0x33);
+
+ i8a[50] = 0x22;
+ assertEq(i8m.xor(), 0x22);
+ assertEq(i8a[50], 0x11);
+ i8a[50] = 0x22;
+ assertEq(i8m.xor_i(50), 0x22);
+ assertEq(i8a[50], 0x11);
+
+ i8a[100] = 0;
+ assertEq(i8m.cas1(), 0);
+ assertEq(i8m.cas2(), -1);
+ assertEq(i8a[100], 0x5A);
+
+ i8a[100] = 0;
+ assertEq(i8m.cas1_i(100), 0);
+ assertEq(i8m.cas2_i(100), -1);
+ assertEq(i8a[100], 0x5A);
+
+ var oob = (heap.byteLength * 2) & ~7;
+
+ assertErrorMessage(() => i8m.cas1_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.cas2_i(oob), RuntimeError, outOfBounds);
+
+ assertErrorMessage(() => i8m.or_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.xor_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.and_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.add_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.sub_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.load_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.store_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.xchg_i(oob), RuntimeError, outOfBounds);
+
+ // Edge cases
+ const INT32_MAX = Math.pow(2, 31);
+ const UINT32_MAX = Math.pow(2, 32);
+ for (var i of [i8a.length, INT32_MAX - 1, INT32_MAX, UINT32_MAX - 1]) {
+ assertErrorMessage(() => i8m.load_i(i), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.store_i(i), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.add_i(i), RuntimeError, outOfBounds);
+ }
+
+ i8a[i8a.length-1] = 88;
+ assertEq(i8m.load_i(i8a.length-1), 88);
+ assertEq(i8m.store_i(i8a.length-1), 37);
+ assertEq(i8m.add_i(i8a.length-1), 37);
+ assertEq(i8m.load_i(i8a.length-1), 37+37);
+ i8a[i8a.length-1] = 0;
+}
+
+var loadModule_uint8_code =
+ USE_ASM + `
+ var atomic_load = stdlib.Atomics.load;
+ var atomic_store = stdlib.Atomics.store;
+ var atomic_cmpxchg = stdlib.Atomics.compareExchange;
+ var atomic_exchange = stdlib.Atomics.exchange;
+ var atomic_add = stdlib.Atomics.add;
+ var atomic_sub = stdlib.Atomics.sub;
+ var atomic_and = stdlib.Atomics.and;
+ var atomic_or = stdlib.Atomics.or;
+ var atomic_xor = stdlib.Atomics.xor;
+
+ var i8a = new stdlib.Uint8Array(heap);
+
+ // Load element 0
+ function do_load() {
+ var v = 0;
+ v = atomic_load(i8a, 0);
+ return v|0;
+ }
+
+ // Load element i
+ function do_load_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_load(i8a, i);
+ return v|0;
+ }
+
+ // Store 37 in element 0
+ function do_store() {
+ var v = 0;
+ v = atomic_store(i8a, 0, 37);
+ return v|0;
+ }
+
+ // Store 37 in element i
+ function do_store_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_store(i8a, i, 37);
+ return v|0;
+ }
+
+ // Exchange 37 into element 200
+ function do_xchg() {
+ var v = 0;
+ v = atomic_exchange(i8a, 200, 37);
+ return v|0;
+ }
+
+ // Exchange 42 into element i
+ function do_xchg_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_exchange(i8a, i, 42);
+ return v|0;
+ }
+
+ // Add 37 to element 10
+ function do_add() {
+ var v = 0;
+ v = atomic_add(i8a, 10, 37);
+ return v|0;
+ }
+
+ // Add 37 to element i
+ function do_add_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_add(i8a, i, 37);
+ return v|0;
+ }
+
+ // Subtract 108 from element 20
+ function do_sub() {
+ var v = 0;
+ v = atomic_sub(i8a, 20, 108);
+ return v|0;
+ }
+
+ // Subtract 108 from element i
+ function do_sub_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_sub(i8a, i, 108);
+ return v|0;
+ }
+
+ // AND 0x33 into element 30
+ function do_and() {
+ var v = 0;
+ v = atomic_and(i8a, 30, 0x33);
+ return v|0;
+ }
+
+ // AND 0x33 into element i
+ function do_and_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_and(i8a, i, 0x33);
+ return v|0;
+ }
+
+ // OR 0x33 into element 40
+ function do_or() {
+ var v = 0;
+ v = atomic_or(i8a, 40, 0x33);
+ return v|0;
+ }
+
+ // OR 0x33 into element i
+ function do_or_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_or(i8a, i, 0x33);
+ return v|0;
+ }
+
+ // XOR 0x33 into element 50
+ function do_xor() {
+ var v = 0;
+ v = atomic_xor(i8a, 50, 0x33);
+ return v|0;
+ }
+
+ // XOR 0x33 into element i
+ function do_xor_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_xor(i8a, i, 0x33);
+ return v|0;
+ }
+
+ // CAS element 100: 0 -> -1
+ function do_cas1() {
+ var v = 0;
+ v = atomic_cmpxchg(i8a, 100, 0, -1);
+ return v|0;
+ }
+
+ // CAS element 100: -1 -> 0x5A
+ function do_cas2() {
+ var v = 0;
+ v = atomic_cmpxchg(i8a, 100, -1, 0x5A);
+ return v|0;
+ }
+
+ // CAS element i: 0 -> -1
+ function do_cas1_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_cmpxchg(i8a, i, 0, -1);
+ return v|0;
+ }
+
+ // CAS element i: -1 -> 0x5A
+ function do_cas2_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_cmpxchg(i8a, i, -1, 0x5A);
+ return v|0;
+ }
+
+ return { load: do_load,
+ load_i: do_load_i,
+ store: do_store,
+ store_i: do_store_i,
+ xchg: do_xchg,
+ xchg_i: do_xchg_i,
+ add: do_add,
+ add_i: do_add_i,
+ sub: do_sub,
+ sub_i: do_sub_i,
+ and: do_and,
+ and_i: do_and_i,
+ or: do_or,
+ or_i: do_or_i,
+ xor: do_xor,
+ xor_i: do_xor_i,
+ cas1: do_cas1,
+ cas2: do_cas2,
+ cas1_i: do_cas1_i,
+ cas2_i: do_cas2_i };
+`
+
+var loadModule_uint8 = asmCompile('stdlib', 'foreign', 'heap', loadModule_uint8_code);
+
+function test_uint8(heap) {
+ var i8a = new Uint8Array(heap);
+ var i8m = loadModule_uint8(this, {}, heap);
+
+ for ( var i=0 ; i < i8a.length ; i++ )
+ i8a[i] = 0;
+
+ var size = Uint8Array.BYTES_PER_ELEMENT;
+
+ i8a[0] = 123;
+ assertEq(i8m.load(), 123);
+ assertEq(i8m.load_i(0), 123);
+
+ i8a[0] = -38;
+ assertEq(i8m.load(), (0x100-38));
+ assertEq(i8m.load_i(size*0), (0x100-38));
+
+ assertEq(i8m.store(), 37);
+ assertEq(i8a[0], 37);
+ assertEq(i8m.store_i(0), 37);
+
+ i8a[200] = 78;
+ assertEq(i8m.xchg(), 78); // 37 into #200
+ assertEq(i8a[0], 37);
+ assertEq(i8m.xchg_i(size*200), 37); // 42 into #200
+ assertEq(i8a[200], 42);
+
+ i8a[10] = 18;
+ assertEq(i8m.add(), 18);
+ assertEq(i8a[10], 18+37);
+ assertEq(i8m.add_i(10), 18+37);
+ assertEq(i8a[10], 18+37+37);
+
+ i8a[10] = -38;
+ assertEq(i8m.add(), (0x100-38));
+ assertEq(i8a[10], (0x100-38)+37);
+ assertEq(i8m.add_i(size*10), (0x100-38)+37);
+ assertEq(i8a[10], ((0x100-38)+37+37) & 0xFF);
+
+ i8a[20] = 49;
+ assertEq(i8m.sub(), 49);
+ assertEq(i8a[20], (49 - 108) & 255);
+ assertEq(i8m.sub_i(20), (49 - 108) & 255);
+ assertEq(i8a[20], (49 - 108 - 108) & 255); // Byte, zero extended
+
+ i8a[30] = 0x66;
+ assertEq(i8m.and(), 0x66);
+ assertEq(i8a[30], 0x22);
+ i8a[30] = 0x66;
+ assertEq(i8m.and_i(30), 0x66);
+ assertEq(i8a[30], 0x22);
+
+ i8a[40] = 0x22;
+ assertEq(i8m.or(), 0x22);
+ assertEq(i8a[40], 0x33);
+ i8a[40] = 0x22;
+ assertEq(i8m.or_i(40), 0x22);
+ assertEq(i8a[40], 0x33);
+
+ i8a[50] = 0x22;
+ assertEq(i8m.xor(), 0x22);
+ assertEq(i8a[50], 0x11);
+ i8a[50] = 0x22;
+ assertEq(i8m.xor_i(50), 0x22);
+ assertEq(i8a[50], 0x11);
+
+ i8a[100] = 0;
+ assertEq(i8m.cas1(), 0);
+ assertEq(i8m.cas2(), 255);
+ assertEq(i8a[100], 0x5A);
+
+ i8a[100] = 0;
+ assertEq(i8m.cas1_i(100), 0);
+ assertEq(i8m.cas2_i(100), 255);
+ assertEq(i8a[100], 0x5A);
+
+ var oob = (heap.byteLength * 2) & ~7;
+
+ assertErrorMessage(() => i8m.cas1_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.cas2_i(oob), RuntimeError, outOfBounds);
+
+ assertErrorMessage(() => i8m.or_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.xor_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.and_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.add_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.sub_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.load_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.store_i(oob), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.xchg_i(oob), RuntimeError, outOfBounds);
+
+ // Edge cases
+ const INT32_MAX = Math.pow(2, 31);
+ const UINT32_MAX = Math.pow(2, 32);
+ for (var i of [i8a.length, INT32_MAX - 1, INT32_MAX, UINT32_MAX - 1]) {
+ assertErrorMessage(() => i8m.load_i(i), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.store_i(i), RuntimeError, outOfBounds);
+ assertErrorMessage(() => i8m.add_i(i), RuntimeError, outOfBounds);
+ }
+
+ i8a[i8a.length-1] = 88;
+ assertEq(i8m.load_i(i8a.length-1), 88);
+ assertEq(i8m.store_i(i8a.length-1), 37);
+ assertEq(i8m.add_i(i8a.length-1), 37);
+ assertEq(i8m.load_i(i8a.length-1), 37+37);
+ i8a[i8a.length-1] = 0;
+}
+
+var loadModule_misc_code =
+ USE_ASM + `
+ var atomic_isLockFree = stdlib.Atomics.isLockFree;
+
+ function ilf1() {
+ return atomic_isLockFree(1)|0;
+ }
+
+ function ilf2() {
+ return atomic_isLockFree(2)|0;
+ }
+
+ function ilf3() {
+ return atomic_isLockFree(3)|0;
+ }
+
+ function ilf4() {
+ return atomic_isLockFree(4)|0;
+ }
+
+ function ilf5() {
+ return atomic_isLockFree(5)|0;
+ }
+
+ function ilf6() {
+ return atomic_isLockFree(6)|0;
+ }
+
+ function ilf7() {
+ return atomic_isLockFree(7)|0;
+ }
+
+ function ilf8() {
+ return atomic_isLockFree(8)|0;
+ }
+
+ function ilf9() {
+ return atomic_isLockFree(9)|0;
+ }
+
+ return { ilf1: ilf1,
+ ilf2: ilf2,
+ ilf3: ilf3,
+ ilf4: ilf4,
+ ilf5: ilf5,
+ ilf6: ilf6,
+ ilf7: ilf7,
+ ilf8: ilf8,
+ ilf9: ilf9 };
+`
+
+var loadModule_misc = asmCompile('stdlib', 'foreign', 'heap', loadModule_misc_code);
+
+function test_misc(heap) {
+ var misc = loadModule_misc(this, {}, heap);
+
+ assertEq(misc.ilf1(), 1); // Guaranteed by SpiderMonkey, not spec
+ assertEq(misc.ilf2(), 1); // Guaranteed by SpiderMonkey, not spec
+ assertEq(misc.ilf3(), 0);
+ assertEq(misc.ilf4(), 1); // Guaranteed by SpiderMonkey, not spec
+ assertEq(misc.ilf5(), 0);
+ assertEq(misc.ilf6(), 0);
+ assertEq(misc.ilf7(), 0);
+ assertEq(misc.ilf8(), 0); // Required by spec, for now
+ assertEq(misc.ilf9(), 0);
+}
+
+// Shared-memory Uint8ClampedArray is not supported for asm.js.
+
+var heap = new SharedArrayBuffer(65536);
+
+test_int8(heap);
+test_uint8(heap);
+test_int16(heap);
+test_uint16(heap);
+test_int32(heap);
+test_uint32(heap);
+test_misc(heap);
+
+// Bug 1254167: Effective Address Analysis should be void on atomics accesses,
+var code = `
+ "use asm";
+ var HEAP32 = new stdlib.Int32Array(heap);
+ var load = stdlib.Atomics.load;
+ function f() {
+ var i2 = 0;
+ i2 = 305002 | 0;
+ return load(HEAP32, i2 >> 2) | 0;
+ }
+ return f;
+`;
+var f = asmLink(asmCompile('stdlib', 'ffi', 'heap', code), this, {}, new SharedArrayBuffer(0x10000));
+assertErrorMessage(f, RuntimeError, outOfBounds);
+
+// Test that ARM callouts compile.
+setARMHwCapFlags('vfp');
+
+asmCompile('stdlib', 'ffi', 'heap',
+ USE_ASM + `
+ var atomic_exchange = stdlib.Atomics.exchange;
+ var i8a = new stdlib.Int8Array(heap);
+
+ function do_xchg() {
+ var v = 0;
+ v = atomic_exchange(i8a, 200, 37);
+ return v|0;
+ }
+
+ return { xchg: do_xchg }
+`);
+
diff --git a/js/src/jit-test/tests/asm.js/testBasic.js b/js/src/jit-test/tests/asm.js/testBasic.js
new file mode 100644
index 000000000..f47a837f3
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBasic.js
@@ -0,0 +1,176 @@
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+assertAsmTypeFail(USE_ASM);
+assertAsmTypeFail(USE_ASM + 'return');
+assertAsmTypeFail(USE_ASM + 'function f() 0');
+assertAsmTypeFail(USE_ASM + 'function f(){}');
+assertAsmTypeFail(USE_ASM + 'function f(){} return 0');
+assertAsmTypeFail(USE_ASM + 'function f() 0; return 0');
+assertAsmTypeFail(USE_ASM + 'function f(){} return g');
+assertAsmTypeFail(USE_ASM + 'function f(){} function f(){} return f');
+assertAsmTypeFail(USE_ASM + 'function f(){}; function g(){}; return {f, g}');
+assertAsmTypeFail(USE_ASM + 'var f = f;');
+assertAsmTypeFail(USE_ASM + 'var f=0; function f(){} return f');
+assertAsmTypeFail(USE_ASM + 'var f=glob.Math.imul; return {}');
+assertAsmTypeFail('glob', USE_ASM + 'var f=glob.Math.imul; function f(){} return f');
+assertAsmTypeFail('glob','foreign', USE_ASM + 'var f=foreign.foo; function f(){} return f');
+assertAsmTypeFail(USE_ASM + 'function f(){} var f=[f,f]; return f');
+assertAsmTypeFail(USE_ASM + 'function f() 0; return f');
+assertAsmTypeFail('"use strict";' + USE_ASM + 'function f() {} return f');
+assertAsmTypeFail(USE_ASM + '"use strict"; function f() {} return f');
+assertAsmTypeFail(USE_ASM + '"use foopy" + 1; function f() {} return f');
+assertAsmTypeFail(USE_ASM + 'function f() { "use strict"; } return f');
+assertEq(asmLink(asmCompile(USE_ASM + '"use asm"; function f() {} return f'))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + '"use foopy"; function f() {} return f'))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + '"use foopy"; "use blarg"; function f() {} return f'))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() { "use asm"; } return f'))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() { "use foopy"; } return f'))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() { "use foopy"; "use blarg"; } return f'))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) { "use foopy"; i=i|0; } return f'))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) { "use foopy"; "use asm"; i=i|0; } return f'))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + '"use warm"; function f(i) { "use cold"; i=i|0 } function g() { "use hot"; return 0 } return f'))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + '"use warm"; function f(i) { "use cold"; i=i|0 } function g() { "use asm"; return 0 } return f'))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(){} return f'))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(){;} return f'))(), undefined);
+assertAsmTypeFail(USE_ASM + 'function f(i,j){;} return f');
+assertEq(asmLink(asmCompile('"use asm";; function f(){};;; return f;;'))(), undefined);
+assertAsmTypeFail(USE_ASM + 'function f(x){} return f');
+assertAsmTypeFail(USE_ASM + 'function f(){if (0) return; return 1} return f');
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(x){x=x|0} return f'))(42), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(x){x=x|0; return x|0} return f'))(42), 42);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(x){x=x|0; return x|0;;;} return f'))(42), 42);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(x,y){x=x|0;y=y|0; return (x+y)|0} return f'))(44, -2), 42);
+assertAsmTypeFail('a', USE_ASM + 'function a(){} return a');
+assertAsmTypeFail('a','b','c', USE_ASM + 'var c');
+assertAsmTypeFail('a','b','c', USE_ASM + 'var c=0');
+assertAsmTypeFail(USE_ASM + 'c=0;return {}');
+assertAsmTypeFail('x','x', USE_ASM + 'function a(){} return a');
+assertAsmTypeFail('x','y','x', USE_ASM + 'function a(){} return a');
+assertEq(asmLink(asmCompile('x', USE_ASM + 'function a(){} return a'))(), undefined);
+assertEq(asmLink(asmCompile('x','y', USE_ASM + 'function a(){} return a'))(), undefined);
+assertEq(asmLink(asmCompile('x','y','z', USE_ASM + 'function a(){} return a'))(), undefined);
+assertAsmTypeFail('x','y', USE_ASM + 'function y(){} return f');
+assertEq(asmLink(asmCompile('x', USE_ASM + 'function f(){} return f'), 1, 2, 3)(), undefined);
+assertEq(asmLink(asmCompile('x', USE_ASM + 'function f(){} return f'), 1)(), undefined);
+assertEq(asmLink(asmCompile('x','y', USE_ASM + 'function f(){} return f'), 1, 2)(), undefined);
+
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) {i=i|0} return f'))(42), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() {var i=0;; var j=1;} return f'))(), undefined); // bug 877965 second part
+assertAsmTypeFail(USE_ASM + 'function f(i) {i=i|0;var i} return f');
+assertAsmTypeFail(USE_ASM + 'function f(i) {i=i|0;var i=0} return f');
+
+assertAsmTypeFail('glob', USE_ASM + 'var im=glob.imul; function f() {} return f');
+assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i,j) {i=i|0;j=j|0; return im(i,j)|0} return f'), null);
+assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i,j) {i=i|0;j=j|0; return im(i,j)|0} return f'), {});
+assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i,j) {i=i|0;j=j|0; return im(i,j)|0} return f'), {imul:Math.imul});
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i,j) {i=i|0;j=j|0; return im(i,j)|0} return f'), {Math:{imul:Math.imul}})(2,3), 6);
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i,j) {i=i|0;j=j|0; return im(i,j)|0} return f'), this)(8,4), 32);
+
+var module = asmCompile('glob','i','b', USE_ASM + 'var i32=new glob.Int32Array(b); function f(){} return f');
+assertAsmLinkAlwaysFail(module, null, null);
+assertAsmLinkAlwaysFail(module, this, null, null);
+assertAsmLinkAlwaysFail(module, this, null, null);
+assertAsmLinkAlwaysFail(module, this, null, new ArrayBuffer(1));
+assertAsmLinkFail(module, this, null, new ArrayBuffer(4));
+assertAsmLinkFail(module, this, null, new ArrayBuffer(100));
+assertAsmLinkFail(module, this, null, new ArrayBuffer(4092));
+assertAsmLinkFail(module, this, null, new ArrayBuffer(64000));
+assertAsmLinkFail(module, this, null, new ArrayBuffer(BUF_MIN+4));
+assertAsmLinkDeprecated(module, this, null, new ArrayBuffer(4096));
+assertAsmLinkDeprecated(module, this, null, new ArrayBuffer(2*4096));
+assertAsmLinkDeprecated(module, this, null, new ArrayBuffer(4*4096));
+assertAsmLinkDeprecated(module, this, null, new ArrayBuffer(32*1024));
+assertEq(asmLink(module, this, null, new ArrayBuffer(BUF_MIN))(), undefined);
+
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i]|0; return i|0}; return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i>>1]|0; return i|0}; return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i>>1]|0; return i|0}; return f');
+assertAsmLinkAlwaysFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i>>2]|0; return i|0}; return f'), this, null, new ArrayBuffer(BUF_MIN-1));
+assertEq(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i>>2]|0; return i|0}; return f')(this, null, new ArrayBuffer(BUF_MIN))(), 0);
+
+var exp = asmLink(asmCompile(USE_ASM + "return {}"));
+assertEq(Object.keys(exp).length, 0);
+
+var exp = asmLink(asmCompile(USE_ASM + "function f() { return 3 } return {f:f,f:f}"));
+assertEq(exp.f(), 3);
+assertEq(Object.keys(exp).join(), 'f');
+
+var exp = asmLink(asmCompile(USE_ASM + "function f() { return 4 } return {f1:f,f2:f}"));
+assertEq(exp.f1(), 4);
+assertEq(exp.f2(), 4);
+assertEq(Object.keys(exp).sort().join(), 'f1,f2');
+assertEq(exp.f1, exp.f2);
+
+assertAsmTypeFail(USE_ASM + "function f() { return 3 } return {1:f}");
+assertAsmTypeFail(USE_ASM + "function f() { return 3 } return {__proto__:f}");
+assertAsmTypeFail(USE_ASM + "function f() { return 3 } return {get x() {} }");
+
+var exp = asmLink(asmCompile(USE_ASM + 'function internal() { return ((g()|0)+2)|0 } function f() { return 1 } function g() { return 2 } function h() { return internal()|0 } return {f:f,g1:g,h1:h}'));
+assertEq(exp.f(), 1);
+assertEq(exp.g1(), 2);
+assertEq(exp.h1(), 4);
+assertEq(Object.keys(exp).join(), 'f,g1,h1');
+
+// can't test destructuring args with Function constructor
+function assertTypeFailInEval(str)
+{
+ if (!isAsmJSCompilationAvailable())
+ return;
+
+ var caught = false;
+ var oldOpts = options("werror");
+ assertEq(oldOpts.indexOf("werror"), -1);
+ try {
+ eval(str);
+ } catch (e) {
+ assertEq((''+e).indexOf(ASM_TYPE_FAIL_STRING) == -1, false);
+ caught = true;
+ }
+ assertEq(caught, true);
+ options("werror");
+}
+assertTypeFailInEval('function f({}) { "use asm"; function g() {} return g }');
+assertTypeFailInEval('function f({global}) { "use asm"; function g() {} return g }');
+assertTypeFailInEval('function f(global, {imports}) { "use asm"; function g() {} return g }');
+assertTypeFailInEval('function f(g = 2) { "use asm"; function g() {} return g }');
+assertTypeFailInEval('function *f() { "use asm"; function g() {} return g }');
+assertTypeFailInEval('f => { "use asm"; function g() {} return g }');
+assertTypeFailInEval('var f = { method() {"use asm"; return {}} }');
+assertAsmTypeFail(USE_ASM + 'return {m() {}};');
+assertTypeFailInEval('class f { constructor() {"use asm"; return {}} }');
+assertAsmTypeFail(USE_ASM + 'class c { constructor() {}}; return c;');
+
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'var)') }, SyntaxError);
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'return)') }, SyntaxError);
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'var z=-2w') }, SyntaxError);
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'var z=-2w;') }, SyntaxError);
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function') }, SyntaxError);
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f') }, SyntaxError);
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f(') }, SyntaxError);
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f()') }, SyntaxError);
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f() {') }, SyntaxError);
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f() {} var') }, SyntaxError);
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f() {} var TBL=-2w; return f') }, SyntaxError);
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function f() {} var TBL=-2w return f') }, SyntaxError);
+assertThrowsInstanceOf(function() { new Function(USE_ASM + 'function () {}') }, SyntaxError);
+assertNoWarning(function() { parse("function f() { 'use asm'; function g() {} return g }") });
+
+// Test asm.js->asm.js, wasm->asm.js, asm.js->wasm imports:
+
+var f = asmLink(asmCompile(USE_ASM + 'function f() {} return f'));
+var g = asmLink(asmCompile('glob', 'ffis', USE_ASM + 'var f = ffis.f; function g() { return f(1)|0; } return g'), null, {f});
+assertEq(g(), 0);
+
+if (wasmIsSupported()) {
+ var h = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`(module
+ (import $f "imp" "f" (param i32) (result i32))
+ (func $h (result i32) (call $f (i32.const 1)))
+ (export "h" $h)
+ )`)), {imp:{f}}).exports.h;
+ assertEq(h(), 0);
+
+ var i = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`(module (func $i) (export "i" $i))`))).exports.i
+ var j = asmLink(asmCompile('glob', 'ffis', USE_ASM + 'var i = ffis.i; function j() { return i(1)|0; } return j'), null, {i});
+ assertEq(j(), 0);
+}
diff --git a/js/src/jit-test/tests/asm.js/testBug1046688.js b/js/src/jit-test/tests/asm.js/testBug1046688.js
new file mode 100644
index 000000000..692747f02
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1046688.js
@@ -0,0 +1,11 @@
+enableSPSProfiling();
+for (var j = 0; j < 1000; ++j) {
+ (function(stdlib) {
+ "use asm";
+ var pow = stdlib.Math.pow;
+ function f() {
+ return +pow(.0, .0)
+ }
+ return f;
+})(this)()
+}
diff --git a/js/src/jit-test/tests/asm.js/testBug1057248.js b/js/src/jit-test/tests/asm.js/testBug1057248.js
new file mode 100644
index 000000000..96197e04c
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1057248.js
@@ -0,0 +1,134 @@
+if (!this.SharedArrayBuffer || !isAsmJSCompilationAvailable())
+ quit();
+
+Random = {
+ weighted: function(wa) {
+ var a = [];
+ for (var i = 0; i < wa.length; ++i) {
+ for (var j = 0; j < wa[i]; ++j) {}
+ }
+ }
+}
+s = (function() {
+ Random.weighted([{
+ n() {}
+ }, {
+ n() {}
+ }, {
+ n() {}
+ }, {
+ w: 5,
+ n() {}
+ }
+ ])
+})()
+var builtinObjectNames = [];
+(function() {
+ function exploreDeeper(a, a) {
+ var s = Object.getOwnPropertyNames(a)
+ for (var j = 0; j < s.length; ++j) {
+ if (typeof h == "" && n != "") {}
+ }
+ builtinObjectNames.push()
+ }
+ exploreDeeper(Math, "")
+})(this, false)
+r = autoExpr(Random.weighted([]));
+r = autoExpr(Random.weighted([]));
+(Random.weighted([]));
+r = (Random.weighted([]))
+v = autoExpr(Random.weighted([]), true);
+r = autoExpr(Random.weighted([{
+ n() {}
+ }
+]), true)
+function autoExpr() {}
+function makeStatement() {}
+s = Random.weighted([{
+ n() {}
+ }
+])
+a = Random.weighted([{}, {}, {}, {}, {}, {
+ n() {}
+ }
+])
+a = Random.weighted([{
+ n() {}
+ }, {}, {}
+])
+var recursiveFunctions = [{
+ text: "(function(){{}})"
+ }, {
+ text: "(function(){if(0){}(1)})",
+ n() {}
+ }, {
+ text: "(function(){t:[]()})",
+ n() {}
+ }, {
+ text: "(function(){g()})",
+ n() {}
+ }
+];
+(function s() {
+ for (var i = 0; i < recursiveFunctions.length; ++i) {
+ a = recursiveFunctions[i];
+ var text = a.text
+ a = eval(text.replace(/@/, ""))
+ }
+ function g() {}
+ s = Random.weighted([{
+ w: 1,
+ n() {}
+ }, {
+ n() {}
+ }, //
+ {
+ n() {}
+ }, //
+ {
+ n() {}
+ }, {
+ w: 0,
+ n() {}
+ }, {
+ n() {}
+ }, {
+ n() {}
+ }, {
+ w: 1,
+ n() {}
+ }, {
+ w: makeStatement
+ }, {
+ w: 5
+ }
+ ])
+ t = function() {}
+ function c() {}
+})()
+function testMathyFunction(f, inputs) {
+ var r = [];
+ for (var j = 0; j < inputs.length; ++j) {
+ for (var k = 0; k < inputs.length; ++k) {
+ try {
+ f(inputs[j])
+ } catch (e) {}
+ }
+ }
+ uneval([])
+}
+mathy2 = (function(stdlib, foreign, heap) {
+ "use asm";
+ var Float32ArrayView = new stdlib.Float32Array(heap)
+ function f(i0) {
+ i0 = i0 | 0;
+ (Float32ArrayView[-i0 >> 2]) = 1.
+ }
+ return f
+})(this, {
+}, new SharedArrayBuffer(4096))
+testMathyFunction(mathy2, [-0])
+mathy5 = (function(y) {
+ ((function() {})(mathy2(y)()))
+})
+testMathyFunction(mathy5, [Math.PI])
diff --git a/js/src/jit-test/tests/asm.js/testBug1099216.js b/js/src/jit-test/tests/asm.js/testBug1099216.js
new file mode 100644
index 000000000..3514f307d
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1099216.js
@@ -0,0 +1,61 @@
+if (typeof SIMD === 'undefined' || !isSimdAvailable()) {
+ print("won't run tests as simd extensions aren't activated yet");
+ quit(0);
+}
+
+(function(global) {
+ "use asm";
+ var frd = global.Math.fround;
+ var fx4 = global.SIMD.Float32x4;
+ var fc4 = fx4.check;
+ var fsp = fx4.splat;
+ function s(){}
+ function d(x){x=fc4(x);}
+ function e() {
+ var x = frd(0);
+ x = frd(x / x);
+ s();
+ d(fsp(x));
+ }
+ return e;
+})(this)();
+
+(function(m) {
+ "use asm"
+ var k = m.SIMD.Bool32x4
+ var g = m.SIMD.Int32x4
+ var gc = g.check;
+ var h = g.select
+ function f() {
+ var x = k(0, 0, 0, 0)
+ var y = g(1, 2, 3, 4)
+ return gc(h(x, y, y))
+ }
+ return f;
+})(this)();
+
+t = (function(global) {
+ "use asm"
+ var toF = global.Math.fround
+ var f4 = global.SIMD.Float32x4
+ var f4c = f4.check
+ function p(x, y, width, value, max_iterations) {
+ x = x | 0
+ y = y | 0
+ width = width | 0
+ value = value | 0
+ max_iterations = max_iterations | 0
+ }
+ function m(xf, yf, yd, max_iterations) {
+ xf = toF(xf)
+ yf = toF(yf)
+ yd = toF(yd)
+ max_iterations = max_iterations | 0
+ var _ = f4(0, 0, 0, 0), c_im4 = f4(0, 0, 0, 0)
+ c_im4 = f4(yf, yd, yd, yf)
+ return f4c(c_im4);
+ }
+ return {p:p,m:m};
+})(this)
+t.p();
+t.m();
diff --git a/js/src/jit-test/tests/asm.js/testBug1111327.js b/js/src/jit-test/tests/asm.js/testBug1111327.js
new file mode 100644
index 000000000..dc1ff6c51
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1111327.js
@@ -0,0 +1,11 @@
+load(libdir + "asm.js");
+
+// Single-step profiling currently only works in the ARM simulator
+if (!getBuildConfiguration()["arm-simulator"])
+ quit();
+
+enableSPSProfiling();
+enableSingleStepProfiling();
+var m = asmCompile(USE_ASM + 'function f() {} return f');
+asmLink(m)();
+asmLink(m)();
diff --git a/js/src/jit-test/tests/asm.js/testBug1117235.js b/js/src/jit-test/tests/asm.js/testBug1117235.js
new file mode 100644
index 000000000..80cac617b
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1117235.js
@@ -0,0 +1,8 @@
+load(libdir + "asserts.js");
+
+if (helperThreadCount() === 0)
+ quit(0);
+
+options('werror');
+offThreadCompileScript("function f() {'use asm'}");
+assertThrowsInstanceOf(()=>runOffThreadScript(), TypeError);
diff --git a/js/src/jit-test/tests/asm.js/testBug1117255.js b/js/src/jit-test/tests/asm.js/testBug1117255.js
new file mode 100644
index 000000000..0cda6f359
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1117255.js
@@ -0,0 +1,14 @@
+function f(stdlib, foreign, buffer) {
+ "use asm";
+ var i32 = new stdlib.Int32Array(buffer);
+ function g(i) {
+ i=i|0;
+ var j=0;
+ for (; (j>>>0) < 100000; j=(j+1)|0)
+ i32[i>>2] = j;
+ }
+ return g
+}
+var g = f(this, null, new ArrayBuffer(1<<16));
+timeout(.1, function cb() { return true });
+g(1<<16);
diff --git a/js/src/jit-test/tests/asm.js/testBug1125561.js b/js/src/jit-test/tests/asm.js/testBug1125561.js
new file mode 100644
index 000000000..9d0d99ca4
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1125561.js
@@ -0,0 +1,47 @@
+load(libdir + "asm.js");
+
+setJitCompilerOption("ion.warmup.trigger", 0);
+setJitCompilerOption("baseline.warmup.trigger", 0);
+setJitCompilerOption("offthread-compilation.enable", 0);
+
+function ffi1() { assertJitStackInvariants() }
+function ffi2() { return { valueOf() { assertJitStackInvariants() } } }
+
+// FFI with no coercion
+var m = asmCompile('stdlib', 'foreign', `
+ "use asm";
+ var ffi = foreign.ffi;
+ function f() { ffi(); }
+ return f
+`);
+var f = asmLink(m, null, {ffi:ffi1});
+f();
+f();
+
+// FFI with ToInt32 coercion
+var m = asmCompile('stdlib', 'foreign', `
+ "use asm";
+ var ffi = foreign.ffi;
+ function f() { ffi() | 0; }
+ return f
+`);
+var f = asmLink(m, null, {ffi:ffi1});
+f();
+f();
+var f = asmLink(m, null, {ffi:ffi2});
+f();
+f();
+
+// FFI with ToNumber coercion
+var m = asmCompile('stdlib', 'foreign', `
+ "use asm";
+ var ffi = foreign.ffi;
+ function f() { +ffi(); }
+ return f
+`);
+var f = asmLink(m, this, {ffi:ffi1});
+f();
+f();
+var f = asmLink(m, this, {ffi:ffi2});
+f();
+f();
diff --git a/js/src/jit-test/tests/asm.js/testBug1147144.js b/js/src/jit-test/tests/asm.js/testBug1147144.js
new file mode 100644
index 000000000..fbdf3a396
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1147144.js
@@ -0,0 +1,20 @@
+load(libdir + 'asm.js');
+load(libdir + 'asserts.js');
+
+if (!isAsmJSCompilationAvailable())
+ quit();
+
+setDiscardSource(true)
+assertEq(eval(`(function asmModule() { "use asm"; function asmFun() {} return asmFun })`).toString(), "function asmModule() {\n [sourceless code]\n}");
+assertEq(eval(`(function asmModule() { "use asm"; function asmFun() {} return asmFun })`).toSource(), "(function asmModule() {\n [sourceless code]\n})");
+assertEq(eval(`(function asmModule() { "use asm"; function asmFun() {} return asmFun })`)().toString(), "function asmFun() {\n [sourceless code]\n}");
+assertEq(eval(`(function asmModule() { "use asm"; function asmFun() {} return asmFun })`)().toSource(), "function asmFun() {\n [sourceless code]\n}");
+assertEq((evaluate(`function asmModule1() { "use asm"; function asmFun() {} return asmFun }`), asmModule1).toString(), "function asmModule1() {\n [sourceless code]\n}");
+assertEq((evaluate(`function asmModule2() { "use asm"; function asmFun() {} return asmFun }`), asmModule2).toSource(), "function asmModule2() {\n [sourceless code]\n}");
+assertEq((evaluate(`function asmModule3() { "use asm"; function asmFun() {} return asmFun }`), asmModule3)().toString(), "function asmFun() {\n [sourceless code]\n}");
+assertEq((evaluate(`function asmModule4() { "use asm"; function asmFun() {} return asmFun }`), asmModule4)().toSource(), "function asmFun() {\n [sourceless code]\n}");
+assertEq(asmCompile(USE_ASM + `function asmFun() {} return asmFun`).toString(), "function anonymous() {\n [sourceless code]\n}");
+assertEq(asmCompile(USE_ASM + `function asmFun() {} return asmFun`).toSource(), "(function anonymous() {\n [sourceless code]\n})");
+assertEq(asmCompile(USE_ASM + `function asmFun() {} return asmFun`)().toString(), "function asmFun() {\n [sourceless code]\n}");
+assertEq(asmCompile(USE_ASM + `function asmFun() {} return asmFun`)().toSource(), "function asmFun() {\n [sourceless code]\n}");
+assertThrowsInstanceOf(()=>asmCompile('stdlib',USE_ASM + "var sin=stdlib.Math.sin;return {}")({Math:{}}), Error);
diff --git a/js/src/jit-test/tests/asm.js/testBug1155176.js b/js/src/jit-test/tests/asm.js/testBug1155176.js
new file mode 100644
index 000000000..80c6f6314
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1155176.js
@@ -0,0 +1,52 @@
+if (!this.SharedArrayBuffer || !isAsmJSCompilationAvailable())
+ quit(0);
+
+load(libdir + "asm.js");
+setJitCompilerOption('asmjs.atomics.enable', 1);
+
+// The way this is constructed, either the first module does not
+// verify as asm.js (if the >>>0 is left off, which was legal prior to
+// bug 1155176), or the results of the two modules have to be equal.
+
+var m = asmCompile("stdlib", "ffi", "heap", `
+ "use asm";
+
+ var view = new stdlib.Uint32Array(heap);
+ var cas = stdlib.Atomics.compareExchange;
+ var hi = ffi.hi;
+
+ function run() {
+ hi(+(cas(view, 37, 0, 0)>>>0));
+ }
+
+ return run;
+`);
+
+assertEq(isAsmJSModule(m), true);
+
+function nonm(stdlib, ffi, heap) {
+
+ var view = new stdlib.Uint32Array(heap);
+ var cas = stdlib.Atomics.compareExchange;
+ var hi = ffi.hi;
+
+ function run() {
+ hi(+cas(view, 37, 0, 0));
+ }
+
+ return run;
+}
+
+var sab = new SharedArrayBuffer(65536);
+var ua = new Uint32Array(sab);
+var results = [];
+var mrun = m(this, {hi: function (x) { results.push(x) }}, sab);
+var nonmrun = nonm(this, {hi: function (x) { results.push(x) }}, sab);
+
+ua[37] = 0x80000001;
+
+mrun();
+nonmrun();
+
+assertEq(results[0], ua[37]);
+assertEq(results[0], results[1]);
diff --git a/js/src/jit-test/tests/asm.js/testBug1164391.js b/js/src/jit-test/tests/asm.js/testBug1164391.js
new file mode 100644
index 000000000..80ec8659c
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1164391.js
@@ -0,0 +1,27 @@
+if (!this.SharedArrayBuffer || !isAsmJSCompilationAvailable())
+ quit(0);
+
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+setJitCompilerOption('asmjs.atomics.enable', 1);
+
+var m = asmCompile("stdlib", "ffi", "heap", `
+ "use asm";
+ var HEAP32 = new stdlib.Int32Array(heap);
+ var add = stdlib.Atomics.add;
+ var load = stdlib.Atomics.load;
+ function add_sharedEv(i1) {
+ i1 = i1 | 0;
+ load(HEAP32, i1 >> 2);
+ add(HEAP32, i1 >> 2, 1);
+ load(HEAP32, i1 >> 2);
+ }
+ return {add_sharedEv:add_sharedEv};
+`);
+
+if (isAsmJSCompilationAvailable())
+ assertEq(isAsmJSModule(m), true);
+
+var sab = new SharedArrayBuffer(65536);
+var {add_sharedEv} = m(this, {}, sab);
+assertErrorMessage(() => add_sharedEv(sab.byteLength), WebAssembly.RuntimeError, /index out of bounds/);
diff --git a/js/src/jit-test/tests/asm.js/testBug1183060.js b/js/src/jit-test/tests/asm.js/testBug1183060.js
new file mode 100644
index 000000000..af2e9cf1b
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1183060.js
@@ -0,0 +1,55 @@
+if (!this.SharedArrayBuffer)
+ quit(0);
+
+function loadModule_uint16(stdlib, foreign, heap) {
+ "use asm";
+ var atomic_add = stdlib.Atomics.add;
+ var atomic_sub = stdlib.Atomics.sub;
+ var atomic_and = stdlib.Atomics.and;
+ var atomic_or = stdlib.Atomics.or;
+ var atomic_xor = stdlib.Atomics.xor;
+ var i16a = new stdlib.Uint16Array(heap);
+ function do_add_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_add(i16a, i>>1, 0x3333)|0;
+ }
+ function do_sub_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_sub(i16a, i>>1, 0x3333)|0;
+ }
+ function do_and_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_and(i16a, i>>1, 0x3333)|0;
+ }
+ function do_or_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_or(i16a, i>>1, 0x3333)|0;
+ }
+ function do_xor_i(i) {
+ i = i|0;
+ var v = 0;
+ v = atomic_xor(i16a, i>>1, 0x3333)|0;
+ }
+ return { add_i: do_add_i,
+ sub_i: do_sub_i,
+ and_i: do_and_i,
+ or_i: do_or_i,
+ xor_i: do_xor_i };
+}
+
+function test_uint16(heap) {
+ var i16m = loadModule_uint16(this, {}, heap);
+ var size = Uint16Array.BYTES_PER_ELEMENT;
+ i16m.add_i(size*40)
+ i16m.sub_i(size*40)
+ i16m.and_i(size*40)
+ i16m.or_i(size*40)
+ i16m.xor_i(size*40)
+}
+
+var heap = new SharedArrayBuffer(65536);
+test_uint16(heap);
diff --git a/js/src/jit-test/tests/asm.js/testBug1219098.js b/js/src/jit-test/tests/asm.js/testBug1219098.js
new file mode 100644
index 000000000..1573ec460
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1219098.js
@@ -0,0 +1,14 @@
+load(libdir + "asm.js");
+
+var bigScript = `
+ function wee() { return 42 }
+ function asmModule() { 'use asm'; function f() { return 43 } return f}
+` + ' '.repeat(10 * 1024 * 1024);
+
+eval(bigScript);
+
+if (isAsmJSCompilationAvailable())
+ assertEq(isAsmJSModule(asmModule), true);
+
+assertEq(wee(), 42);
+assertEq(eval('(' + wee.toSource() + ')')(), 42);
diff --git a/js/src/jit-test/tests/asm.js/testBug1236484.js b/js/src/jit-test/tests/asm.js/testBug1236484.js
new file mode 100644
index 000000000..61a8b49dc
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1236484.js
@@ -0,0 +1,10 @@
+var lfcode = new Array();
+lfcode.push("gczeal(2, 1);");
+lfcode.push(`
+function test(stdlib, foreign) {
+ "use asm"
+ function f(y) {}
+ return f
+}`);
+for (var i = 0; i < 2; ++i)
+ evaluate(lfcode.shift());
diff --git a/js/src/jit-test/tests/asm.js/testBug1236541.js b/js/src/jit-test/tests/asm.js/testBug1236541.js
new file mode 100644
index 000000000..7f6d54999
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1236541.js
@@ -0,0 +1,15 @@
+enableSPSProfiling();
+
+function mod() {
+ "use asm";
+ function f(i0) {
+ i0 = i0 | 0
+ switch (0) {
+ case 0:
+ }
+ }
+ return f;
+}
+
+mod()();
+mod()();
diff --git a/js/src/jit-test/tests/asm.js/testBug1236552.js b/js/src/jit-test/tests/asm.js/testBug1236552.js
new file mode 100644
index 000000000..2a47ba7ec
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1236552.js
@@ -0,0 +1,3 @@
+g = newGlobal();
+Debugger(g).memory.trackingAllocationSites = true;
+evaluate("function h() { 'use asm'; return {}}", { global: g });
diff --git a/js/src/jit-test/tests/asm.js/testBug1255954.js b/js/src/jit-test/tests/asm.js/testBug1255954.js
new file mode 100644
index 000000000..5529d950e
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1255954.js
@@ -0,0 +1,14 @@
+// |jit-test| slow
+
+const USE_ASM = '"use asm";';
+if (!('oomTest' in this))
+ quit();
+function asmCompile() {
+ var f = Function.apply(null, arguments);
+}
+oomTest(() => {
+ try {
+ function f(b) {}
+ } catch (exc0) {}
+ f(asmCompile(USE_ASM + "function f() { var i=42; return i|0; for(;1;) {} return 0 } return f"));
+});
diff --git a/js/src/jit-test/tests/asm.js/testBug1291887.js b/js/src/jit-test/tests/asm.js/testBug1291887.js
new file mode 100644
index 000000000..7632f0bf3
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1291887.js
@@ -0,0 +1,13 @@
+(function(stdlib) {
+ "use asm"
+ var log = stdlib.Math.log
+
+ function f(x) {
+ x = +x
+ var y = 3.
+ return 0, y
+ return +log(x) + y
+ }
+
+ return f
+})(this)
diff --git a/js/src/jit-test/tests/asm.js/testBug1301191.js b/js/src/jit-test/tests/asm.js/testBug1301191.js
new file mode 100644
index 000000000..46426bc46
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1301191.js
@@ -0,0 +1,24 @@
+// |jit-test| exitstatus:6
+timeout(1);
+// Adapted from randomly chosen test: js/src/jit-test/tests/asm.js/testBug975182.js
+(function() {
+ g = (function(t, foreign) {
+ "use asm";
+ var ff = foreign.ff;
+ function f() {
+ ff()
+ }
+ return f
+ })(this, {
+ ff: arguments.callee
+ })
+})()
+function m(f) {
+ var i = 0;
+ while (true) {
+ f();
+ if ((i++ % 1000) === 0)
+ gc();
+ }
+}
+m(g);
diff --git a/js/src/jit-test/tests/asm.js/testBug1302407.js b/js/src/jit-test/tests/asm.js/testBug1302407.js
new file mode 100644
index 000000000..545d6d6b2
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug1302407.js
@@ -0,0 +1,6 @@
+if (!this['SharedArrayBuffer'])
+ quit();
+
+setJitCompilerOption('asmjs.atomics.enable', 1);
+new SharedArrayBuffer(65536);
+setJitCompilerOption('asmjs.atomics.enable', 0)
diff --git a/js/src/jit-test/tests/asm.js/testBug855442.js b/js/src/jit-test/tests/asm.js/testBug855442.js
new file mode 100644
index 000000000..cd95449f0
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug855442.js
@@ -0,0 +1,8 @@
+gczeal(2,4);
+function asmModule(g, foreign, heap) {
+ "use asm";
+ var HEAP8 = new g.Int8Array(heap);
+ function f() {}
+ return {f: f};
+}
+asmModule(this, 2, new ArrayBuffer(2048));
diff --git a/js/src/jit-test/tests/asm.js/testBug863867.js b/js/src/jit-test/tests/asm.js/testBug863867.js
new file mode 100644
index 000000000..4d5a2dce1
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug863867.js
@@ -0,0 +1,34 @@
+assertEq((function() {
+ 'use asm';
+ function _main() {
+ var $1=0, $2=0, $3=0, $4=0, $5=0, $6=0, $7=0, $8=0, $9=0, $10=0, label=0;
+ label = 1;
+ while (1) {
+ switch (label | 0) {
+ case 1:
+ $2 = $1 + 14 | 0;
+ $3 = $1;
+ label = 20;
+ break;
+ case 20:
+ $5 = $2;
+ $4 = $3;
+ label = 24;
+ break;
+ case 24:
+ $7 = $5 + 1 | 0;
+ $8 = $4 + 1 | 0;
+ return $8|0;
+ case 49:
+ $9 = $6 + 1 | 0;
+ if ($10) {
+ $6 = $9;
+ break;
+ }
+ return 0;
+ }
+ }
+ return 0;
+ }
+ return _main;
+})()(), 1);
diff --git a/js/src/jit-test/tests/asm.js/testBug878435.js b/js/src/jit-test/tests/asm.js/testBug878435.js
new file mode 100644
index 000000000..965b28002
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug878435.js
@@ -0,0 +1,11 @@
+function g()
+{
+ "use asm";
+ function f()
+ {
+ return (0 > (0x80000000 | 0)) | 0;
+ }
+ return f;
+}
+
+assertEq(g()(), (0 > (0x80000000 | 0)) | 0);
diff --git a/js/src/jit-test/tests/asm.js/testBug878495.js b/js/src/jit-test/tests/asm.js/testBug878495.js
new file mode 100644
index 000000000..a4c01f4d4
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug878495.js
@@ -0,0 +1,10 @@
+var disassemble = disassemble || false;
+if (disassemble)
+{
+ disassemble("-r", (function() {
+ (function() {
+ "use asm"
+ return {}
+ })()
+ }))
+}
diff --git a/js/src/jit-test/tests/asm.js/testBug878520.js b/js/src/jit-test/tests/asm.js/testBug878520.js
new file mode 100644
index 000000000..fbc335872
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug878520.js
@@ -0,0 +1,9 @@
+function surprise(depth) {
+ arguments.callee.caller(depth);
+}
+
+(function(depth) {
+ function foo() { function asmModule() { 'use asm'; return {} } };
+ if (depth)
+ surprise(depth - 1);
+})(2);
diff --git a/js/src/jit-test/tests/asm.js/testBug892291.js b/js/src/jit-test/tests/asm.js/testBug892291.js
new file mode 100644
index 000000000..9e0ae9761
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug892291.js
@@ -0,0 +1,10 @@
+function a(stdlib) {
+ "use asm";
+ var imul = stdlib.Math.imul;
+ function f() {
+ return ((imul(-800, 0xf8ba1243)|0) % -1)|0;
+ }
+ return f;
+}
+var f = a(this);
+assertEq(f(), 0);
diff --git a/js/src/jit-test/tests/asm.js/testBug893364.js b/js/src/jit-test/tests/asm.js/testBug893364.js
new file mode 100644
index 000000000..8a0eadd35
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug893364.js
@@ -0,0 +1,14 @@
+function m()
+{
+ "use asm";
+ function f()
+ {
+ var x = 0;
+ var y = 0;
+ x = (((0x77777777 - 0xcccccccc) | 0) % -1) | 0;
+ y = (((0x7FFFFFFF + 0x7FFFFFFF) | 0) % -1) | 0;
+ return (x+y)|0;
+ }
+ return f;
+}
+assertEq(m()(), 0)
diff --git a/js/src/jit-test/tests/asm.js/testBug893368.js b/js/src/jit-test/tests/asm.js/testBug893368.js
new file mode 100644
index 000000000..b149390e7
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug893368.js
@@ -0,0 +1,13 @@
+function m(stdlib)
+{
+ "use asm";
+ var abs = stdlib.Math.abs;
+ function f(p)
+ {
+ p = p|0;
+ return ((abs(p|0)|0) % 3)|0;
+ }
+ return f;
+}
+var f = m(this);
+assertEq(f(0x80000000), -2);
diff --git a/js/src/jit-test/tests/asm.js/testBug893519.js b/js/src/jit-test/tests/asm.js/testBug893519.js
new file mode 100644
index 000000000..8995c6e87
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug893519.js
@@ -0,0 +1,11 @@
+// |jit-test| error:Error
+
+if (!isAsmJSCompilationAvailable()) {
+ throw new Error('this test expects an error to be thrown, here it is');
+ quit();
+}
+
+var g = newGlobal();
+evaluate("function h() { function f() { 'use asm'; function g() { return 42 } return g } return f }", { global:g});
+var h = clone(g.h);
+assertEq(h()()(), 42);
diff --git a/js/src/jit-test/tests/asm.js/testBug907085.js b/js/src/jit-test/tests/asm.js/testBug907085.js
new file mode 100644
index 000000000..fb35331df
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug907085.js
@@ -0,0 +1,22 @@
+try {
+ s.e
+} catch (e) {}
+o = o = s2 = /x/
+for (let e in []);
+x = s2
+schedulegc(21)
+eval("x.e=x.t")
+try {
+ (function() {
+ this.eval("\
+ (function(stdlib,fgn,heap) {\
+ \"use asm\";\
+ var Vie = new stdlib.Float64Array(heap);\
+ var Iew = new stdlib.Int8Array(heap);\
+ function f(){\
+ ent\
+ }\
+ })()\
+ ")
+ })()
+} catch (e) {}
diff --git a/js/src/jit-test/tests/asm.js/testBug952022.js b/js/src/jit-test/tests/asm.js/testBug952022.js
new file mode 100644
index 000000000..12f5d71f8
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug952022.js
@@ -0,0 +1,57 @@
+function g(f) {
+ for (var j = 0; j < 9; ++j) {
+ try {
+ f()
+ } catch (e) {}
+ }
+}
+function h(code) {
+ Function(code)();
+}
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+g([]);
+h("\
+ m = (function(stdlib, foreign) { \
+ \"use asm\";\
+ var ff=foreign.ff;\
+ function f(){\
+ ff(0);\
+ } \
+ return f \
+ })(this , { \
+ ff: arguments.callee.caller\
+ });\
+ g(m , []);\
+");
+h("\
+ m = undefined;\
+ gc();\
+")
diff --git a/js/src/jit-test/tests/asm.js/testBug965767.js b/js/src/jit-test/tests/asm.js/testBug965767.js
new file mode 100644
index 000000000..95ddc6522
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug965767.js
@@ -0,0 +1,2098 @@
+var buffer = new ArrayBuffer(4096);
+
+function testmod (glob, env, b) {
+ 'use asm';
+ var f32=new glob.Float32Array(b)
+ function fn1() {
+ f32[0 >> 2]=2.0
+ f32[4 >> 2]=2.125
+ f32[8 >> 2]=2.25
+ f32[12 >> 2]=2.375
+ f32[16 >> 2]=2.5
+ f32[20 >> 2]=2.625
+ f32[24 >> 2]=2.75
+ f32[28 >> 2]=2.875
+ f32[32 >> 2]=3.0
+ f32[36 >> 2]=3.125
+ f32[40 >> 2]=3.25
+ f32[44 >> 2]=3.375
+ f32[48 >> 2]=3.5
+ f32[52 >> 2]=3.625
+ f32[56 >> 2]=3.75
+ f32[60 >> 2]=3.875
+ f32[64 >> 2]=4.0
+ f32[68 >> 2]=4.25
+ f32[72 >> 2]=4.5
+ f32[76 >> 2]=4.75
+ f32[80 >> 2]=5.0
+ f32[84 >> 2]=5.25
+ f32[88 >> 2]=5.5
+ f32[92 >> 2]=5.75
+ f32[96 >> 2]=6.0
+ f32[100 >> 2]=6.25
+ f32[104 >> 2]=6.5
+ f32[108 >> 2]=6.75
+ f32[112 >> 2]=7.0
+ f32[116 >> 2]=7.25
+ f32[120 >> 2]=7.5
+ f32[124 >> 2]=7.75
+ f32[128 >> 2]=8.0
+ f32[132 >> 2]=8.5
+ f32[136 >> 2]=9.0
+ f32[140 >> 2]=9.5
+ f32[144 >> 2]=10.0
+ f32[148 >> 2]=10.5
+ f32[152 >> 2]=11.0
+ f32[156 >> 2]=11.5
+ f32[160 >> 2]=12.0
+ f32[164 >> 2]=12.5
+ f32[168 >> 2]=13.0
+ f32[172 >> 2]=13.5
+ f32[176 >> 2]=14.0
+ f32[180 >> 2]=14.5
+ f32[184 >> 2]=15.0
+ f32[188 >> 2]=15.5
+ f32[192 >> 2]=16.0
+ f32[196 >> 2]=17.0
+ f32[200 >> 2]=18.0
+ f32[204 >> 2]=19.0
+ f32[208 >> 2]=20.0
+ f32[212 >> 2]=21.0
+ f32[216 >> 2]=22.0
+ f32[220 >> 2]=23.0
+ f32[224 >> 2]=24.0
+ f32[228 >> 2]=25.0
+ f32[232 >> 2]=26.0
+ f32[236 >> 2]=27.0
+ f32[240 >> 2]=28.0
+ f32[244 >> 2]=29.0
+ f32[248 >> 2]=30.0
+ f32[252 >> 2]=31.0
+ f32[256 >> 2]=0.125
+ f32[260 >> 2]=0.1328125
+ f32[264 >> 2]=0.140625
+ f32[268 >> 2]=0.1484375
+ f32[272 >> 2]=0.15625
+ f32[276 >> 2]=0.1640625
+ f32[280 >> 2]=0.171875
+ f32[284 >> 2]=0.1796875
+ f32[288 >> 2]=0.1875
+ f32[292 >> 2]=0.1953125
+ f32[296 >> 2]=0.203125
+ f32[300 >> 2]=0.2109375
+ f32[304 >> 2]=0.21875
+ f32[308 >> 2]=0.2265625
+ f32[312 >> 2]=0.234375
+ f32[316 >> 2]=0.2421875
+ f32[320 >> 2]=0.25
+ f32[324 >> 2]=0.265625
+ f32[328 >> 2]=0.28125
+ f32[332 >> 2]=0.296875
+ f32[336 >> 2]=0.3125
+ f32[340 >> 2]=0.328125
+ f32[344 >> 2]=0.34375
+ f32[348 >> 2]=0.359375
+ f32[352 >> 2]=0.375
+ f32[356 >> 2]=0.390625
+ f32[360 >> 2]=0.40625
+ f32[364 >> 2]=0.421875
+ f32[368 >> 2]=0.4375
+ f32[368 >> 2]=0.4375
+ f32[372 >> 2]=0.453125
+ f32[376 >> 2]=0.46875
+ f32[380 >> 2]=0.484375
+ f32[384 >> 2]=0.5
+ f32[388 >> 2]=0.53125
+ f32[392 >> 2]=0.5625
+ f32[396 >> 2]=0.59375
+ f32[400 >> 2]=0.625
+ f32[404 >> 2]=0.65625
+ f32[408 >> 2]=0.6875
+ f32[412 >> 2]=0.71875
+ f32[416 >> 2]=0.75
+ f32[420 >> 2]=0.78125
+ f32[424 >> 2]=0.8125
+ f32[428 >> 2]=0.84375
+ f32[432 >> 2]=0.875
+ f32[436 >> 2]=0.90625
+ f32[440 >> 2]=0.9375
+ f32[444 >> 2]=0.96875
+ f32[448 >> 2]=1.0
+ f32[452 >> 2]=1.0625
+ f32[456 >> 2]=1.125
+ f32[460 >> 2]=1.1875
+ f32[464 >> 2]=1.25
+ f32[468 >> 2]=1.3125
+ f32[472 >> 2]=1.375
+ f32[476 >> 2]=1.4375
+ f32[480 >> 2]=1.5
+ f32[484 >> 2]=1.5625
+ f32[488 >> 2]=1.625
+ f32[492 >> 2]=1.6875
+ f32[496 >> 2]=1.75
+ f32[500 >> 2]=1.8125
+ f32[504 >> 2]=1.875
+ f32[508 >> 2]=1.9375
+ f32[512 >> 2]=-2.0
+ f32[516 >> 2]=-2.125
+ f32[520 >> 2]=-2.25
+ f32[524 >> 2]=-2.375
+ f32[528 >> 2]=-2.5
+ f32[532 >> 2]=-2.625
+ f32[536 >> 2]=-2.75
+ f32[540 >> 2]=-2.875
+ f32[544 >> 2]=-3.0
+ f32[548 >> 2]=-3.125
+ f32[552 >> 2]=-3.25
+ f32[556 >> 2]=-3.375
+ f32[560 >> 2]=-3.5
+ f32[564 >> 2]=-3.625
+ f32[568 >> 2]=-3.75
+ f32[572 >> 2]=-3.875
+ f32[576 >> 2]=-4.0
+ f32[580 >> 2]=-4.25
+ f32[584 >> 2]=-4.5
+ f32[588 >> 2]=-4.75
+ f32[592 >> 2]=-5.0
+ f32[596 >> 2]=-5.25
+ f32[600 >> 2]=-5.5
+ f32[604 >> 2]=-5.75
+ f32[608 >> 2]=-6.0
+ f32[612 >> 2]=-6.25
+ f32[616 >> 2]=-6.5
+ f32[620 >> 2]=-6.75
+ f32[624 >> 2]=-7.0
+ f32[628 >> 2]=-7.25
+ f32[632 >> 2]=-7.5
+ f32[636 >> 2]=-7.75
+ f32[640 >> 2]=-8.0
+ f32[644 >> 2]=-8.5
+ f32[648 >> 2]=-9.0
+ f32[652 >> 2]=-9.5
+ f32[656 >> 2]=-10.0
+ f32[660 >> 2]=-10.5
+ f32[664 >> 2]=-11.0
+ f32[668 >> 2]=-11.5
+ f32[672 >> 2]=-12.0
+ f32[676 >> 2]=-12.5
+ f32[680 >> 2]=-13.0
+ f32[684 >> 2]=-13.5
+ f32[688 >> 2]=-14.0
+ f32[692 >> 2]=-14.5
+ f32[696 >> 2]=-15.0
+ f32[700 >> 2]=-15.5
+ f32[704 >> 2]=-16.0
+ f32[708 >> 2]=-17.0
+ f32[712 >> 2]=-18.0
+ f32[716 >> 2]=-19.0
+ f32[720 >> 2]=-20.0
+ f32[724 >> 2]=-21.0
+ f32[728 >> 2]=-22.0
+ f32[732 >> 2]=-23.0
+ f32[736 >> 2]=-24.0
+ f32[740 >> 2]=-25.0
+ f32[744 >> 2]=-26.0
+ f32[748 >> 2]=-27.0
+ f32[752 >> 2]=-28.0
+ f32[756 >> 2]=-29.0
+ f32[760 >> 2]=-30.0
+ f32[764 >> 2]=-31.0
+ f32[768 >> 2]=-0.125
+ f32[768 >> 2]=-0.125
+ f32[772 >> 2]=-0.1328125
+ f32[776 >> 2]=-0.140625
+ f32[780 >> 2]=-0.1484375
+ f32[784 >> 2]=-0.15625
+ f32[788 >> 2]=-0.1640625
+ f32[792 >> 2]=-0.171875
+ f32[796 >> 2]=-0.1796875
+ f32[800 >> 2]=-0.1875
+ f32[804 >> 2]=-0.1953125
+ f32[808 >> 2]=-0.203125
+ f32[812 >> 2]=-0.2109375
+ f32[816 >> 2]=-0.21875
+ f32[820 >> 2]=-0.2265625
+ f32[824 >> 2]=-0.234375
+ f32[828 >> 2]=-0.2421875
+ f32[832 >> 2]=-0.25
+ f32[836 >> 2]=-0.265625
+ f32[840 >> 2]=-0.28125
+ f32[844 >> 2]=-0.296875
+ f32[848 >> 2]=-0.3125
+ f32[852 >> 2]=-0.328125
+ f32[856 >> 2]=-0.34375
+ f32[860 >> 2]=-0.359375
+ f32[864 >> 2]=-0.375
+ f32[868 >> 2]=-0.390625
+ f32[872 >> 2]=-0.40625
+ f32[876 >> 2]=-0.421875
+ f32[880 >> 2]=-0.4375
+ f32[884 >> 2]=-0.453125
+ f32[888 >> 2]=-0.46875
+ f32[892 >> 2]=-0.484375
+ f32[896 >> 2]=-0.5
+ f32[900 >> 2]=-0.53125
+ f32[904 >> 2]=-0.5625
+ f32[908 >> 2]=-0.59375
+ f32[912 >> 2]=-0.625
+ f32[916 >> 2]=-0.65625
+ f32[920 >> 2]=-0.6875
+ f32[924 >> 2]=-0.71875
+ f32[928 >> 2]=-0.75
+ f32[932 >> 2]=-0.78125
+ f32[936 >> 2]=-0.8125
+ f32[940 >> 2]=-0.84375
+ f32[944 >> 2]=-0.875
+ f32[948 >> 2]=-0.90625
+ f32[952 >> 2]=-0.9375
+ f32[956 >> 2]=-0.96875
+ f32[960 >> 2]=-1.0
+ f32[964 >> 2]=-1.0625
+ f32[968 >> 2]=-1.125
+ f32[972 >> 2]=-1.1875
+ f32[976 >> 2]=-1.25
+ f32[980 >> 2]=-1.3125
+ f32[984 >> 2]=-1.375
+ f32[988 >> 2]=-1.4375
+ f32[992 >> 2]=-1.5
+ f32[996 >> 2]=-1.5625
+ f32[1000 >> 2]=-1.625
+ f32[1004 >> 2]=-1.6875
+ f32[1008 >> 2]=-1.75
+ f32[1012 >> 2]=-1.8125
+ f32[1016 >> 2]=-1.875
+ f32[1020 >> 2]=-1.9375
+
+ // Some cases that should not be encoded as an immediate on the ARM.
+
+ // All the low zero bits set.
+ f32[1024 >> 2]=2.1249998
+ f32[1028 >> 2]=2.2499998
+ f32[1032 >> 2]=2.3749998
+ f32[1036 >> 2]=2.4999998
+ f32[1040 >> 2]=2.6249998
+ f32[1044 >> 2]=2.7499998
+ f32[1048 >> 2]=2.8749998
+ f32[1052 >> 2]=2.9999998
+ f32[1056 >> 2]=3.1249998
+ f32[1060 >> 2]=3.2499998
+ f32[1064 >> 2]=3.3749998
+ f32[1068 >> 2]=3.4999998
+ f32[1072 >> 2]=3.6249998
+ f32[1076 >> 2]=3.7499998
+ f32[1080 >> 2]=3.8749998
+ f32[1084 >> 2]=3.9999998
+ f32[1088 >> 2]=4.2499995
+ f32[1092 >> 2]=4.4999995
+ f32[1096 >> 2]=4.7499995
+ f32[1100 >> 2]=4.9999995
+ f32[1104 >> 2]=5.2499995
+ f32[1108 >> 2]=5.4999995
+ f32[1112 >> 2]=5.7499995
+ f32[1116 >> 2]=5.9999995
+ f32[1120 >> 2]=6.2499995
+ f32[1124 >> 2]=6.4999995
+ f32[1128 >> 2]=6.7499995
+ f32[1132 >> 2]=6.9999995
+ f32[1136 >> 2]=7.2499995
+ f32[1140 >> 2]=7.4999995
+ f32[1144 >> 2]=7.7499995
+ f32[1148 >> 2]=7.9999995
+ f32[1152 >> 2]=8.499999
+ f32[1156 >> 2]=8.999999
+ f32[1160 >> 2]=9.499999
+ f32[1164 >> 2]=9.999999
+ f32[1168 >> 2]=10.499999
+ f32[1172 >> 2]=10.999999
+ f32[1176 >> 2]=11.499999
+ f32[1180 >> 2]=11.999999
+ f32[1184 >> 2]=12.499999
+ f32[1188 >> 2]=12.999999
+ f32[1192 >> 2]=13.499999
+ f32[1196 >> 2]=13.999999
+ f32[1200 >> 2]=14.499999
+ f32[1204 >> 2]=14.999999
+ f32[1208 >> 2]=15.499999
+ f32[1212 >> 2]=15.999999
+ f32[1216 >> 2]=16.999998
+ f32[1220 >> 2]=17.999998
+ f32[1224 >> 2]=18.999998
+ f32[1228 >> 2]=19.999998
+ f32[1232 >> 2]=20.999998
+ f32[1236 >> 2]=21.999998
+ f32[1240 >> 2]=22.999998
+ f32[1244 >> 2]=23.999998
+ f32[1248 >> 2]=24.999998
+ f32[1252 >> 2]=25.999998
+ f32[1256 >> 2]=26.999998
+ f32[1260 >> 2]=27.999998
+ f32[1264 >> 2]=28.999998
+ f32[1268 >> 2]=29.999998
+ f32[1272 >> 2]=30.999998
+ f32[1276 >> 2]=31.999998
+ f32[1280 >> 2]=0.13281249
+ f32[1284 >> 2]=0.14062499
+ f32[1288 >> 2]=0.14843749
+ f32[1292 >> 2]=0.15624999
+ f32[1296 >> 2]=0.16406249
+ f32[1300 >> 2]=0.17187499
+ f32[1304 >> 2]=0.17968749
+ f32[1308 >> 2]=0.18749999
+ f32[1312 >> 2]=0.19531249
+ f32[1316 >> 2]=0.20312499
+ f32[1320 >> 2]=0.21093749
+ f32[1324 >> 2]=0.21874999
+ f32[1328 >> 2]=0.22656249
+ f32[1332 >> 2]=0.23437499
+ f32[1336 >> 2]=0.24218749
+ f32[1340 >> 2]=0.24999999
+ f32[1344 >> 2]=0.26562497
+ f32[1348 >> 2]=0.28124997
+ f32[1352 >> 2]=0.29687497
+ f32[1356 >> 2]=0.31249997
+ f32[1360 >> 2]=0.32812497
+ f32[1364 >> 2]=0.34374997
+ f32[1368 >> 2]=0.35937497
+ f32[1372 >> 2]=0.37499997
+ f32[1376 >> 2]=0.39062497
+ f32[1380 >> 2]=0.40624997
+ f32[1384 >> 2]=0.42187497
+ f32[1388 >> 2]=0.43749997
+ f32[1392 >> 2]=0.45312497
+ f32[1396 >> 2]=0.46874997
+ f32[1400 >> 2]=0.48437497
+ f32[1404 >> 2]=0.49999997
+ f32[1408 >> 2]=0.53124994
+ f32[1412 >> 2]=0.56249994
+ f32[1416 >> 2]=0.59374994
+ f32[1420 >> 2]=0.62499994
+ f32[1424 >> 2]=0.65624994
+ f32[1428 >> 2]=0.68749994
+ f32[1432 >> 2]=0.71874994
+ f32[1436 >> 2]=0.74999994
+ f32[1440 >> 2]=0.78124994
+ f32[1444 >> 2]=0.81249994
+ f32[1448 >> 2]=0.84374994
+ f32[1452 >> 2]=0.87499994
+ f32[1456 >> 2]=0.90624994
+ f32[1460 >> 2]=0.93749994
+ f32[1464 >> 2]=0.96874994
+ f32[1468 >> 2]=0.99999994
+ f32[1472 >> 2]=1.0624999
+ f32[1476 >> 2]=1.1249999
+ f32[1480 >> 2]=1.1874999
+ f32[1484 >> 2]=1.2499999
+ f32[1488 >> 2]=1.3124999
+ f32[1488 >> 2]=1.3124999
+ f32[1492 >> 2]=1.3749999
+ f32[1496 >> 2]=1.4374999
+ f32[1500 >> 2]=1.4999999
+ f32[1504 >> 2]=1.5624999
+ f32[1508 >> 2]=1.6249999
+ f32[1512 >> 2]=1.6874999
+ f32[1516 >> 2]=1.7499999
+ f32[1520 >> 2]=1.8124999
+ f32[1524 >> 2]=1.8749999
+ f32[1528 >> 2]=1.9374999
+ f32[1532 >> 2]=1.9999999
+ f32[1536 >> 2]=-2.1249998
+ f32[1540 >> 2]=-2.2499998
+ f32[1544 >> 2]=-2.3749998
+ f32[1548 >> 2]=-2.4999998
+ f32[1552 >> 2]=-2.6249998
+ f32[1556 >> 2]=-2.7499998
+ f32[1560 >> 2]=-2.8749998
+ f32[1564 >> 2]=-2.9999998
+ f32[1568 >> 2]=-3.1249998
+ f32[1572 >> 2]=-3.2499998
+ f32[1576 >> 2]=-3.3749998
+ f32[1580 >> 2]=-3.4999998
+ f32[1584 >> 2]=-3.6249998
+ f32[1588 >> 2]=-3.7499998
+ f32[1592 >> 2]=-3.8749998
+ f32[1596 >> 2]=-3.9999998
+ f32[1600 >> 2]=-4.2499995
+ f32[1604 >> 2]=-4.4999995
+ f32[1608 >> 2]=-4.7499995
+ f32[1612 >> 2]=-4.9999995
+ f32[1616 >> 2]=-5.2499995
+ f32[1620 >> 2]=-5.4999995
+ f32[1624 >> 2]=-5.7499995
+ f32[1628 >> 2]=-5.9999995
+ f32[1632 >> 2]=-6.2499995
+ f32[1636 >> 2]=-6.4999995
+ f32[1640 >> 2]=-6.7499995
+ f32[1644 >> 2]=-6.9999995
+ f32[1648 >> 2]=-7.2499995
+ f32[1652 >> 2]=-7.4999995
+ f32[1656 >> 2]=-7.7499995
+ f32[1660 >> 2]=-7.9999995
+ f32[1664 >> 2]=-8.499999
+ f32[1668 >> 2]=-8.999999
+ f32[1672 >> 2]=-9.499999
+ f32[1676 >> 2]=-9.999999
+ f32[1680 >> 2]=-10.499999
+ f32[1684 >> 2]=-10.999999
+ f32[1688 >> 2]=-11.499999
+ f32[1692 >> 2]=-11.999999
+ f32[1696 >> 2]=-12.499999
+ f32[1700 >> 2]=-12.999999
+ f32[1704 >> 2]=-13.499999
+ f32[1708 >> 2]=-13.999999
+ f32[1712 >> 2]=-14.499999
+ f32[1716 >> 2]=-14.999999
+ f32[1720 >> 2]=-15.499999
+ f32[1724 >> 2]=-15.999999
+ f32[1728 >> 2]=-16.999998
+ f32[1732 >> 2]=-17.999998
+ f32[1736 >> 2]=-18.999998
+ f32[1740 >> 2]=-19.999998
+ f32[1744 >> 2]=-20.999998
+ f32[1748 >> 2]=-21.999998
+ f32[1752 >> 2]=-22.999998
+ f32[1756 >> 2]=-23.999998
+ f32[1760 >> 2]=-24.999998
+ f32[1764 >> 2]=-25.999998
+ f32[1768 >> 2]=-26.999998
+ f32[1772 >> 2]=-27.999998
+ f32[1776 >> 2]=-28.999998
+ f32[1780 >> 2]=-29.999998
+ f32[1784 >> 2]=-30.999998
+ f32[1788 >> 2]=-31.999998
+ f32[1792 >> 2]=-0.13281249
+ f32[1796 >> 2]=-0.14062499
+ f32[1800 >> 2]=-0.14843749
+ f32[1804 >> 2]=-0.15624999
+ f32[1808 >> 2]=-0.16406249
+ f32[1812 >> 2]=-0.17187499
+ f32[1816 >> 2]=-0.17968749
+ f32[1820 >> 2]=-0.18749999
+ f32[1824 >> 2]=-0.19531249
+ f32[1828 >> 2]=-0.20312499
+ f32[1832 >> 2]=-0.21093749
+ f32[1836 >> 2]=-0.21874999
+ f32[1840 >> 2]=-0.22656249
+ f32[1844 >> 2]=-0.23437499
+ f32[1848 >> 2]=-0.24218749
+ f32[1852 >> 2]=-0.24999999
+ f32[1856 >> 2]=-0.26562497
+ f32[1860 >> 2]=-0.28124997
+ f32[1864 >> 2]=-0.29687497
+ f32[1868 >> 2]=-0.31249997
+ f32[1872 >> 2]=-0.32812497
+ f32[1876 >> 2]=-0.34374997
+ f32[1880 >> 2]=-0.35937497
+ f32[1884 >> 2]=-0.37499997
+ f32[1888 >> 2]=-0.39062497
+ f32[1888 >> 2]=-0.39062497
+ f32[1892 >> 2]=-0.40624997
+ f32[1896 >> 2]=-0.42187497
+ f32[1900 >> 2]=-0.43749997
+ f32[1904 >> 2]=-0.45312497
+ f32[1908 >> 2]=-0.46874997
+ f32[1912 >> 2]=-0.48437497
+ f32[1916 >> 2]=-0.49999997
+ f32[1920 >> 2]=-0.53124994
+ f32[1924 >> 2]=-0.56249994
+ f32[1928 >> 2]=-0.59374994
+ f32[1932 >> 2]=-0.62499994
+ f32[1936 >> 2]=-0.65624994
+ f32[1940 >> 2]=-0.68749994
+ f32[1944 >> 2]=-0.71874994
+ f32[1948 >> 2]=-0.74999994
+ f32[1952 >> 2]=-0.78124994
+ f32[1956 >> 2]=-0.81249994
+ f32[1960 >> 2]=-0.84374994
+ f32[1964 >> 2]=-0.87499994
+ f32[1968 >> 2]=-0.90624994
+ f32[1972 >> 2]=-0.93749994
+ f32[1976 >> 2]=-0.96874994
+ f32[1980 >> 2]=-0.99999994
+ f32[1984 >> 2]=-1.0624999
+ f32[1988 >> 2]=-1.1249999
+ f32[1992 >> 2]=-1.1874999
+ f32[1996 >> 2]=-1.2499999
+ f32[2000 >> 2]=-1.3124999
+ f32[2004 >> 2]=-1.3749999
+ f32[2008 >> 2]=-1.4374999
+ f32[2012 >> 2]=-1.4999999
+ f32[2016 >> 2]=-1.5624999
+ f32[2020 >> 2]=-1.6249999
+ f32[2024 >> 2]=-1.6874999
+ f32[2028 >> 2]=-1.7499999
+ f32[2032 >> 2]=-1.8124999
+ f32[2036 >> 2]=-1.8749999
+ f32[2040 >> 2]=-1.9374999
+ f32[2044 >> 2]=-1.9999999
+
+ // Just the lowest zero bit set.
+ f32[2048 >> 2]=2.0000002
+ f32[2052 >> 2]=2.1250002
+ f32[2056 >> 2]=2.2500002
+ f32[2060 >> 2]=2.3750002
+ f32[2064 >> 2]=2.5000002
+ f32[2068 >> 2]=2.6250002
+ f32[2072 >> 2]=2.7500002
+ f32[2076 >> 2]=2.8750002
+ f32[2080 >> 2]=3.0000002
+ f32[2084 >> 2]=3.1250002
+ f32[2088 >> 2]=3.2500002
+ f32[2092 >> 2]=3.3750002
+ f32[2096 >> 2]=3.5000002
+ f32[2100 >> 2]=3.6250002
+ f32[2104 >> 2]=3.7500002
+ f32[2108 >> 2]=3.8750002
+ f32[2112 >> 2]=4.0000005
+ f32[2116 >> 2]=4.2500005
+ f32[2120 >> 2]=4.5000005
+ f32[2124 >> 2]=4.7500005
+ f32[2128 >> 2]=5.0000005
+ f32[2132 >> 2]=5.2500005
+ f32[2136 >> 2]=5.5000005
+ f32[2140 >> 2]=5.7500005
+ f32[2140 >> 2]=5.7500005
+ f32[2144 >> 2]=6.0000005
+ f32[2148 >> 2]=6.2500005
+ f32[2152 >> 2]=6.5000005
+ f32[2156 >> 2]=6.7500005
+ f32[2160 >> 2]=7.0000005
+ f32[2164 >> 2]=7.2500005
+ f32[2168 >> 2]=7.5000005
+ f32[2172 >> 2]=7.7500005
+ f32[2176 >> 2]=8.000001
+ f32[2180 >> 2]=8.500001
+ f32[2184 >> 2]=9.000001
+ f32[2188 >> 2]=9.500001
+ f32[2192 >> 2]=10.000001
+ f32[2196 >> 2]=10.500001
+ f32[2200 >> 2]=11.000001
+ f32[2204 >> 2]=11.500001
+ f32[2208 >> 2]=12.000001
+ f32[2212 >> 2]=12.500001
+ f32[2216 >> 2]=13.000001
+ f32[2220 >> 2]=13.500001
+ f32[2224 >> 2]=14.000001
+ f32[2228 >> 2]=14.500001
+ f32[2232 >> 2]=15.000001
+ f32[2236 >> 2]=15.500001
+ f32[2240 >> 2]=16.000002
+ f32[2244 >> 2]=17.000002
+ f32[2248 >> 2]=18.000002
+ f32[2252 >> 2]=19.000002
+ f32[2256 >> 2]=20.000002
+ f32[2260 >> 2]=21.000002
+ f32[2264 >> 2]=22.000002
+ f32[2268 >> 2]=23.000002
+ f32[2272 >> 2]=24.000002
+ f32[2276 >> 2]=25.000002
+ f32[2280 >> 2]=26.000002
+ f32[2284 >> 2]=27.000002
+ f32[2288 >> 2]=28.000002
+ f32[2292 >> 2]=29.000002
+ f32[2296 >> 2]=30.000002
+ f32[2300 >> 2]=31.000002
+ f32[2304 >> 2]=0.12500001
+ f32[2308 >> 2]=0.13281251
+ f32[2312 >> 2]=0.14062501
+ f32[2316 >> 2]=0.14843751
+ f32[2320 >> 2]=0.15625001
+ f32[2324 >> 2]=0.16406251
+ f32[2328 >> 2]=0.17187501
+ f32[2332 >> 2]=0.17968751
+ f32[2336 >> 2]=0.18750001
+ f32[2340 >> 2]=0.19531251
+ f32[2344 >> 2]=0.20312501
+ f32[2348 >> 2]=0.21093751
+ f32[2352 >> 2]=0.21875001
+ f32[2356 >> 2]=0.22656251
+ f32[2360 >> 2]=0.23437501
+ f32[2364 >> 2]=0.24218751
+ f32[2368 >> 2]=0.25000003
+ f32[2372 >> 2]=0.26562503
+ f32[2376 >> 2]=0.28125003
+ f32[2380 >> 2]=0.29687503
+ f32[2384 >> 2]=0.31250003
+ f32[2388 >> 2]=0.32812503
+ f32[2392 >> 2]=0.34375003
+ f32[2396 >> 2]=0.35937503
+ f32[2400 >> 2]=0.37500003
+ f32[2404 >> 2]=0.39062503
+ f32[2408 >> 2]=0.40625003
+ f32[2412 >> 2]=0.42187503
+ f32[2416 >> 2]=0.43750003
+ f32[2420 >> 2]=0.45312503
+ f32[2424 >> 2]=0.46875003
+ f32[2428 >> 2]=0.48437503
+ f32[2432 >> 2]=0.50000006
+ f32[2436 >> 2]=0.53125006
+ f32[2440 >> 2]=0.56250006
+ f32[2444 >> 2]=0.59375006
+ f32[2448 >> 2]=0.62500006
+ f32[2452 >> 2]=0.65625006
+ f32[2456 >> 2]=0.68750006
+ f32[2460 >> 2]=0.71875006
+ f32[2464 >> 2]=0.75000006
+ f32[2468 >> 2]=0.78125006
+ f32[2472 >> 2]=0.81250006
+ f32[2476 >> 2]=0.84375006
+ f32[2480 >> 2]=0.87500006
+ f32[2484 >> 2]=0.90625006
+ f32[2488 >> 2]=0.93750006
+ f32[2492 >> 2]=0.96875006
+ f32[2496 >> 2]=1.0000001
+ f32[2500 >> 2]=1.0625001
+ f32[2504 >> 2]=1.1250001
+ f32[2508 >> 2]=1.1875001
+ f32[2512 >> 2]=1.2500001
+ f32[2516 >> 2]=1.3125001
+ f32[2520 >> 2]=1.3750001
+ f32[2524 >> 2]=1.4375001
+ f32[2528 >> 2]=1.5000001
+ f32[2532 >> 2]=1.5625001
+ f32[2536 >> 2]=1.6250001
+ f32[2540 >> 2]=1.6875001
+ f32[2540 >> 2]=1.6875001
+ f32[2544 >> 2]=1.7500001
+ f32[2548 >> 2]=1.8125001
+ f32[2552 >> 2]=1.8750001
+ f32[2556 >> 2]=1.9375001
+ f32[2560 >> 2]=-2.0000002
+ f32[2564 >> 2]=-2.1250002
+ f32[2568 >> 2]=-2.2500002
+ f32[2572 >> 2]=-2.3750002
+ f32[2576 >> 2]=-2.5000002
+ f32[2580 >> 2]=-2.6250002
+ f32[2584 >> 2]=-2.7500002
+ f32[2588 >> 2]=-2.8750002
+ f32[2592 >> 2]=-3.0000002
+ f32[2596 >> 2]=-3.1250002
+ f32[2600 >> 2]=-3.2500002
+ f32[2604 >> 2]=-3.3750002
+ f32[2608 >> 2]=-3.5000002
+ f32[2612 >> 2]=-3.6250002
+ f32[2616 >> 2]=-3.7500002
+ f32[2620 >> 2]=-3.8750002
+ f32[2624 >> 2]=-4.0000005
+ f32[2628 >> 2]=-4.2500005
+ f32[2632 >> 2]=-4.5000005
+ f32[2636 >> 2]=-4.7500005
+ f32[2640 >> 2]=-5.0000005
+ f32[2644 >> 2]=-5.2500005
+ f32[2648 >> 2]=-5.5000005
+ f32[2652 >> 2]=-5.7500005
+ f32[2656 >> 2]=-6.0000005
+ f32[2660 >> 2]=-6.2500005
+ f32[2664 >> 2]=-6.5000005
+ f32[2668 >> 2]=-6.7500005
+ f32[2672 >> 2]=-7.0000005
+ f32[2676 >> 2]=-7.2500005
+ f32[2680 >> 2]=-7.5000005
+ f32[2684 >> 2]=-7.7500005
+ f32[2688 >> 2]=-8.000001
+ f32[2692 >> 2]=-8.500001
+ f32[2696 >> 2]=-9.000001
+ f32[2700 >> 2]=-9.500001
+ f32[2704 >> 2]=-10.000001
+ f32[2708 >> 2]=-10.500001
+ f32[2712 >> 2]=-11.000001
+ f32[2716 >> 2]=-11.500001
+ f32[2720 >> 2]=-12.000001
+ f32[2724 >> 2]=-12.500001
+ f32[2728 >> 2]=-13.000001
+ f32[2732 >> 2]=-13.500001
+ f32[2736 >> 2]=-14.000001
+ f32[2740 >> 2]=-14.500001
+ f32[2744 >> 2]=-15.000001
+ f32[2748 >> 2]=-15.500001
+ f32[2752 >> 2]=-16.000002
+ f32[2756 >> 2]=-17.000002
+ f32[2760 >> 2]=-18.000002
+ f32[2764 >> 2]=-19.000002
+ f32[2768 >> 2]=-20.000002
+ f32[2772 >> 2]=-21.000002
+ f32[2776 >> 2]=-22.000002
+ f32[2780 >> 2]=-23.000002
+ f32[2784 >> 2]=-24.000002
+ f32[2788 >> 2]=-25.000002
+ f32[2792 >> 2]=-26.000002
+ f32[2796 >> 2]=-27.000002
+ f32[2800 >> 2]=-28.000002
+ f32[2804 >> 2]=-29.000002
+ f32[2808 >> 2]=-30.000002
+ f32[2812 >> 2]=-31.000002
+ f32[2816 >> 2]=-0.12500001
+ f32[2820 >> 2]=-0.13281251
+ f32[2824 >> 2]=-0.14062501
+ f32[2828 >> 2]=-0.14843751
+ f32[2832 >> 2]=-0.15625001
+ f32[2836 >> 2]=-0.16406251
+ f32[2840 >> 2]=-0.17187501
+ f32[2844 >> 2]=-0.17968751
+ f32[2848 >> 2]=-0.18750001
+ f32[2852 >> 2]=-0.19531251
+ f32[2856 >> 2]=-0.20312501
+ f32[2860 >> 2]=-0.21093751
+ f32[2864 >> 2]=-0.21875001
+ f32[2868 >> 2]=-0.22656251
+ f32[2872 >> 2]=-0.23437501
+ f32[2876 >> 2]=-0.24218751
+ f32[2880 >> 2]=-0.25000003
+ f32[2884 >> 2]=-0.26562503
+ f32[2888 >> 2]=-0.28125003
+ f32[2892 >> 2]=-0.29687503
+ f32[2896 >> 2]=-0.31250003
+ f32[2900 >> 2]=-0.32812503
+ f32[2904 >> 2]=-0.34375003
+ f32[2908 >> 2]=-0.35937503
+ f32[2912 >> 2]=-0.37500003
+ f32[2916 >> 2]=-0.39062503
+ f32[2920 >> 2]=-0.40625003
+ f32[2924 >> 2]=-0.42187503
+ f32[2928 >> 2]=-0.43750003
+ f32[2932 >> 2]=-0.45312503
+ f32[2936 >> 2]=-0.46875003
+ f32[2940 >> 2]=-0.48437503
+ f32[2940 >> 2]=-0.48437503
+ f32[2944 >> 2]=-0.50000006
+ f32[2948 >> 2]=-0.53125006
+ f32[2952 >> 2]=-0.56250006
+ f32[2956 >> 2]=-0.59375006
+ f32[2960 >> 2]=-0.62500006
+ f32[2964 >> 2]=-0.65625006
+ f32[2968 >> 2]=-0.68750006
+ f32[2972 >> 2]=-0.71875006
+ f32[2976 >> 2]=-0.75000006
+ f32[2980 >> 2]=-0.78125006
+ f32[2984 >> 2]=-0.81250006
+ f32[2988 >> 2]=-0.84375006
+ f32[2992 >> 2]=-0.87500006
+ f32[2996 >> 2]=-0.90625006
+ f32[3000 >> 2]=-0.93750006
+ f32[3004 >> 2]=-0.96875006
+ f32[3008 >> 2]=-1.0000001
+ f32[3012 >> 2]=-1.0625001
+ f32[3016 >> 2]=-1.1250001
+ f32[3020 >> 2]=-1.1875001
+ f32[3024 >> 2]=-1.2500001
+ f32[3028 >> 2]=-1.3125001
+ f32[3032 >> 2]=-1.3750001
+ f32[3036 >> 2]=-1.4375001
+ f32[3040 >> 2]=-1.5000001
+ f32[3044 >> 2]=-1.5625001
+ f32[3048 >> 2]=-1.6250001
+ f32[3052 >> 2]=-1.6875001
+ f32[3056 >> 2]=-1.7500001
+ f32[3060 >> 2]=-1.8125001
+ f32[3064 >> 2]=-1.8750001
+ f32[3068 >> 2]=-1.9375001
+
+ // Just the highest zero bit set.
+ f32[3073 >> 2]=2.0625
+ f32[3073 >> 2]=2.0625
+ f32[3077 >> 2]=2.1875
+ f32[3081 >> 2]=2.3125
+ f32[3085 >> 2]=2.4375
+ f32[3089 >> 2]=2.5625
+ f32[3093 >> 2]=2.6875
+ f32[3097 >> 2]=2.8125
+ f32[3101 >> 2]=2.9375
+ f32[3105 >> 2]=3.0625
+ f32[3109 >> 2]=3.1875
+ f32[3113 >> 2]=3.3125
+ f32[3117 >> 2]=3.4375
+ f32[3121 >> 2]=3.5625
+ f32[3125 >> 2]=3.6875
+ f32[3129 >> 2]=3.8125
+ f32[3133 >> 2]=3.9375
+ f32[3137 >> 2]=4.125
+ f32[3141 >> 2]=4.375
+ f32[3145 >> 2]=4.625
+ f32[3149 >> 2]=4.875
+ f32[3153 >> 2]=5.125
+ f32[3157 >> 2]=5.375
+ f32[3161 >> 2]=5.625
+ f32[3165 >> 2]=5.875
+ f32[3169 >> 2]=6.125
+ f32[3173 >> 2]=6.375
+ f32[3177 >> 2]=6.625
+ f32[3181 >> 2]=6.875
+ f32[3185 >> 2]=7.125
+ f32[3189 >> 2]=7.375
+ f32[3193 >> 2]=7.625
+ f32[3197 >> 2]=7.875
+ f32[3201 >> 2]=8.25
+ f32[3205 >> 2]=8.75
+ f32[3209 >> 2]=9.25
+ f32[3213 >> 2]=9.75
+ f32[3217 >> 2]=10.25
+ f32[3221 >> 2]=10.75
+ f32[3225 >> 2]=11.25
+ f32[3229 >> 2]=11.75
+ f32[3233 >> 2]=12.25
+ f32[3237 >> 2]=12.75
+ f32[3241 >> 2]=13.25
+ f32[3245 >> 2]=13.75
+ f32[3249 >> 2]=14.25
+ f32[3253 >> 2]=14.75
+ f32[3257 >> 2]=15.25
+ f32[3261 >> 2]=15.75
+ f32[3265 >> 2]=16.5
+ f32[3269 >> 2]=17.5
+ f32[3273 >> 2]=18.5
+ f32[3277 >> 2]=19.5
+ f32[3281 >> 2]=20.5
+ f32[3285 >> 2]=21.5
+ f32[3289 >> 2]=22.5
+ f32[3293 >> 2]=23.5
+ f32[3297 >> 2]=24.5
+ f32[3301 >> 2]=25.5
+ f32[3305 >> 2]=26.5
+ f32[3309 >> 2]=27.5
+ f32[3313 >> 2]=28.5
+ f32[3317 >> 2]=29.5
+ f32[3321 >> 2]=30.5
+ f32[3325 >> 2]=31.5
+ f32[3329 >> 2]=0.12890625
+ f32[3333 >> 2]=0.13671875
+ f32[3337 >> 2]=0.14453125
+ f32[3341 >> 2]=0.15234375
+ f32[3345 >> 2]=0.16015625
+ f32[3349 >> 2]=0.16796875
+ f32[3353 >> 2]=0.17578125
+ f32[3357 >> 2]=0.18359375
+ f32[3361 >> 2]=0.19140625
+ f32[3365 >> 2]=0.19921875
+ f32[3369 >> 2]=0.20703125
+ f32[3373 >> 2]=0.21484375
+ f32[3377 >> 2]=0.22265625
+ f32[3381 >> 2]=0.23046875
+ f32[3385 >> 2]=0.23828125
+ f32[3389 >> 2]=0.24609375
+ f32[3393 >> 2]=0.2578125
+ f32[3397 >> 2]=0.2734375
+ f32[3401 >> 2]=0.2890625
+ f32[3405 >> 2]=0.3046875
+ f32[3409 >> 2]=0.3203125
+ f32[3413 >> 2]=0.3359375
+ f32[3417 >> 2]=0.3515625
+ f32[3421 >> 2]=0.3671875
+ f32[3425 >> 2]=0.3828125
+ f32[3429 >> 2]=0.3984375
+ f32[3433 >> 2]=0.4140625
+ f32[3437 >> 2]=0.4296875
+ f32[3441 >> 2]=0.4453125
+ f32[3445 >> 2]=0.4609375
+ f32[3449 >> 2]=0.4765625
+ f32[3453 >> 2]=0.4921875
+ f32[3457 >> 2]=0.515625
+ f32[3461 >> 2]=0.546875
+ f32[3465 >> 2]=0.578125
+ f32[3469 >> 2]=0.609375
+ f32[3473 >> 2]=0.640625
+ f32[3473 >> 2]=0.640625
+ f32[3477 >> 2]=0.671875
+ f32[3481 >> 2]=0.703125
+ f32[3485 >> 2]=0.734375
+ f32[3489 >> 2]=0.765625
+ f32[3493 >> 2]=0.796875
+ f32[3497 >> 2]=0.828125
+ f32[3501 >> 2]=0.859375
+ f32[3505 >> 2]=0.890625
+ f32[3509 >> 2]=0.921875
+ f32[3513 >> 2]=0.953125
+ f32[3517 >> 2]=0.984375
+ f32[3521 >> 2]=1.03125
+ f32[3525 >> 2]=1.09375
+ f32[3529 >> 2]=1.15625
+ f32[3533 >> 2]=1.21875
+ f32[3537 >> 2]=1.28125
+ f32[3541 >> 2]=1.34375
+ f32[3545 >> 2]=1.40625
+ f32[3549 >> 2]=1.46875
+ f32[3553 >> 2]=1.53125
+ f32[3557 >> 2]=1.59375
+ f32[3561 >> 2]=1.65625
+ f32[3565 >> 2]=1.71875
+ f32[3569 >> 2]=1.78125
+ f32[3573 >> 2]=1.84375
+ f32[3577 >> 2]=1.90625
+ f32[3581 >> 2]=1.96875
+ f32[3585 >> 2]=-2.0625
+ f32[3589 >> 2]=-2.1875
+ f32[3593 >> 2]=-2.3125
+ f32[3597 >> 2]=-2.4375
+ f32[3601 >> 2]=-2.5625
+ f32[3605 >> 2]=-2.6875
+ f32[3609 >> 2]=-2.8125
+ f32[3613 >> 2]=-2.9375
+ f32[3617 >> 2]=-3.0625
+ f32[3621 >> 2]=-3.1875
+ f32[3625 >> 2]=-3.3125
+ f32[3629 >> 2]=-3.4375
+ f32[3633 >> 2]=-3.5625
+ f32[3637 >> 2]=-3.6875
+ f32[3641 >> 2]=-3.8125
+ f32[3645 >> 2]=-3.9375
+ f32[3649 >> 2]=-4.125
+ f32[3653 >> 2]=-4.375
+ f32[3657 >> 2]=-4.625
+ f32[3661 >> 2]=-4.875
+ f32[3665 >> 2]=-5.125
+ f32[3669 >> 2]=-5.375
+ f32[3673 >> 2]=-5.625
+ f32[3677 >> 2]=-5.875
+ f32[3681 >> 2]=-6.125
+ f32[3685 >> 2]=-6.375
+ f32[3689 >> 2]=-6.625
+ f32[3693 >> 2]=-6.875
+ f32[3697 >> 2]=-7.125
+ f32[3701 >> 2]=-7.375
+ f32[3705 >> 2]=-7.625
+ f32[3709 >> 2]=-7.875
+ f32[3713 >> 2]=-8.25
+ f32[3717 >> 2]=-8.75
+ f32[3721 >> 2]=-9.25
+ f32[3725 >> 2]=-9.75
+ f32[3729 >> 2]=-10.25
+ f32[3733 >> 2]=-10.75
+ f32[3737 >> 2]=-11.25
+ f32[3741 >> 2]=-11.75
+ f32[3745 >> 2]=-12.25
+ f32[3749 >> 2]=-12.75
+ f32[3753 >> 2]=-13.25
+ f32[3757 >> 2]=-13.75
+ f32[3761 >> 2]=-14.25
+ f32[3765 >> 2]=-14.75
+ f32[3769 >> 2]=-15.25
+ f32[3773 >> 2]=-15.75
+ f32[3777 >> 2]=-16.5
+ f32[3781 >> 2]=-17.5
+ f32[3785 >> 2]=-18.5
+ f32[3789 >> 2]=-19.5
+ f32[3793 >> 2]=-20.5
+ f32[3797 >> 2]=-21.5
+ f32[3801 >> 2]=-22.5
+ f32[3805 >> 2]=-23.5
+ f32[3809 >> 2]=-24.5
+ f32[3813 >> 2]=-25.5
+ f32[3817 >> 2]=-26.5
+ f32[3821 >> 2]=-27.5
+ f32[3825 >> 2]=-28.5
+ f32[3829 >> 2]=-29.5
+ f32[3833 >> 2]=-30.5
+ f32[3837 >> 2]=-31.5
+ f32[3841 >> 2]=-0.12890625
+ f32[3845 >> 2]=-0.13671875
+ f32[3849 >> 2]=-0.14453125
+ f32[3853 >> 2]=-0.15234375
+ f32[3857 >> 2]=-0.16015625
+ f32[3861 >> 2]=-0.16796875
+ f32[3865 >> 2]=-0.17578125
+ f32[3869 >> 2]=-0.18359375
+ f32[3873 >> 2]=-0.19140625
+ f32[3873 >> 2]=-0.19140625
+ f32[3877 >> 2]=-0.19921875
+ f32[3881 >> 2]=-0.20703125
+ f32[3885 >> 2]=-0.21484375
+ f32[3889 >> 2]=-0.22265625
+ f32[3893 >> 2]=-0.23046875
+ f32[3897 >> 2]=-0.23828125
+ f32[3901 >> 2]=-0.24609375
+ f32[3905 >> 2]=-0.2578125
+ f32[3909 >> 2]=-0.2734375
+ f32[3913 >> 2]=-0.2890625
+ f32[3917 >> 2]=-0.3046875
+ f32[3921 >> 2]=-0.3203125
+ f32[3925 >> 2]=-0.3359375
+ f32[3929 >> 2]=-0.3515625
+ f32[3933 >> 2]=-0.3671875
+ f32[3937 >> 2]=-0.3828125
+ f32[3941 >> 2]=-0.3984375
+ f32[3945 >> 2]=-0.4140625
+ f32[3949 >> 2]=-0.4296875
+ f32[3953 >> 2]=-0.4453125
+ f32[3957 >> 2]=-0.4609375
+ f32[3961 >> 2]=-0.4765625
+ f32[3965 >> 2]=-0.4921875
+ f32[3969 >> 2]=-0.515625
+ f32[3973 >> 2]=-0.546875
+ f32[3977 >> 2]=-0.578125
+ f32[3981 >> 2]=-0.609375
+ f32[3985 >> 2]=-0.640625
+ f32[3989 >> 2]=-0.671875
+ f32[3993 >> 2]=-0.703125
+ f32[3997 >> 2]=-0.734375
+ f32[4001 >> 2]=-0.765625
+ f32[4005 >> 2]=-0.796875
+ f32[4009 >> 2]=-0.828125
+ f32[4013 >> 2]=-0.859375
+ f32[4017 >> 2]=-0.890625
+ f32[4021 >> 2]=-0.921875
+ f32[4025 >> 2]=-0.953125
+ f32[4029 >> 2]=-0.984375
+ f32[4033 >> 2]=-1.03125
+ f32[4037 >> 2]=-1.09375
+ f32[4041 >> 2]=-1.15625
+ f32[4045 >> 2]=-1.21875
+ f32[4049 >> 2]=-1.28125
+ f32[4053 >> 2]=-1.34375
+ f32[4057 >> 2]=-1.40625
+ f32[4061 >> 2]=-1.46875
+ f32[4065 >> 2]=-1.53125
+ f32[4069 >> 2]=-1.59375
+ f32[4073 >> 2]=-1.65625
+ f32[4077 >> 2]=-1.71875
+ f32[4081 >> 2]=-1.78125
+ f32[4085 >> 2]=-1.84375
+ f32[4089 >> 2]=-1.90625
+ f32[4093 >> 2]=-1.96875
+ };
+
+ return {
+ fn1: fn1
+ };
+};
+
+var asm = testmod(this, {}, buffer);
+
+asm.fn1()
+
+var f32=new Float32Array(buffer);
+assertEq(f32[0 >> 2], 2.0)
+assertEq(f32[4 >> 2], 2.125)
+assertEq(f32[8 >> 2], 2.25)
+assertEq(f32[12 >> 2], 2.375)
+assertEq(f32[16 >> 2], 2.5)
+assertEq(f32[20 >> 2], 2.625)
+assertEq(f32[24 >> 2], 2.75)
+assertEq(f32[28 >> 2], 2.875)
+assertEq(f32[32 >> 2], 3.0)
+assertEq(f32[36 >> 2], 3.125)
+assertEq(f32[40 >> 2], 3.25)
+assertEq(f32[44 >> 2], 3.375)
+assertEq(f32[48 >> 2], 3.5)
+assertEq(f32[52 >> 2], 3.625)
+assertEq(f32[56 >> 2], 3.75)
+assertEq(f32[60 >> 2], 3.875)
+assertEq(f32[64 >> 2], 4.0)
+assertEq(f32[68 >> 2], 4.25)
+assertEq(f32[72 >> 2], 4.5)
+assertEq(f32[76 >> 2], 4.75)
+assertEq(f32[80 >> 2], 5.0)
+assertEq(f32[84 >> 2], 5.25)
+assertEq(f32[88 >> 2], 5.5)
+assertEq(f32[92 >> 2], 5.75)
+assertEq(f32[96 >> 2], 6.0)
+assertEq(f32[100 >> 2], 6.25)
+assertEq(f32[104 >> 2], 6.5)
+assertEq(f32[108 >> 2], 6.75)
+assertEq(f32[112 >> 2], 7.0)
+assertEq(f32[116 >> 2], 7.25)
+assertEq(f32[120 >> 2], 7.5)
+assertEq(f32[124 >> 2], 7.75)
+assertEq(f32[128 >> 2], 8.0)
+assertEq(f32[132 >> 2], 8.5)
+assertEq(f32[136 >> 2], 9.0)
+assertEq(f32[140 >> 2], 9.5)
+assertEq(f32[144 >> 2], 10.0)
+assertEq(f32[148 >> 2], 10.5)
+assertEq(f32[152 >> 2], 11.0)
+assertEq(f32[156 >> 2], 11.5)
+assertEq(f32[160 >> 2], 12.0)
+assertEq(f32[164 >> 2], 12.5)
+assertEq(f32[168 >> 2], 13.0)
+assertEq(f32[172 >> 2], 13.5)
+assertEq(f32[176 >> 2], 14.0)
+assertEq(f32[180 >> 2], 14.5)
+assertEq(f32[184 >> 2], 15.0)
+assertEq(f32[188 >> 2], 15.5)
+assertEq(f32[192 >> 2], 16.0)
+assertEq(f32[196 >> 2], 17.0)
+assertEq(f32[200 >> 2], 18.0)
+assertEq(f32[204 >> 2], 19.0)
+assertEq(f32[208 >> 2], 20.0)
+assertEq(f32[212 >> 2], 21.0)
+assertEq(f32[216 >> 2], 22.0)
+assertEq(f32[220 >> 2], 23.0)
+assertEq(f32[224 >> 2], 24.0)
+assertEq(f32[228 >> 2], 25.0)
+assertEq(f32[232 >> 2], 26.0)
+assertEq(f32[236 >> 2], 27.0)
+assertEq(f32[240 >> 2], 28.0)
+assertEq(f32[244 >> 2], 29.0)
+assertEq(f32[248 >> 2], 30.0)
+assertEq(f32[252 >> 2], 31.0)
+assertEq(f32[256 >> 2], 0.125)
+assertEq(f32[260 >> 2], 0.1328125)
+assertEq(f32[264 >> 2], 0.140625)
+assertEq(f32[268 >> 2], 0.1484375)
+assertEq(f32[272 >> 2], 0.15625)
+assertEq(f32[276 >> 2], 0.1640625)
+assertEq(f32[280 >> 2], 0.171875)
+assertEq(f32[284 >> 2], 0.1796875)
+assertEq(f32[288 >> 2], 0.1875)
+assertEq(f32[292 >> 2], 0.1953125)
+assertEq(f32[296 >> 2], 0.203125)
+assertEq(f32[300 >> 2], 0.2109375)
+assertEq(f32[304 >> 2], 0.21875)
+assertEq(f32[308 >> 2], 0.2265625)
+assertEq(f32[312 >> 2], 0.234375)
+assertEq(f32[316 >> 2], 0.2421875)
+assertEq(f32[320 >> 2], 0.25)
+assertEq(f32[324 >> 2], 0.265625)
+assertEq(f32[328 >> 2], 0.28125)
+assertEq(f32[332 >> 2], 0.296875)
+assertEq(f32[336 >> 2], 0.3125)
+assertEq(f32[340 >> 2], 0.328125)
+assertEq(f32[344 >> 2], 0.34375)
+assertEq(f32[348 >> 2], 0.359375)
+assertEq(f32[348 >> 2], 0.359375)
+assertEq(f32[352 >> 2], 0.375)
+assertEq(f32[356 >> 2], 0.390625)
+assertEq(f32[360 >> 2], 0.40625)
+assertEq(f32[364 >> 2], 0.421875)
+assertEq(f32[368 >> 2], 0.4375)
+assertEq(f32[372 >> 2], 0.453125)
+assertEq(f32[376 >> 2], 0.46875)
+assertEq(f32[380 >> 2], 0.484375)
+assertEq(f32[384 >> 2], 0.5)
+assertEq(f32[388 >> 2], 0.53125)
+assertEq(f32[392 >> 2], 0.5625)
+assertEq(f32[396 >> 2], 0.59375)
+assertEq(f32[400 >> 2], 0.625)
+assertEq(f32[404 >> 2], 0.65625)
+assertEq(f32[408 >> 2], 0.6875)
+assertEq(f32[412 >> 2], 0.71875)
+assertEq(f32[416 >> 2], 0.75)
+assertEq(f32[420 >> 2], 0.78125)
+assertEq(f32[424 >> 2], 0.8125)
+assertEq(f32[428 >> 2], 0.84375)
+assertEq(f32[432 >> 2], 0.875)
+assertEq(f32[436 >> 2], 0.90625)
+assertEq(f32[440 >> 2], 0.9375)
+assertEq(f32[444 >> 2], 0.96875)
+assertEq(f32[448 >> 2], 1.0)
+assertEq(f32[452 >> 2], 1.0625)
+assertEq(f32[456 >> 2], 1.125)
+assertEq(f32[460 >> 2], 1.1875)
+assertEq(f32[464 >> 2], 1.25)
+assertEq(f32[468 >> 2], 1.3125)
+assertEq(f32[472 >> 2], 1.375)
+assertEq(f32[476 >> 2], 1.4375)
+assertEq(f32[480 >> 2], 1.5)
+assertEq(f32[484 >> 2], 1.5625)
+assertEq(f32[488 >> 2], 1.625)
+assertEq(f32[492 >> 2], 1.6875)
+assertEq(f32[496 >> 2], 1.75)
+assertEq(f32[500 >> 2], 1.8125)
+assertEq(f32[504 >> 2], 1.875)
+assertEq(f32[508 >> 2], 1.9375)
+assertEq(f32[512 >> 2], -2.0)
+assertEq(f32[516 >> 2], -2.125)
+assertEq(f32[520 >> 2], -2.25)
+assertEq(f32[524 >> 2], -2.375)
+assertEq(f32[528 >> 2], -2.5)
+assertEq(f32[532 >> 2], -2.625)
+assertEq(f32[536 >> 2], -2.75)
+assertEq(f32[540 >> 2], -2.875)
+assertEq(f32[544 >> 2], -3.0)
+assertEq(f32[548 >> 2], -3.125)
+assertEq(f32[552 >> 2], -3.25)
+assertEq(f32[556 >> 2], -3.375)
+assertEq(f32[560 >> 2], -3.5)
+assertEq(f32[564 >> 2], -3.625)
+assertEq(f32[568 >> 2], -3.75)
+assertEq(f32[572 >> 2], -3.875)
+assertEq(f32[576 >> 2], -4.0)
+assertEq(f32[580 >> 2], -4.25)
+assertEq(f32[584 >> 2], -4.5)
+assertEq(f32[588 >> 2], -4.75)
+assertEq(f32[592 >> 2], -5.0)
+assertEq(f32[596 >> 2], -5.25)
+assertEq(f32[600 >> 2], -5.5)
+assertEq(f32[604 >> 2], -5.75)
+assertEq(f32[608 >> 2], -6.0)
+assertEq(f32[612 >> 2], -6.25)
+assertEq(f32[616 >> 2], -6.5)
+assertEq(f32[620 >> 2], -6.75)
+assertEq(f32[624 >> 2], -7.0)
+assertEq(f32[628 >> 2], -7.25)
+assertEq(f32[632 >> 2], -7.5)
+assertEq(f32[636 >> 2], -7.75)
+assertEq(f32[640 >> 2], -8.0)
+assertEq(f32[644 >> 2], -8.5)
+assertEq(f32[648 >> 2], -9.0)
+assertEq(f32[652 >> 2], -9.5)
+assertEq(f32[656 >> 2], -10.0)
+assertEq(f32[660 >> 2], -10.5)
+assertEq(f32[664 >> 2], -11.0)
+assertEq(f32[668 >> 2], -11.5)
+assertEq(f32[672 >> 2], -12.0)
+assertEq(f32[676 >> 2], -12.5)
+assertEq(f32[680 >> 2], -13.0)
+assertEq(f32[684 >> 2], -13.5)
+assertEq(f32[688 >> 2], -14.0)
+assertEq(f32[692 >> 2], -14.5)
+assertEq(f32[696 >> 2], -15.0)
+assertEq(f32[700 >> 2], -15.5)
+assertEq(f32[704 >> 2], -16.0)
+assertEq(f32[708 >> 2], -17.0)
+assertEq(f32[712 >> 2], -18.0)
+assertEq(f32[716 >> 2], -19.0)
+assertEq(f32[720 >> 2], -20.0)
+assertEq(f32[724 >> 2], -21.0)
+assertEq(f32[728 >> 2], -22.0)
+assertEq(f32[732 >> 2], -23.0)
+assertEq(f32[736 >> 2], -24.0)
+assertEq(f32[740 >> 2], -25.0)
+assertEq(f32[744 >> 2], -26.0)
+assertEq(f32[748 >> 2], -27.0)
+assertEq(f32[748 >> 2], -27.0)
+assertEq(f32[752 >> 2], -28.0)
+assertEq(f32[756 >> 2], -29.0)
+assertEq(f32[760 >> 2], -30.0)
+assertEq(f32[764 >> 2], -31.0)
+assertEq(f32[768 >> 2], -0.125)
+assertEq(f32[772 >> 2], -0.1328125)
+assertEq(f32[776 >> 2], -0.140625)
+assertEq(f32[780 >> 2], -0.1484375)
+assertEq(f32[784 >> 2], -0.15625)
+assertEq(f32[788 >> 2], -0.1640625)
+assertEq(f32[792 >> 2], -0.171875)
+assertEq(f32[796 >> 2], -0.1796875)
+assertEq(f32[800 >> 2], -0.1875)
+assertEq(f32[804 >> 2], -0.1953125)
+assertEq(f32[808 >> 2], -0.203125)
+assertEq(f32[812 >> 2], -0.2109375)
+assertEq(f32[816 >> 2], -0.21875)
+assertEq(f32[820 >> 2], -0.2265625)
+assertEq(f32[824 >> 2], -0.234375)
+assertEq(f32[828 >> 2], -0.2421875)
+assertEq(f32[832 >> 2], -0.25)
+assertEq(f32[836 >> 2], -0.265625)
+assertEq(f32[840 >> 2], -0.28125)
+assertEq(f32[844 >> 2], -0.296875)
+assertEq(f32[848 >> 2], -0.3125)
+assertEq(f32[852 >> 2], -0.328125)
+assertEq(f32[856 >> 2], -0.34375)
+assertEq(f32[860 >> 2], -0.359375)
+assertEq(f32[864 >> 2], -0.375)
+assertEq(f32[868 >> 2], -0.390625)
+assertEq(f32[872 >> 2], -0.40625)
+assertEq(f32[876 >> 2], -0.421875)
+assertEq(f32[880 >> 2], -0.4375)
+assertEq(f32[884 >> 2], -0.453125)
+assertEq(f32[888 >> 2], -0.46875)
+assertEq(f32[892 >> 2], -0.484375)
+assertEq(f32[896 >> 2], -0.5)
+assertEq(f32[900 >> 2], -0.53125)
+assertEq(f32[904 >> 2], -0.5625)
+assertEq(f32[908 >> 2], -0.59375)
+assertEq(f32[912 >> 2], -0.625)
+assertEq(f32[916 >> 2], -0.65625)
+assertEq(f32[920 >> 2], -0.6875)
+assertEq(f32[924 >> 2], -0.71875)
+assertEq(f32[928 >> 2], -0.75)
+assertEq(f32[932 >> 2], -0.78125)
+assertEq(f32[936 >> 2], -0.8125)
+assertEq(f32[940 >> 2], -0.84375)
+assertEq(f32[944 >> 2], -0.875)
+assertEq(f32[948 >> 2], -0.90625)
+assertEq(f32[952 >> 2], -0.9375)
+assertEq(f32[956 >> 2], -0.96875)
+assertEq(f32[960 >> 2], -1.0)
+assertEq(f32[964 >> 2], -1.0625)
+assertEq(f32[968 >> 2], -1.125)
+assertEq(f32[972 >> 2], -1.1875)
+assertEq(f32[976 >> 2], -1.25)
+assertEq(f32[980 >> 2], -1.3125)
+assertEq(f32[984 >> 2], -1.375)
+assertEq(f32[988 >> 2], -1.4375)
+assertEq(f32[992 >> 2], -1.5)
+assertEq(f32[996 >> 2], -1.5625)
+assertEq(f32[1000 >> 2], -1.625)
+assertEq(f32[1004 >> 2], -1.6875)
+assertEq(f32[1008 >> 2], -1.75)
+assertEq(f32[1012 >> 2], -1.8125)
+assertEq(f32[1016 >> 2], -1.875)
+assertEq(f32[1020 >> 2], -1.9375)
+
+assertEq(f32[1024 >> 2], 2.124999761581421)
+assertEq(f32[1028 >> 2], 2.249999761581421)
+assertEq(f32[1032 >> 2], 2.374999761581421)
+assertEq(f32[1036 >> 2], 2.499999761581421)
+assertEq(f32[1040 >> 2], 2.624999761581421)
+assertEq(f32[1044 >> 2], 2.749999761581421)
+assertEq(f32[1048 >> 2], 2.874999761581421)
+assertEq(f32[1052 >> 2], 2.999999761581421)
+assertEq(f32[1056 >> 2], 3.124999761581421)
+assertEq(f32[1060 >> 2], 3.249999761581421)
+assertEq(f32[1064 >> 2], 3.374999761581421)
+assertEq(f32[1068 >> 2], 3.499999761581421)
+assertEq(f32[1072 >> 2], 3.624999761581421)
+assertEq(f32[1076 >> 2], 3.749999761581421)
+assertEq(f32[1080 >> 2], 3.874999761581421)
+assertEq(f32[1084 >> 2], 3.999999761581421)
+assertEq(f32[1088 >> 2], 4.249999523162842)
+assertEq(f32[1092 >> 2], 4.499999523162842)
+assertEq(f32[1096 >> 2], 4.749999523162842)
+assertEq(f32[1100 >> 2], 4.999999523162842)
+assertEq(f32[1104 >> 2], 5.249999523162842)
+assertEq(f32[1108 >> 2], 5.499999523162842)
+assertEq(f32[1112 >> 2], 5.749999523162842)
+assertEq(f32[1116 >> 2], 5.999999523162842)
+assertEq(f32[1120 >> 2], 6.249999523162842)
+assertEq(f32[1124 >> 2], 6.499999523162842)
+assertEq(f32[1128 >> 2], 6.749999523162842)
+assertEq(f32[1132 >> 2], 6.999999523162842)
+assertEq(f32[1136 >> 2], 7.249999523162842)
+assertEq(f32[1140 >> 2], 7.499999523162842)
+assertEq(f32[1144 >> 2], 7.749999523162842)
+assertEq(f32[1148 >> 2], 7.999999523162842)
+assertEq(f32[1152 >> 2], 8.499999046325684)
+assertEq(f32[1156 >> 2], 8.999999046325684)
+assertEq(f32[1160 >> 2], 9.499999046325684)
+assertEq(f32[1164 >> 2], 9.999999046325684)
+assertEq(f32[1168 >> 2], 10.499999046325684)
+assertEq(f32[1172 >> 2], 10.999999046325684)
+assertEq(f32[1176 >> 2], 11.499999046325684)
+assertEq(f32[1180 >> 2], 11.999999046325684)
+assertEq(f32[1184 >> 2], 12.499999046325684)
+assertEq(f32[1184 >> 2], 12.499999046325684)
+assertEq(f32[1188 >> 2], 12.999999046325684)
+assertEq(f32[1192 >> 2], 13.499999046325684)
+assertEq(f32[1196 >> 2], 13.999999046325684)
+assertEq(f32[1200 >> 2], 14.499999046325684)
+assertEq(f32[1204 >> 2], 14.999999046325684)
+assertEq(f32[1208 >> 2], 15.499999046325684)
+assertEq(f32[1212 >> 2], 15.999999046325684)
+assertEq(f32[1216 >> 2], 16.999998092651367)
+assertEq(f32[1220 >> 2], 17.999998092651367)
+assertEq(f32[1224 >> 2], 18.999998092651367)
+assertEq(f32[1228 >> 2], 19.999998092651367)
+assertEq(f32[1232 >> 2], 20.999998092651367)
+assertEq(f32[1236 >> 2], 21.999998092651367)
+assertEq(f32[1240 >> 2], 22.999998092651367)
+assertEq(f32[1244 >> 2], 23.999998092651367)
+assertEq(f32[1248 >> 2], 24.999998092651367)
+assertEq(f32[1252 >> 2], 25.999998092651367)
+assertEq(f32[1256 >> 2], 26.999998092651367)
+assertEq(f32[1260 >> 2], 27.999998092651367)
+assertEq(f32[1264 >> 2], 28.999998092651367)
+assertEq(f32[1268 >> 2], 29.999998092651367)
+assertEq(f32[1272 >> 2], 30.999998092651367)
+assertEq(f32[1276 >> 2], 31.999998092651367)
+assertEq(f32[1280 >> 2], 0.1328124850988388)
+assertEq(f32[1284 >> 2], 0.1406249850988388)
+assertEq(f32[1288 >> 2], 0.1484374850988388)
+assertEq(f32[1292 >> 2], 0.1562499850988388)
+assertEq(f32[1296 >> 2], 0.1640624850988388)
+assertEq(f32[1300 >> 2], 0.1718749850988388)
+assertEq(f32[1304 >> 2], 0.1796874850988388)
+assertEq(f32[1308 >> 2], 0.1874999850988388)
+assertEq(f32[1312 >> 2], 0.1953124850988388)
+assertEq(f32[1316 >> 2], 0.2031249850988388)
+assertEq(f32[1320 >> 2], 0.2109374850988388)
+assertEq(f32[1324 >> 2], 0.2187499850988388)
+assertEq(f32[1328 >> 2], 0.2265624850988388)
+assertEq(f32[1332 >> 2], 0.2343749850988388)
+assertEq(f32[1336 >> 2], 0.2421874850988388)
+assertEq(f32[1340 >> 2], 0.2499999850988388)
+assertEq(f32[1344 >> 2], 0.2656249701976776)
+assertEq(f32[1348 >> 2], 0.2812499701976776)
+assertEq(f32[1352 >> 2], 0.2968749701976776)
+assertEq(f32[1356 >> 2], 0.3124999701976776)
+assertEq(f32[1360 >> 2], 0.3281249701976776)
+assertEq(f32[1364 >> 2], 0.3437499701976776)
+assertEq(f32[1368 >> 2], 0.3593749701976776)
+assertEq(f32[1372 >> 2], 0.3749999701976776)
+assertEq(f32[1376 >> 2], 0.3906249701976776)
+assertEq(f32[1380 >> 2], 0.4062499701976776)
+assertEq(f32[1384 >> 2], 0.4218749701976776)
+assertEq(f32[1388 >> 2], 0.4374999701976776)
+assertEq(f32[1392 >> 2], 0.4531249701976776)
+assertEq(f32[1396 >> 2], 0.4687499701976776)
+assertEq(f32[1400 >> 2], 0.4843749701976776)
+assertEq(f32[1404 >> 2], 0.4999999701976776)
+assertEq(f32[1408 >> 2], 0.5312499403953552)
+assertEq(f32[1412 >> 2], 0.5624999403953552)
+assertEq(f32[1416 >> 2], 0.5937499403953552)
+assertEq(f32[1420 >> 2], 0.6249999403953552)
+assertEq(f32[1424 >> 2], 0.6562499403953552)
+assertEq(f32[1428 >> 2], 0.6874999403953552)
+assertEq(f32[1432 >> 2], 0.7187499403953552)
+assertEq(f32[1436 >> 2], 0.7499999403953552)
+assertEq(f32[1440 >> 2], 0.7812499403953552)
+assertEq(f32[1444 >> 2], 0.8124999403953552)
+assertEq(f32[1448 >> 2], 0.8437499403953552)
+assertEq(f32[1452 >> 2], 0.8749999403953552)
+assertEq(f32[1456 >> 2], 0.9062499403953552)
+assertEq(f32[1460 >> 2], 0.9374999403953552)
+assertEq(f32[1464 >> 2], 0.9687499403953552)
+assertEq(f32[1468 >> 2], 0.9999999403953552)
+assertEq(f32[1472 >> 2], 1.0624998807907104)
+assertEq(f32[1476 >> 2], 1.1249998807907104)
+assertEq(f32[1480 >> 2], 1.1874998807907104)
+assertEq(f32[1484 >> 2], 1.2499998807907104)
+assertEq(f32[1488 >> 2], 1.3124998807907104)
+assertEq(f32[1492 >> 2], 1.3749998807907104)
+assertEq(f32[1496 >> 2], 1.4374998807907104)
+assertEq(f32[1500 >> 2], 1.4999998807907104)
+assertEq(f32[1504 >> 2], 1.5624998807907104)
+assertEq(f32[1508 >> 2], 1.6249998807907104)
+assertEq(f32[1512 >> 2], 1.6874998807907104)
+assertEq(f32[1516 >> 2], 1.7499998807907104)
+assertEq(f32[1520 >> 2], 1.8124998807907104)
+assertEq(f32[1524 >> 2], 1.8749998807907104)
+assertEq(f32[1528 >> 2], 1.9374998807907104)
+assertEq(f32[1532 >> 2], 1.9999998807907104)
+assertEq(f32[1536 >> 2], -2.124999761581421)
+assertEq(f32[1540 >> 2], -2.249999761581421)
+assertEq(f32[1544 >> 2], -2.374999761581421)
+assertEq(f32[1548 >> 2], -2.499999761581421)
+assertEq(f32[1552 >> 2], -2.624999761581421)
+assertEq(f32[1556 >> 2], -2.749999761581421)
+assertEq(f32[1560 >> 2], -2.874999761581421)
+assertEq(f32[1564 >> 2], -2.999999761581421)
+assertEq(f32[1568 >> 2], -3.124999761581421)
+assertEq(f32[1572 >> 2], -3.249999761581421)
+assertEq(f32[1576 >> 2], -3.374999761581421)
+assertEq(f32[1580 >> 2], -3.499999761581421)
+assertEq(f32[1584 >> 2], -3.624999761581421)
+assertEq(f32[1584 >> 2], -3.624999761581421)
+assertEq(f32[1588 >> 2], -3.749999761581421)
+assertEq(f32[1592 >> 2], -3.874999761581421)
+assertEq(f32[1596 >> 2], -3.999999761581421)
+assertEq(f32[1600 >> 2], -4.249999523162842)
+assertEq(f32[1604 >> 2], -4.499999523162842)
+assertEq(f32[1608 >> 2], -4.749999523162842)
+assertEq(f32[1612 >> 2], -4.999999523162842)
+assertEq(f32[1616 >> 2], -5.249999523162842)
+assertEq(f32[1620 >> 2], -5.499999523162842)
+assertEq(f32[1624 >> 2], -5.749999523162842)
+assertEq(f32[1628 >> 2], -5.999999523162842)
+assertEq(f32[1632 >> 2], -6.249999523162842)
+assertEq(f32[1636 >> 2], -6.499999523162842)
+assertEq(f32[1640 >> 2], -6.749999523162842)
+assertEq(f32[1644 >> 2], -6.999999523162842)
+assertEq(f32[1648 >> 2], -7.249999523162842)
+assertEq(f32[1652 >> 2], -7.499999523162842)
+assertEq(f32[1656 >> 2], -7.749999523162842)
+assertEq(f32[1660 >> 2], -7.999999523162842)
+assertEq(f32[1664 >> 2], -8.499999046325684)
+assertEq(f32[1668 >> 2], -8.999999046325684)
+assertEq(f32[1672 >> 2], -9.499999046325684)
+assertEq(f32[1676 >> 2], -9.999999046325684)
+assertEq(f32[1680 >> 2], -10.499999046325684)
+assertEq(f32[1684 >> 2], -10.999999046325684)
+assertEq(f32[1688 >> 2], -11.499999046325684)
+assertEq(f32[1692 >> 2], -11.999999046325684)
+assertEq(f32[1696 >> 2], -12.499999046325684)
+assertEq(f32[1700 >> 2], -12.999999046325684)
+assertEq(f32[1704 >> 2], -13.499999046325684)
+assertEq(f32[1708 >> 2], -13.999999046325684)
+assertEq(f32[1712 >> 2], -14.499999046325684)
+assertEq(f32[1716 >> 2], -14.999999046325684)
+assertEq(f32[1720 >> 2], -15.499999046325684)
+assertEq(f32[1724 >> 2], -15.999999046325684)
+assertEq(f32[1728 >> 2], -16.999998092651367)
+assertEq(f32[1732 >> 2], -17.999998092651367)
+assertEq(f32[1736 >> 2], -18.999998092651367)
+assertEq(f32[1740 >> 2], -19.999998092651367)
+assertEq(f32[1744 >> 2], -20.999998092651367)
+assertEq(f32[1748 >> 2], -21.999998092651367)
+assertEq(f32[1752 >> 2], -22.999998092651367)
+assertEq(f32[1756 >> 2], -23.999998092651367)
+assertEq(f32[1760 >> 2], -24.999998092651367)
+assertEq(f32[1764 >> 2], -25.999998092651367)
+assertEq(f32[1768 >> 2], -26.999998092651367)
+assertEq(f32[1772 >> 2], -27.999998092651367)
+assertEq(f32[1776 >> 2], -28.999998092651367)
+assertEq(f32[1780 >> 2], -29.999998092651367)
+assertEq(f32[1784 >> 2], -30.999998092651367)
+assertEq(f32[1788 >> 2], -31.999998092651367)
+assertEq(f32[1792 >> 2], -0.1328124850988388)
+assertEq(f32[1796 >> 2], -0.1406249850988388)
+assertEq(f32[1800 >> 2], -0.1484374850988388)
+assertEq(f32[1804 >> 2], -0.1562499850988388)
+assertEq(f32[1808 >> 2], -0.1640624850988388)
+assertEq(f32[1812 >> 2], -0.1718749850988388)
+assertEq(f32[1816 >> 2], -0.1796874850988388)
+assertEq(f32[1820 >> 2], -0.1874999850988388)
+assertEq(f32[1824 >> 2], -0.1953124850988388)
+assertEq(f32[1828 >> 2], -0.2031249850988388)
+assertEq(f32[1832 >> 2], -0.2109374850988388)
+assertEq(f32[1836 >> 2], -0.2187499850988388)
+assertEq(f32[1840 >> 2], -0.2265624850988388)
+assertEq(f32[1844 >> 2], -0.2343749850988388)
+assertEq(f32[1848 >> 2], -0.2421874850988388)
+assertEq(f32[1852 >> 2], -0.2499999850988388)
+assertEq(f32[1856 >> 2], -0.2656249701976776)
+assertEq(f32[1860 >> 2], -0.2812499701976776)
+assertEq(f32[1864 >> 2], -0.2968749701976776)
+assertEq(f32[1868 >> 2], -0.3124999701976776)
+assertEq(f32[1872 >> 2], -0.3281249701976776)
+assertEq(f32[1876 >> 2], -0.3437499701976776)
+assertEq(f32[1880 >> 2], -0.3593749701976776)
+assertEq(f32[1884 >> 2], -0.3749999701976776)
+assertEq(f32[1888 >> 2], -0.3906249701976776)
+assertEq(f32[1892 >> 2], -0.4062499701976776)
+assertEq(f32[1896 >> 2], -0.4218749701976776)
+assertEq(f32[1900 >> 2], -0.4374999701976776)
+assertEq(f32[1904 >> 2], -0.4531249701976776)
+assertEq(f32[1908 >> 2], -0.4687499701976776)
+assertEq(f32[1912 >> 2], -0.4843749701976776)
+assertEq(f32[1916 >> 2], -0.4999999701976776)
+assertEq(f32[1920 >> 2], -0.5312499403953552)
+assertEq(f32[1924 >> 2], -0.5624999403953552)
+assertEq(f32[1928 >> 2], -0.5937499403953552)
+assertEq(f32[1932 >> 2], -0.6249999403953552)
+assertEq(f32[1936 >> 2], -0.6562499403953552)
+assertEq(f32[1940 >> 2], -0.6874999403953552)
+assertEq(f32[1944 >> 2], -0.7187499403953552)
+assertEq(f32[1948 >> 2], -0.7499999403953552)
+assertEq(f32[1952 >> 2], -0.7812499403953552)
+assertEq(f32[1956 >> 2], -0.8124999403953552)
+assertEq(f32[1960 >> 2], -0.8437499403953552)
+assertEq(f32[1964 >> 2], -0.8749999403953552)
+assertEq(f32[1968 >> 2], -0.9062499403953552)
+assertEq(f32[1972 >> 2], -0.9374999403953552)
+assertEq(f32[1976 >> 2], -0.9687499403953552)
+assertEq(f32[1980 >> 2], -0.9999999403953552)
+assertEq(f32[1984 >> 2], -1.0624998807907104)
+assertEq(f32[1984 >> 2], -1.0624998807907104)
+assertEq(f32[1988 >> 2], -1.1249998807907104)
+assertEq(f32[1992 >> 2], -1.1874998807907104)
+assertEq(f32[1996 >> 2], -1.2499998807907104)
+assertEq(f32[2000 >> 2], -1.3124998807907104)
+assertEq(f32[2004 >> 2], -1.3749998807907104)
+assertEq(f32[2008 >> 2], -1.4374998807907104)
+assertEq(f32[2012 >> 2], -1.4999998807907104)
+assertEq(f32[2016 >> 2], -1.5624998807907104)
+assertEq(f32[2020 >> 2], -1.6249998807907104)
+assertEq(f32[2024 >> 2], -1.6874998807907104)
+assertEq(f32[2028 >> 2], -1.7499998807907104)
+assertEq(f32[2032 >> 2], -1.8124998807907104)
+assertEq(f32[2036 >> 2], -1.8749998807907104)
+assertEq(f32[2040 >> 2], -1.9374998807907104)
+assertEq(f32[2044 >> 2], -1.9999998807907104)
+
+assertEq(f32[2048 >> 2], 2.000000238418579)
+assertEq(f32[2052 >> 2], 2.125000238418579)
+assertEq(f32[2056 >> 2], 2.250000238418579)
+assertEq(f32[2060 >> 2], 2.375000238418579)
+assertEq(f32[2064 >> 2], 2.500000238418579)
+assertEq(f32[2068 >> 2], 2.625000238418579)
+assertEq(f32[2072 >> 2], 2.750000238418579)
+assertEq(f32[2076 >> 2], 2.875000238418579)
+assertEq(f32[2080 >> 2], 3.000000238418579)
+assertEq(f32[2084 >> 2], 3.125000238418579)
+assertEq(f32[2088 >> 2], 3.250000238418579)
+assertEq(f32[2092 >> 2], 3.375000238418579)
+assertEq(f32[2096 >> 2], 3.500000238418579)
+assertEq(f32[2100 >> 2], 3.625000238418579)
+assertEq(f32[2104 >> 2], 3.750000238418579)
+assertEq(f32[2108 >> 2], 3.875000238418579)
+assertEq(f32[2112 >> 2], 4.000000476837158)
+assertEq(f32[2116 >> 2], 4.250000476837158)
+assertEq(f32[2120 >> 2], 4.500000476837158)
+assertEq(f32[2124 >> 2], 4.750000476837158)
+assertEq(f32[2128 >> 2], 5.000000476837158)
+assertEq(f32[2132 >> 2], 5.250000476837158)
+assertEq(f32[2136 >> 2], 5.500000476837158)
+assertEq(f32[2140 >> 2], 5.750000476837158)
+assertEq(f32[2144 >> 2], 6.000000476837158)
+assertEq(f32[2148 >> 2], 6.250000476837158)
+assertEq(f32[2152 >> 2], 6.500000476837158)
+assertEq(f32[2156 >> 2], 6.750000476837158)
+assertEq(f32[2160 >> 2], 7.000000476837158)
+assertEq(f32[2164 >> 2], 7.250000476837158)
+assertEq(f32[2168 >> 2], 7.500000476837158)
+assertEq(f32[2172 >> 2], 7.750000476837158)
+assertEq(f32[2176 >> 2], 8.000000953674316)
+assertEq(f32[2180 >> 2], 8.500000953674316)
+assertEq(f32[2184 >> 2], 9.000000953674316)
+assertEq(f32[2188 >> 2], 9.500000953674316)
+assertEq(f32[2192 >> 2], 10.000000953674316)
+assertEq(f32[2196 >> 2], 10.500000953674316)
+assertEq(f32[2200 >> 2], 11.000000953674316)
+assertEq(f32[2204 >> 2], 11.500000953674316)
+assertEq(f32[2208 >> 2], 12.000000953674316)
+assertEq(f32[2212 >> 2], 12.500000953674316)
+assertEq(f32[2216 >> 2], 13.000000953674316)
+assertEq(f32[2220 >> 2], 13.500000953674316)
+assertEq(f32[2224 >> 2], 14.000000953674316)
+assertEq(f32[2228 >> 2], 14.500000953674316)
+assertEq(f32[2228 >> 2], 14.500000953674316)
+assertEq(f32[2232 >> 2], 15.000000953674316)
+assertEq(f32[2236 >> 2], 15.500000953674316)
+assertEq(f32[2240 >> 2], 16.000001907348633)
+assertEq(f32[2244 >> 2], 17.000001907348633)
+assertEq(f32[2248 >> 2], 18.000001907348633)
+assertEq(f32[2252 >> 2], 19.000001907348633)
+assertEq(f32[2256 >> 2], 20.000001907348633)
+assertEq(f32[2260 >> 2], 21.000001907348633)
+assertEq(f32[2264 >> 2], 22.000001907348633)
+assertEq(f32[2268 >> 2], 23.000001907348633)
+assertEq(f32[2272 >> 2], 24.000001907348633)
+assertEq(f32[2276 >> 2], 25.000001907348633)
+assertEq(f32[2280 >> 2], 26.000001907348633)
+assertEq(f32[2284 >> 2], 27.000001907348633)
+assertEq(f32[2288 >> 2], 28.000001907348633)
+assertEq(f32[2292 >> 2], 29.000001907348633)
+assertEq(f32[2296 >> 2], 30.000001907348633)
+assertEq(f32[2300 >> 2], 31.000001907348633)
+assertEq(f32[2304 >> 2], 0.1250000149011612)
+assertEq(f32[2308 >> 2], 0.1328125149011612)
+assertEq(f32[2312 >> 2], 0.1406250149011612)
+assertEq(f32[2316 >> 2], 0.1484375149011612)
+assertEq(f32[2320 >> 2], 0.1562500149011612)
+assertEq(f32[2324 >> 2], 0.1640625149011612)
+assertEq(f32[2328 >> 2], 0.1718750149011612)
+assertEq(f32[2332 >> 2], 0.1796875149011612)
+assertEq(f32[2336 >> 2], 0.1875000149011612)
+assertEq(f32[2340 >> 2], 0.1953125149011612)
+assertEq(f32[2344 >> 2], 0.2031250149011612)
+assertEq(f32[2348 >> 2], 0.2109375149011612)
+assertEq(f32[2352 >> 2], 0.2187500149011612)
+assertEq(f32[2356 >> 2], 0.2265625149011612)
+assertEq(f32[2360 >> 2], 0.2343750149011612)
+assertEq(f32[2364 >> 2], 0.2421875149011612)
+assertEq(f32[2368 >> 2], 0.2500000298023224)
+assertEq(f32[2372 >> 2], 0.2656250298023224)
+assertEq(f32[2376 >> 2], 0.2812500298023224)
+assertEq(f32[2380 >> 2], 0.2968750298023224)
+assertEq(f32[2384 >> 2], 0.3125000298023224)
+assertEq(f32[2388 >> 2], 0.3281250298023224)
+assertEq(f32[2392 >> 2], 0.3437500298023224)
+assertEq(f32[2396 >> 2], 0.3593750298023224)
+assertEq(f32[2400 >> 2], 0.3750000298023224)
+assertEq(f32[2404 >> 2], 0.3906250298023224)
+assertEq(f32[2408 >> 2], 0.4062500298023224)
+assertEq(f32[2412 >> 2], 0.4218750298023224)
+assertEq(f32[2416 >> 2], 0.4375000298023224)
+assertEq(f32[2420 >> 2], 0.4531250298023224)
+assertEq(f32[2424 >> 2], 0.4687500298023224)
+assertEq(f32[2428 >> 2], 0.4843750298023224)
+assertEq(f32[2432 >> 2], 0.5000000596046448)
+assertEq(f32[2436 >> 2], 0.5312500596046448)
+assertEq(f32[2440 >> 2], 0.5625000596046448)
+assertEq(f32[2444 >> 2], 0.5937500596046448)
+assertEq(f32[2448 >> 2], 0.6250000596046448)
+assertEq(f32[2452 >> 2], 0.6562500596046448)
+assertEq(f32[2456 >> 2], 0.6875000596046448)
+assertEq(f32[2460 >> 2], 0.7187500596046448)
+assertEq(f32[2464 >> 2], 0.7500000596046448)
+assertEq(f32[2468 >> 2], 0.7812500596046448)
+assertEq(f32[2472 >> 2], 0.8125000596046448)
+assertEq(f32[2476 >> 2], 0.8437500596046448)
+assertEq(f32[2480 >> 2], 0.8750000596046448)
+assertEq(f32[2484 >> 2], 0.9062500596046448)
+assertEq(f32[2488 >> 2], 0.9375000596046448)
+assertEq(f32[2492 >> 2], 0.9687500596046448)
+assertEq(f32[2496 >> 2], 1.0000001192092896)
+assertEq(f32[2500 >> 2], 1.0625001192092896)
+assertEq(f32[2504 >> 2], 1.1250001192092896)
+assertEq(f32[2508 >> 2], 1.1875001192092896)
+assertEq(f32[2512 >> 2], 1.2500001192092896)
+assertEq(f32[2516 >> 2], 1.3125001192092896)
+assertEq(f32[2520 >> 2], 1.3750001192092896)
+assertEq(f32[2524 >> 2], 1.4375001192092896)
+assertEq(f32[2528 >> 2], 1.5000001192092896)
+assertEq(f32[2532 >> 2], 1.5625001192092896)
+assertEq(f32[2536 >> 2], 1.6250001192092896)
+assertEq(f32[2540 >> 2], 1.6875001192092896)
+assertEq(f32[2544 >> 2], 1.7500001192092896)
+assertEq(f32[2548 >> 2], 1.8125001192092896)
+assertEq(f32[2552 >> 2], 1.8750001192092896)
+assertEq(f32[2556 >> 2], 1.9375001192092896)
+assertEq(f32[2560 >> 2], -2.000000238418579)
+assertEq(f32[2564 >> 2], -2.125000238418579)
+assertEq(f32[2568 >> 2], -2.250000238418579)
+assertEq(f32[2572 >> 2], -2.375000238418579)
+assertEq(f32[2576 >> 2], -2.500000238418579)
+assertEq(f32[2580 >> 2], -2.625000238418579)
+assertEq(f32[2584 >> 2], -2.750000238418579)
+assertEq(f32[2588 >> 2], -2.875000238418579)
+assertEq(f32[2592 >> 2], -3.000000238418579)
+assertEq(f32[2596 >> 2], -3.125000238418579)
+assertEq(f32[2600 >> 2], -3.250000238418579)
+assertEq(f32[2604 >> 2], -3.375000238418579)
+assertEq(f32[2608 >> 2], -3.500000238418579)
+assertEq(f32[2612 >> 2], -3.625000238418579)
+assertEq(f32[2616 >> 2], -3.750000238418579)
+assertEq(f32[2620 >> 2], -3.875000238418579)
+assertEq(f32[2624 >> 2], -4.000000476837158)
+assertEq(f32[2628 >> 2], -4.250000476837158)
+assertEq(f32[2628 >> 2], -4.250000476837158)
+assertEq(f32[2632 >> 2], -4.500000476837158)
+assertEq(f32[2636 >> 2], -4.750000476837158)
+assertEq(f32[2640 >> 2], -5.000000476837158)
+assertEq(f32[2644 >> 2], -5.250000476837158)
+assertEq(f32[2648 >> 2], -5.500000476837158)
+assertEq(f32[2652 >> 2], -5.750000476837158)
+assertEq(f32[2656 >> 2], -6.000000476837158)
+assertEq(f32[2660 >> 2], -6.250000476837158)
+assertEq(f32[2664 >> 2], -6.500000476837158)
+assertEq(f32[2668 >> 2], -6.750000476837158)
+assertEq(f32[2672 >> 2], -7.000000476837158)
+assertEq(f32[2676 >> 2], -7.250000476837158)
+assertEq(f32[2680 >> 2], -7.500000476837158)
+assertEq(f32[2684 >> 2], -7.750000476837158)
+assertEq(f32[2688 >> 2], -8.000000953674316)
+assertEq(f32[2692 >> 2], -8.500000953674316)
+assertEq(f32[2696 >> 2], -9.000000953674316)
+assertEq(f32[2700 >> 2], -9.500000953674316)
+assertEq(f32[2704 >> 2], -10.000000953674316)
+assertEq(f32[2708 >> 2], -10.500000953674316)
+assertEq(f32[2712 >> 2], -11.000000953674316)
+assertEq(f32[2716 >> 2], -11.500000953674316)
+assertEq(f32[2720 >> 2], -12.000000953674316)
+assertEq(f32[2724 >> 2], -12.500000953674316)
+assertEq(f32[2728 >> 2], -13.000000953674316)
+assertEq(f32[2732 >> 2], -13.500000953674316)
+assertEq(f32[2736 >> 2], -14.000000953674316)
+assertEq(f32[2740 >> 2], -14.500000953674316)
+assertEq(f32[2744 >> 2], -15.000000953674316)
+assertEq(f32[2748 >> 2], -15.500000953674316)
+assertEq(f32[2752 >> 2], -16.000001907348633)
+assertEq(f32[2756 >> 2], -17.000001907348633)
+assertEq(f32[2760 >> 2], -18.000001907348633)
+assertEq(f32[2764 >> 2], -19.000001907348633)
+assertEq(f32[2768 >> 2], -20.000001907348633)
+assertEq(f32[2772 >> 2], -21.000001907348633)
+assertEq(f32[2776 >> 2], -22.000001907348633)
+assertEq(f32[2780 >> 2], -23.000001907348633)
+assertEq(f32[2784 >> 2], -24.000001907348633)
+assertEq(f32[2788 >> 2], -25.000001907348633)
+assertEq(f32[2792 >> 2], -26.000001907348633)
+assertEq(f32[2796 >> 2], -27.000001907348633)
+assertEq(f32[2800 >> 2], -28.000001907348633)
+assertEq(f32[2804 >> 2], -29.000001907348633)
+assertEq(f32[2808 >> 2], -30.000001907348633)
+assertEq(f32[2812 >> 2], -31.000001907348633)
+assertEq(f32[2816 >> 2], -0.1250000149011612)
+assertEq(f32[2820 >> 2], -0.1328125149011612)
+assertEq(f32[2824 >> 2], -0.1406250149011612)
+assertEq(f32[2828 >> 2], -0.1484375149011612)
+assertEq(f32[2832 >> 2], -0.1562500149011612)
+assertEq(f32[2836 >> 2], -0.1640625149011612)
+assertEq(f32[2840 >> 2], -0.1718750149011612)
+assertEq(f32[2844 >> 2], -0.1796875149011612)
+assertEq(f32[2848 >> 2], -0.1875000149011612)
+assertEq(f32[2852 >> 2], -0.1953125149011612)
+assertEq(f32[2856 >> 2], -0.2031250149011612)
+assertEq(f32[2860 >> 2], -0.2109375149011612)
+assertEq(f32[2864 >> 2], -0.2187500149011612)
+assertEq(f32[2868 >> 2], -0.2265625149011612)
+assertEq(f32[2872 >> 2], -0.2343750149011612)
+assertEq(f32[2876 >> 2], -0.2421875149011612)
+assertEq(f32[2880 >> 2], -0.2500000298023224)
+assertEq(f32[2884 >> 2], -0.2656250298023224)
+assertEq(f32[2888 >> 2], -0.2812500298023224)
+assertEq(f32[2892 >> 2], -0.2968750298023224)
+assertEq(f32[2896 >> 2], -0.3125000298023224)
+assertEq(f32[2900 >> 2], -0.3281250298023224)
+assertEq(f32[2904 >> 2], -0.3437500298023224)
+assertEq(f32[2908 >> 2], -0.3593750298023224)
+assertEq(f32[2912 >> 2], -0.3750000298023224)
+assertEq(f32[2916 >> 2], -0.3906250298023224)
+assertEq(f32[2920 >> 2], -0.4062500298023224)
+assertEq(f32[2924 >> 2], -0.4218750298023224)
+assertEq(f32[2928 >> 2], -0.4375000298023224)
+assertEq(f32[2932 >> 2], -0.4531250298023224)
+assertEq(f32[2936 >> 2], -0.4687500298023224)
+assertEq(f32[2940 >> 2], -0.4843750298023224)
+assertEq(f32[2944 >> 2], -0.5000000596046448)
+assertEq(f32[2948 >> 2], -0.5312500596046448)
+assertEq(f32[2952 >> 2], -0.5625000596046448)
+assertEq(f32[2956 >> 2], -0.5937500596046448)
+assertEq(f32[2960 >> 2], -0.6250000596046448)
+assertEq(f32[2964 >> 2], -0.6562500596046448)
+assertEq(f32[2968 >> 2], -0.6875000596046448)
+assertEq(f32[2972 >> 2], -0.7187500596046448)
+assertEq(f32[2976 >> 2], -0.7500000596046448)
+assertEq(f32[2980 >> 2], -0.7812500596046448)
+assertEq(f32[2984 >> 2], -0.8125000596046448)
+assertEq(f32[2988 >> 2], -0.8437500596046448)
+assertEq(f32[2992 >> 2], -0.8750000596046448)
+assertEq(f32[2996 >> 2], -0.9062500596046448)
+assertEq(f32[3000 >> 2], -0.9375000596046448)
+assertEq(f32[3004 >> 2], -0.9687500596046448)
+assertEq(f32[3008 >> 2], -1.0000001192092896)
+assertEq(f32[3012 >> 2], -1.0625001192092896)
+assertEq(f32[3016 >> 2], -1.1250001192092896)
+assertEq(f32[3020 >> 2], -1.1875001192092896)
+assertEq(f32[3024 >> 2], -1.2500001192092896)
+assertEq(f32[3028 >> 2], -1.3125001192092896)
+assertEq(f32[3028 >> 2], -1.3125001192092896)
+assertEq(f32[3032 >> 2], -1.3750001192092896)
+assertEq(f32[3036 >> 2], -1.4375001192092896)
+assertEq(f32[3040 >> 2], -1.5000001192092896)
+assertEq(f32[3044 >> 2], -1.5625001192092896)
+assertEq(f32[3048 >> 2], -1.6250001192092896)
+assertEq(f32[3052 >> 2], -1.6875001192092896)
+assertEq(f32[3056 >> 2], -1.7500001192092896)
+assertEq(f32[3060 >> 2], -1.8125001192092896)
+assertEq(f32[3064 >> 2], -1.8750001192092896)
+assertEq(f32[3068 >> 2], -1.9375001192092896)
+
+assertEq(f32[3072 >> 2], 2.0625)
+assertEq(f32[3076 >> 2], 2.1875)
+assertEq(f32[3080 >> 2], 2.3125)
+assertEq(f32[3084 >> 2], 2.4375)
+assertEq(f32[3088 >> 2], 2.5625)
+assertEq(f32[3092 >> 2], 2.6875)
+assertEq(f32[3096 >> 2], 2.8125)
+assertEq(f32[3100 >> 2], 2.9375)
+assertEq(f32[3104 >> 2], 3.0625)
+assertEq(f32[3108 >> 2], 3.1875)
+assertEq(f32[3112 >> 2], 3.3125)
+assertEq(f32[3116 >> 2], 3.4375)
+assertEq(f32[3120 >> 2], 3.5625)
+assertEq(f32[3124 >> 2], 3.6875)
+assertEq(f32[3128 >> 2], 3.8125)
+assertEq(f32[3132 >> 2], 3.9375)
+assertEq(f32[3136 >> 2], 4.125)
+assertEq(f32[3140 >> 2], 4.375)
+assertEq(f32[3144 >> 2], 4.625)
+assertEq(f32[3148 >> 2], 4.875)
+assertEq(f32[3152 >> 2], 5.125)
+assertEq(f32[3156 >> 2], 5.375)
+assertEq(f32[3160 >> 2], 5.625)
+assertEq(f32[3164 >> 2], 5.875)
+assertEq(f32[3168 >> 2], 6.125)
+assertEq(f32[3172 >> 2], 6.375)
+assertEq(f32[3176 >> 2], 6.625)
+assertEq(f32[3180 >> 2], 6.875)
+assertEq(f32[3184 >> 2], 7.125)
+assertEq(f32[3188 >> 2], 7.375)
+assertEq(f32[3192 >> 2], 7.625)
+assertEq(f32[3196 >> 2], 7.875)
+assertEq(f32[3200 >> 2], 8.25)
+assertEq(f32[3204 >> 2], 8.75)
+assertEq(f32[3208 >> 2], 9.25)
+assertEq(f32[3212 >> 2], 9.75)
+assertEq(f32[3216 >> 2], 10.25)
+assertEq(f32[3220 >> 2], 10.75)
+assertEq(f32[3224 >> 2], 11.25)
+assertEq(f32[3224 >> 2], 11.25)
+assertEq(f32[3228 >> 2], 11.75)
+assertEq(f32[3232 >> 2], 12.25)
+assertEq(f32[3236 >> 2], 12.75)
+assertEq(f32[3240 >> 2], 13.25)
+assertEq(f32[3244 >> 2], 13.75)
+assertEq(f32[3248 >> 2], 14.25)
+assertEq(f32[3252 >> 2], 14.75)
+assertEq(f32[3256 >> 2], 15.25)
+assertEq(f32[3260 >> 2], 15.75)
+assertEq(f32[3264 >> 2], 16.5)
+assertEq(f32[3268 >> 2], 17.5)
+assertEq(f32[3272 >> 2], 18.5)
+assertEq(f32[3276 >> 2], 19.5)
+assertEq(f32[3280 >> 2], 20.5)
+assertEq(f32[3284 >> 2], 21.5)
+assertEq(f32[3288 >> 2], 22.5)
+assertEq(f32[3292 >> 2], 23.5)
+assertEq(f32[3296 >> 2], 24.5)
+assertEq(f32[3300 >> 2], 25.5)
+assertEq(f32[3304 >> 2], 26.5)
+assertEq(f32[3308 >> 2], 27.5)
+assertEq(f32[3312 >> 2], 28.5)
+assertEq(f32[3316 >> 2], 29.5)
+assertEq(f32[3320 >> 2], 30.5)
+assertEq(f32[3324 >> 2], 31.5)
+assertEq(f32[3328 >> 2], 0.12890625)
+assertEq(f32[3332 >> 2], 0.13671875)
+assertEq(f32[3336 >> 2], 0.14453125)
+assertEq(f32[3340 >> 2], 0.15234375)
+assertEq(f32[3344 >> 2], 0.16015625)
+assertEq(f32[3348 >> 2], 0.16796875)
+assertEq(f32[3352 >> 2], 0.17578125)
+assertEq(f32[3356 >> 2], 0.18359375)
+assertEq(f32[3360 >> 2], 0.19140625)
+assertEq(f32[3364 >> 2], 0.19921875)
+assertEq(f32[3368 >> 2], 0.20703125)
+assertEq(f32[3372 >> 2], 0.21484375)
+assertEq(f32[3376 >> 2], 0.22265625)
+assertEq(f32[3380 >> 2], 0.23046875)
+assertEq(f32[3384 >> 2], 0.23828125)
+assertEq(f32[3388 >> 2], 0.24609375)
+assertEq(f32[3392 >> 2], 0.2578125)
+assertEq(f32[3396 >> 2], 0.2734375)
+assertEq(f32[3400 >> 2], 0.2890625)
+assertEq(f32[3404 >> 2], 0.3046875)
+assertEq(f32[3408 >> 2], 0.3203125)
+assertEq(f32[3412 >> 2], 0.3359375)
+assertEq(f32[3416 >> 2], 0.3515625)
+assertEq(f32[3420 >> 2], 0.3671875)
+assertEq(f32[3424 >> 2], 0.3828125)
+assertEq(f32[3428 >> 2], 0.3984375)
+assertEq(f32[3432 >> 2], 0.4140625)
+assertEq(f32[3436 >> 2], 0.4296875)
+assertEq(f32[3440 >> 2], 0.4453125)
+assertEq(f32[3444 >> 2], 0.4609375)
+assertEq(f32[3448 >> 2], 0.4765625)
+assertEq(f32[3452 >> 2], 0.4921875)
+assertEq(f32[3456 >> 2], 0.515625)
+assertEq(f32[3460 >> 2], 0.546875)
+assertEq(f32[3464 >> 2], 0.578125)
+assertEq(f32[3468 >> 2], 0.609375)
+assertEq(f32[3472 >> 2], 0.640625)
+assertEq(f32[3476 >> 2], 0.671875)
+assertEq(f32[3480 >> 2], 0.703125)
+assertEq(f32[3484 >> 2], 0.734375)
+assertEq(f32[3488 >> 2], 0.765625)
+assertEq(f32[3492 >> 2], 0.796875)
+assertEq(f32[3496 >> 2], 0.828125)
+assertEq(f32[3500 >> 2], 0.859375)
+assertEq(f32[3504 >> 2], 0.890625)
+assertEq(f32[3508 >> 2], 0.921875)
+assertEq(f32[3512 >> 2], 0.953125)
+assertEq(f32[3516 >> 2], 0.984375)
+assertEq(f32[3520 >> 2], 1.03125)
+assertEq(f32[3524 >> 2], 1.09375)
+assertEq(f32[3528 >> 2], 1.15625)
+assertEq(f32[3532 >> 2], 1.21875)
+assertEq(f32[3536 >> 2], 1.28125)
+assertEq(f32[3540 >> 2], 1.34375)
+assertEq(f32[3544 >> 2], 1.40625)
+assertEq(f32[3548 >> 2], 1.46875)
+assertEq(f32[3552 >> 2], 1.53125)
+assertEq(f32[3556 >> 2], 1.59375)
+assertEq(f32[3560 >> 2], 1.65625)
+assertEq(f32[3564 >> 2], 1.71875)
+assertEq(f32[3568 >> 2], 1.78125)
+assertEq(f32[3572 >> 2], 1.84375)
+assertEq(f32[3576 >> 2], 1.90625)
+assertEq(f32[3580 >> 2], 1.96875)
+assertEq(f32[3584 >> 2], -2.0625)
+assertEq(f32[3588 >> 2], -2.1875)
+assertEq(f32[3592 >> 2], -2.3125)
+assertEq(f32[3596 >> 2], -2.4375)
+assertEq(f32[3600 >> 2], -2.5625)
+assertEq(f32[3604 >> 2], -2.6875)
+assertEq(f32[3608 >> 2], -2.8125)
+assertEq(f32[3612 >> 2], -2.9375)
+assertEq(f32[3616 >> 2], -3.0625)
+assertEq(f32[3620 >> 2], -3.1875)
+assertEq(f32[3624 >> 2], -3.3125)
+assertEq(f32[3624 >> 2], -3.3125)
+assertEq(f32[3628 >> 2], -3.4375)
+assertEq(f32[3632 >> 2], -3.5625)
+assertEq(f32[3636 >> 2], -3.6875)
+assertEq(f32[3640 >> 2], -3.8125)
+assertEq(f32[3644 >> 2], -3.9375)
+assertEq(f32[3648 >> 2], -4.125)
+assertEq(f32[3652 >> 2], -4.375)
+assertEq(f32[3656 >> 2], -4.625)
+assertEq(f32[3660 >> 2], -4.875)
+assertEq(f32[3664 >> 2], -5.125)
+assertEq(f32[3668 >> 2], -5.375)
+assertEq(f32[3672 >> 2], -5.625)
+assertEq(f32[3676 >> 2], -5.875)
+assertEq(f32[3680 >> 2], -6.125)
+assertEq(f32[3684 >> 2], -6.375)
+assertEq(f32[3688 >> 2], -6.625)
+assertEq(f32[3692 >> 2], -6.875)
+assertEq(f32[3696 >> 2], -7.125)
+assertEq(f32[3700 >> 2], -7.375)
+assertEq(f32[3704 >> 2], -7.625)
+assertEq(f32[3708 >> 2], -7.875)
+assertEq(f32[3712 >> 2], -8.25)
+assertEq(f32[3716 >> 2], -8.75)
+assertEq(f32[3720 >> 2], -9.25)
+assertEq(f32[3724 >> 2], -9.75)
+assertEq(f32[3728 >> 2], -10.25)
+assertEq(f32[3732 >> 2], -10.75)
+assertEq(f32[3736 >> 2], -11.25)
+assertEq(f32[3740 >> 2], -11.75)
+assertEq(f32[3744 >> 2], -12.25)
+assertEq(f32[3748 >> 2], -12.75)
+assertEq(f32[3752 >> 2], -13.25)
+assertEq(f32[3756 >> 2], -13.75)
+assertEq(f32[3760 >> 2], -14.25)
+assertEq(f32[3764 >> 2], -14.75)
+assertEq(f32[3768 >> 2], -15.25)
+assertEq(f32[3772 >> 2], -15.75)
+assertEq(f32[3776 >> 2], -16.5)
+assertEq(f32[3780 >> 2], -17.5)
+assertEq(f32[3784 >> 2], -18.5)
+assertEq(f32[3788 >> 2], -19.5)
+assertEq(f32[3792 >> 2], -20.5)
+assertEq(f32[3796 >> 2], -21.5)
+assertEq(f32[3800 >> 2], -22.5)
+assertEq(f32[3804 >> 2], -23.5)
+assertEq(f32[3808 >> 2], -24.5)
+assertEq(f32[3812 >> 2], -25.5)
+assertEq(f32[3816 >> 2], -26.5)
+assertEq(f32[3820 >> 2], -27.5)
+assertEq(f32[3824 >> 2], -28.5)
+assertEq(f32[3828 >> 2], -29.5)
+assertEq(f32[3832 >> 2], -30.5)
+assertEq(f32[3836 >> 2], -31.5)
+assertEq(f32[3840 >> 2], -0.12890625)
+assertEq(f32[3844 >> 2], -0.13671875)
+assertEq(f32[3848 >> 2], -0.14453125)
+assertEq(f32[3852 >> 2], -0.15234375)
+assertEq(f32[3856 >> 2], -0.16015625)
+assertEq(f32[3860 >> 2], -0.16796875)
+assertEq(f32[3864 >> 2], -0.17578125)
+assertEq(f32[3868 >> 2], -0.18359375)
+assertEq(f32[3872 >> 2], -0.19140625)
+assertEq(f32[3876 >> 2], -0.19921875)
+assertEq(f32[3880 >> 2], -0.20703125)
+assertEq(f32[3884 >> 2], -0.21484375)
+assertEq(f32[3888 >> 2], -0.22265625)
+assertEq(f32[3892 >> 2], -0.23046875)
+assertEq(f32[3896 >> 2], -0.23828125)
+assertEq(f32[3900 >> 2], -0.24609375)
+assertEq(f32[3904 >> 2], -0.2578125)
+assertEq(f32[3908 >> 2], -0.2734375)
+assertEq(f32[3912 >> 2], -0.2890625)
+assertEq(f32[3916 >> 2], -0.3046875)
+assertEq(f32[3920 >> 2], -0.3203125)
+assertEq(f32[3924 >> 2], -0.3359375)
+assertEq(f32[3928 >> 2], -0.3515625)
+assertEq(f32[3932 >> 2], -0.3671875)
+assertEq(f32[3936 >> 2], -0.3828125)
+assertEq(f32[3940 >> 2], -0.3984375)
+assertEq(f32[3944 >> 2], -0.4140625)
+assertEq(f32[3948 >> 2], -0.4296875)
+assertEq(f32[3952 >> 2], -0.4453125)
+assertEq(f32[3956 >> 2], -0.4609375)
+assertEq(f32[3960 >> 2], -0.4765625)
+assertEq(f32[3964 >> 2], -0.4921875)
+assertEq(f32[3968 >> 2], -0.515625)
+assertEq(f32[3972 >> 2], -0.546875)
+assertEq(f32[3976 >> 2], -0.578125)
+assertEq(f32[3980 >> 2], -0.609375)
+assertEq(f32[3984 >> 2], -0.640625)
+assertEq(f32[3988 >> 2], -0.671875)
+assertEq(f32[3992 >> 2], -0.703125)
+assertEq(f32[3996 >> 2], -0.734375)
+assertEq(f32[4000 >> 2], -0.765625)
+assertEq(f32[4004 >> 2], -0.796875)
+assertEq(f32[4008 >> 2], -0.828125)
+assertEq(f32[4012 >> 2], -0.859375)
+assertEq(f32[4016 >> 2], -0.890625)
+assertEq(f32[4020 >> 2], -0.921875)
+assertEq(f32[4024 >> 2], -0.953125)
+assertEq(f32[4024 >> 2], -0.953125)
+assertEq(f32[4028 >> 2], -0.984375)
+assertEq(f32[4032 >> 2], -1.03125)
+assertEq(f32[4036 >> 2], -1.09375)
+assertEq(f32[4040 >> 2], -1.15625)
+assertEq(f32[4044 >> 2], -1.21875)
+assertEq(f32[4048 >> 2], -1.28125)
+assertEq(f32[4052 >> 2], -1.34375)
+assertEq(f32[4056 >> 2], -1.40625)
+assertEq(f32[4060 >> 2], -1.46875)
+assertEq(f32[4064 >> 2], -1.53125)
+assertEq(f32[4068 >> 2], -1.59375)
+assertEq(f32[4072 >> 2], -1.65625)
+assertEq(f32[4076 >> 2], -1.71875)
+assertEq(f32[4080 >> 2], -1.78125)
+assertEq(f32[4084 >> 2], -1.84375)
+assertEq(f32[4088 >> 2], -1.90625)
+assertEq(f32[4092 >> 2], -1.96875)
diff --git a/js/src/jit-test/tests/asm.js/testBug975182.js b/js/src/jit-test/tests/asm.js/testBug975182.js
new file mode 100644
index 000000000..41c627148
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug975182.js
@@ -0,0 +1,20 @@
+Function("\
+ g = (function(t,foreign){\
+ \"use asm\";\
+ var ff = foreign.ff;\
+ function f() {\
+ +ff()\
+ }\
+ return f\
+ })(this, {\
+ ff: arguments.callee\
+ }, new ArrayBuffer(4096))\
+")()
+function m(f) {
+ for (var j = 0; j < 6000; ++j) {
+ f();
+ if ((j % 1000) === 0)
+ gc();
+ }
+}
+m(g);
diff --git a/js/src/jit-test/tests/asm.js/testBug989166.js b/js/src/jit-test/tests/asm.js/testBug989166.js
new file mode 100644
index 000000000..c96d19de4
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug989166.js
@@ -0,0 +1,8 @@
+(function(stdlib) {
+ "use asm";
+ var pow = stdlib.Math.pow
+ function f() {
+ return +pow(.0, .0)
+ }
+ return f
+})(this, {}, ArrayBuffer)()
diff --git a/js/src/jit-test/tests/asm.js/testBug999790.js b/js/src/jit-test/tests/asm.js/testBug999790.js
new file mode 100644
index 000000000..85f92c22f
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBug999790.js
@@ -0,0 +1,65 @@
+function CanBeConstructed(f) {
+ var caught = false;
+ try {
+ new f;
+ } catch (e) {
+ caught = true;
+ }
+ return !caught;
+}
+
+function IsConstructedFunction(f) {
+ return f.hasOwnProperty('length')
+ && f.hasOwnProperty('name')
+ && f.hasOwnProperty('prototype')
+ && f.prototype.hasOwnProperty('constructor')
+ && f.prototype.constructor === f;
+}
+
+function IsntConstructedFunction(f) {
+ return !f.hasOwnProperty('length')
+ && !f.hasOwnProperty('name')
+ && !f.hasOwnProperty('prototype')
+}
+
+var m = function() {
+ "use asm"
+ function g(){}
+ return g;
+};
+assertEq(CanBeConstructed(m), true, "asm.js modules can't be constructed");
+
+var objM = new m;
+assertEq(IsConstructedFunction(objM), true);
+
+var g = m();
+assertEq(CanBeConstructed(g), true, "asm.js functions can't be constructed");
+// g is a ctor returning an primitive value, thus an empty object
+assertEq(Object.getOwnPropertyNames(new g).length, 0);
+
+var n = function() {
+ "use asm"
+ function g(){return 42.0}
+ function h(){return 42}
+ return {
+ g: g,
+ h: h
+ };
+};
+assertEq(CanBeConstructed(n), true, "asm.js modules can't be constructed");
+
+var objN = new n;
+// objN is an object with attributes g and h
+assertEq(IsntConstructedFunction(objN), true);
+assertEq(objN.hasOwnProperty('g'), true);
+assertEq(objN.hasOwnProperty('h'), true);
+
+assertEq(IsConstructedFunction(objN.g), true);
+assertEq(IsConstructedFunction(objN.h), true);
+
+var h = n().h;
+assertEq(CanBeConstructed(h), true, "asm.js functions can't be constructed");
+// h is a ctor returning an primitive value, thus an empty object
+assertEq(Object.getOwnPropertyNames(new h).length, 0);
+
+assertEq(typeof(function() {"use asm"; return {}}.prototype) !== 'undefined', true);
diff --git a/js/src/jit-test/tests/asm.js/testBullet.js b/js/src/jit-test/tests/asm.js/testBullet.js
new file mode 100644
index 000000000..64a6377e7
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testBullet.js
@@ -0,0 +1,19 @@
+// Test a big fat asm.js module. First load/compile/cache bullet.js in a
+// separate process and then load it again in this process, which should be a
+// cache hit.
+
+setCachingEnabled(true);
+if (!isAsmJSCompilationAvailable())
+ quit();
+
+// Note: if you get some failure in this test, it probably has to do with
+// bullet.js and not the nestedShell() call, so try first commenting out
+// nestedShell() (and the loadedFromCache assertion) to see if the error
+// reproduces.
+var code = "setIonCheckGraphCoherency(false); setCachingEnabled(true); load('" + libdir + "bullet.js'); runBullet()";
+nestedShell("--js-cache", "--no-js-cache-per-process", "--execute=" + code);
+setIonCheckGraphCoherency(false);
+load(libdir + 'bullet.js');
+var results = runBullet();
+assertEq(results.asmJSValidated, true);
+assertEq(results.loadedFromCache, true);
diff --git a/js/src/jit-test/tests/asm.js/testCaching.js b/js/src/jit-test/tests/asm.js/testCaching.js
new file mode 100644
index 000000000..8029ce56b
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testCaching.js
@@ -0,0 +1,102 @@
+load(libdir + "asm.js");
+
+setCachingEnabled(true);
+if (!isAsmJSCompilationAvailable() || !isCachingEnabled())
+ quit();
+
+var body1 = "'use asm'; function f() { return 42 } function ff() { return 43 } return f";
+var m = new Function(body1);
+assertEq(isAsmJSModule(m), true);
+assertEq(m()(), 42);
+var m = new Function(body1);
+assertEq(isAsmJSModuleLoadedFromCache(m), true);
+assertEq(m()(), 42);
+var body2 = body1 + "f";
+var m = new Function(body2);
+assertEq(isAsmJSModuleLoadedFromCache(m), false);
+assertEq(m()(), 43);
+var evalStr1 = "(function() { " + body1 + "})";
+var m = eval(evalStr1);
+assertEq(isAsmJSModuleLoadedFromCache(m), false);
+assertEq(m()(), 42);
+var m = eval(evalStr1);
+assertEq(isAsmJSModuleLoadedFromCache(m), true);
+assertEq(m()(), 42);
+var evalStr2 = "(function() { " + body2 + "})";
+var m = eval(evalStr2);
+assertEq(isAsmJSModuleLoadedFromCache(m), false);
+assertEq(m()(), 43);
+var m = eval(evalStr2);
+assertEq(isAsmJSModuleLoadedFromCache(m), true);
+assertEq(m()(), 43);
+
+var evalStr3 = "(function(global) { 'use asm'; var sin=global.Math.sin; function g(d) { d=+d; return +sin(d) } return g })";
+var m = eval(evalStr3);
+assertEq(isAsmJSModule(m), true);
+assertEq(m(this)(.3), Math.sin(.3));
+var m = eval(evalStr3);
+assertEq(isAsmJSModuleLoadedFromCache(m), true);
+assertEq(m(this)(.3), Math.sin(.3));
+var evalStr4 = "(function(gobal) { 'use asm'; var sin=global.Math.sin; function g(d) { d=+d; return +sin(d) } return g })";
+var m = eval(evalStr4);
+assertEq(isAsmJSModule(m), false);
+var m = eval(evalStr3);
+assertEq(isAsmJSModuleLoadedFromCache(m), true);
+var evalStr5 = "(function(global,foreign) { 'use asm'; var sin=global.Math.sin; function g(d) { d=+d; return +sin(d) } return g })";
+var m = eval(evalStr5);
+assertEq(isAsmJSModuleLoadedFromCache(m), false);
+
+var m = new Function(body1);
+assertEq(isAsmJSModule(m), true);
+var body3 = "'use asm'; var sin=global.Math.sin; function g(d) { d=+d; return +sin(d) } return g";
+var m = new Function('global', body3);
+assertEq(isAsmJSModuleLoadedFromCache(m), false);
+assertEq(m(this)(.2), Math.sin(.2));
+var m = new Function('gobal', body3);
+assertEq(isAsmJSModule(m), false);
+var m = new Function('global', body3);
+assertEq(isAsmJSModuleLoadedFromCache(m), true);
+var m = new Function('global','foreign', body3);
+assertEq(isAsmJSModuleLoadedFromCache(m), false);
+var m = new Function('global','foreign', body3);
+assertEq(isAsmJSModuleLoadedFromCache(m), true);
+var m = new Function('gobal','foreign', body3);
+assertEq(isAsmJSModule(m), false);
+var m = new Function('global','foreign', body3);
+assertEq(isAsmJSModuleLoadedFromCache(m), true);
+var m = new Function('global','foregn', body3);
+assertEq(isAsmJSModuleLoadedFromCache(m), false);
+var m = new Function('global','foreign', 'buffer', body3);
+assertEq(isAsmJSModuleLoadedFromCache(m), false);
+var m = new Function('global','foreign', 'buffer', 'foopy', body3);
+assertEq(isAsmJSModule(m), false);
+var m = new Function('global','foreign', 'buffer', body3);
+assertEq(isAsmJSModuleLoadedFromCache(m), true);
+var m = new Function('global','foreign', 'bffer', body3);
+assertEq(isAsmJSModuleLoadedFromCache(m), false);
+var m = new Function('global','foreign', 'foreign', body3);
+assertEq(isAsmJSModule(m), false);
+
+var body = "f() { 'use asm'; function g() {} return g }";
+var evalStr6 = "(function " + body + ")";
+var evalStr7 = "(function* " + body + ")";
+var m = eval(evalStr6);
+assertEq(isAsmJSModule(m), true);
+var m = eval(evalStr6);
+assertEq(isAsmJSModuleLoadedFromCache(m), true);
+var m = eval(evalStr7);
+assertEq(isAsmJSModule(m), false);
+
+// Test caching using a separate process (which, with ASLR, should mean a
+// separate address space) to compile/cache the code. Ideally, every asmCompile
+// would do this, but that makes jit-tests run 100x slower. Do it here, for one
+// of each feature. asm.js/testBullet.js should pound on everything.
+assertEq(asmLink(asmCompileCached(USE_ASM + "function f(i) { i=i|0; return +((i+1)|0) } function g(d) { d=+d; return +(d + +f(42) + 1.5) } return g"))(.2), .2+43+1.5);
+assertEq(asmLink(asmCompileCached(USE_ASM + "function f1() { return 1 } function f2() { return 2 } function f(i) { i=i|0; return T[i&1]()|0 } var T=[f1,f2]; return f"))(1), 2);
+assertEq(asmLink(asmCompileCached("g", USE_ASM + "var s=g.Math.sin; function f(d) { d=+d; return +s(d) } return f"), this)(.3), Math.sin(.3));
+assertEq(asmLink(asmCompileCached("g","ffis", USE_ASM + "var ffi=ffis.ffi; function f(i) { i=i|0; return ffi(i|0)|0 } return f"), null, {ffi:function(i){return i+2}})(1), 3);
+assertEq(asmLink(asmCompileCached("g","ffis", USE_ASM + "var x=ffis.x|0; function f() { return x|0 } return f"), null, {x:43})(), 43);
+var i32 = new Int32Array(BUF_MIN/4);
+i32[4] = 42;
+assertEq(asmLink(asmCompileCached("g","ffis","buf", USE_ASM + "var i32=new g.Int32Array(buf); function f(i) { i=i|0; return i32[i>>2]|0 } return f"), this, null, i32.buffer)(4*4), 42);
+assertEq(asmLink(asmCompileCached('glob', USE_ASM + 'var x=glob.Math.PI; function f() { return +x } return f'), this)(), Math.PI);
diff --git a/js/src/jit-test/tests/asm.js/testCall.js b/js/src/jit-test/tests/asm.js/testCall.js
new file mode 100644
index 000000000..5d15fe257
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testCall.js
@@ -0,0 +1,75 @@
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+assertAsmTypeFail(USE_ASM+"function f(){i=i|0} function g() { f(0) } return g");
+assertAsmTypeFail(USE_ASM+"function f(i){i=i|0} function g() { f() } return g");
+assertAsmTypeFail(USE_ASM+"function f(){} function g() { f()|0 } return g");
+assertAsmTypeFail(USE_ASM+"function f(){} function g() { +f() } return g");
+assertAsmTypeFail(USE_ASM+"function f(){} function g() { return f() } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { +f() } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { f()|f() } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0.0} function g() { f()|0 } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0.0} function g() { ~~f() } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0.0} function g() { -f() } return g");
+assertAsmTypeFail(USE_ASM+"function f(i,j,k,l){i=i|0;j=j|0;k=k|0;l=l|0} function g() { f(0,1,2) } return g");
+assertAsmTypeFail(USE_ASM+"function f(i,j,k,l){i=i|0;j=j|0;k=k|0;l=l|0} function g() { f(0,1,2,3,4) } return g");
+assertAsmTypeFail(USE_ASM+"function f(i){i=i|0} function g() { f(.1) } return g");
+assertAsmTypeFail(USE_ASM+"function f(i){i=+i} function g() { f(1) } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { var i=0.1; i=f()|0 } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { var i=0.1; i=+f() } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0.1} function g() { var i=0; i=f() } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0.1} function g() { var i=0; i=f()|0 } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0.1} function g() { var i=0; i=+f() } return g");
+assertAsmTypeFail(USE_ASM+"function f(){} function g() { (1, f()) } return g");
+
+assertEq(asmLink(asmCompile(USE_ASM+"var x=0; function f() {x=42} function g() { return (f(),x)|0 } return g"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM+"function f() {return 42} function g() { return f()|0 } return g"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM+"function g(i) { i=i|0; return (i+2)|0 } function h(i) { i=i|0; return ((g(i)|0)+8)|0 } return h"))(50), 60);
+assertEq(asmLink(asmCompile(USE_ASM+"function g(i) { i=i|0; return (i+2)|0 } function h(i) { i=i|0; return ((g(i)|0)+i)|0 } return h"))(50), 102);
+assertEq(asmLink(asmCompile(USE_ASM+"function g(i) { i=+i; return +(i+.1) } function h(i) { i=+i; return +(+g(i)+.2) } return h"))(20), 20+.1+.2);
+assertEq(asmLink(asmCompile(USE_ASM+"function g(i,j) { i=i|0;j=j|0; return (i-j)|0 } function h(j,i) { j=j|0;i=i|0; return ((g(i,j)|0)+8)|0 } return h"))(10,20), 18);
+assertEq(asmLink(asmCompile(USE_ASM+"function g(i,j) { i=i|0;j=+j; return +(+~~i+j) } function h(i,j) { i=i|0;j=+j; return +(+g(i,j)+8.6) } return h"))(10, 1.5), 10+1.5+8.6);
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0; return (n-o)|0 } return f"))(1,2,3,4,5,6,100), -94);
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } return f"))(1,2,3,4,5,6,100,20), 80);
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (((o+p)|0) + ((o+p)|0))|0 } return f"))(1,2,3,4,5,6,30,20), 100);
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p,q,r) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p;q=+q;r=+r; return +(q-r) } return f"))(1,2,3,4,5,6,7,8,40.2,1.4), 40.2-1.4);
+
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0; return (n-o)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,i,j)|0 } return g"))(20,5), 15);
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,i,j)|0 } return g"))(20,5), 15);
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; return +f(0.0,0.0,0.0,0.0,0.0,0.0,i,j) } return g"))(.5, .1), .5-.1);
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; var k=0; k=(i+j)|0; return ((f(0,0,0,0,0,0,i,j)|0)+k)|0 } return g"))(20,10), 40);
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; var k=0.1; k=i+j; return +(+f(0.0,0.0,0.0,0.0,0.0,0.0,i,j)+k) } return g"))(.5, .1), (.5+.1)+(.5-.1));
+
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p,q) { i=i|0;j=j|0;k=k|0;l=l|0;m=+m;n=n|0;o=o|0;p=+p;q=q|0; return +((m-p) + +~~q) } function g(i,j,k) { i=+i;j=+j;k=k|0; return +f(0,0,0,0,j,0,0,i,k) } return g"))(.5, 20.1, 4), (20.1-.5)+4);
+
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,f(0,0,0,0,0,0,i,j)|0,j)|0 } return g"))(20,5), 10);
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,f(0,0,0,0,0,0,i,j)|0,f(0,0,0,0,0,0,j,i)|0)|0 } return g"))(20,5), 30);
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; return +f(0.0,0.0,0.0,0.0,0.0,0.0,+f(0.0,0.0,0.0,0.0,0.0,0.0,i,j),j) } return g"))(10.3, .2), 10.3-.2-.2);
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; return +f(0.0,0.0,0.0,0.0,0.0,0.0,+f(0.0,0.0,0.0,0.0,0.0,0.0,i,j),+f(0.0,0.0,0.0,0.0,0.0,0.0,j,i)) } return g"))(10.3, .2), (10.3-.2)-(.2-10.3));
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p,q) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0;q=q|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,i,f(0,0,0,0,0,0,i,j,0)|0,0)|0 } return g"))(20,5), 5);
+
+assertEq(asmLink(asmCompile(USE_ASM+"function f(i) {i=i|0; return i|0} function g() { return 42; return f(13)|0 } return g"))(), 42);
+
+assertEq(asmLink(asmCompile(USE_ASM+"function e() { return 42 } function f(i) { i=i|0; switch(i|0) { case 0: return e()|0; default: return 13 } return 0 } function g() { return f(0)|0 } return g"))(), 42);
+
+var rec = asmLink(asmCompile(USE_ASM+"function rec() { rec() } return rec"));
+assertThrowsInstanceOf(rec, InternalError);
+
+var rec = asmLink(asmCompile(USE_ASM+"function rec(i) { i=i|0; if (!i) return 0; return ((rec((i-1)|0)|0)+1)|0 } return rec"));
+assertEq(rec(100), 100);
+assertEq(rec(1000), 1000);
+assertThrowsInstanceOf(function() rec(100000000000), InternalError);
+assertEq(rec(2000), 2000);
+
+assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { var i=0; i=f() } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0.0} function g() { var i=0.0; i=f() } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { return (f()+1)|0 } return g");
+assertAsmTypeFail(USE_ASM+"function f(){return 0.0} function g() { return +(f()+1.0) } return g");
+
+assertEq(asmLink(asmCompile(USE_ASM + "const M = 42; function f() { return M } function g() { return f()|0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "const M = -42; function f() { return M } function g() { return f()|0 } return f"))(), -42);
+assertAsmTypeFail(USE_ASM + "const M = 42; function f() { return M } function g() { return +f() } return f");
+assertEq(asmLink(asmCompile(USE_ASM + "const M = 42.1; function f() { return M } function g() { return +f() } return f"))(), 42.1);
+assertAsmTypeFail(USE_ASM + "const M = 42.1; function f() { return M } function g() { return f()|0 } return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + "var tof = glob.Math.fround; const M = tof(42); function f() { return M } function g() { return tof(f()) } return f"), this)(), 42);
+assertAsmTypeFail('glob', USE_ASM + "var tof = glob.Math.fround; const M = tof(42); function f() { return M } function g() { return +f() } return f");
diff --git a/js/src/jit-test/tests/asm.js/testCloning.js b/js/src/jit-test/tests/asm.js/testCloning.js
new file mode 100644
index 000000000..e84f34303
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testCloning.js
@@ -0,0 +1,50 @@
+load(libdir + "asm.js");
+
+setCachingEnabled(true);
+
+var code = asmCompile(USE_ASM + "function g() { return 42 } return g");
+assertEq(asmLink(code)(), 42);
+assertEq(asmLink(code)(), 42);
+
+var code = evaluate("(function() { " + USE_ASM + " function g() { return 43 } return g})", {fileName: null});
+assertEq(asmLink(code)(), 43);
+assertEq(asmLink(code)(), 43);
+
+var code = asmCompile('glob', 'ffis', 'buf', USE_ASM + 'var i32=new glob.Int32Array(buf); function g() { return i32[0]|0 } return g');
+var i32_1 = new Int32Array(BUF_MIN/4);
+i32_1[0] = 42;
+var i32_2 = new Int32Array(BUF_MIN/4);
+i32_2[0] = 13;
+assertEq(asmLink(code, this, null, i32_1.buffer)(), 42);
+assertEq(asmLink(code, this, null, i32_2.buffer)(), 13);
+var i32_3 = new Int32Array(4097);
+assertAsmLinkFail(code, this, null, i32_3.buffer);
+
+var code = asmCompile('glob', 'ffis', USE_ASM + 'var ffi=ffis.ffi; function g(n) { n=n|0; var i=0; for(; (i|0)<(n|0); i=(i+1)|0) ffi() } return g');
+var calls1 = 0, calls2 = 0;
+function ffi1() { calls1++ }
+function ffi2() { calls2++ }
+asmLink(code, null, {ffi:ffi1})(100000);
+assertEq(calls1, 100000);
+assertEq(calls2, 0);
+calls1 = 0;
+asmLink(code, null, {ffi:ffi2})(50000);
+assertEq(calls1, 0);
+assertEq(calls2, 50000);
+
+var code = asmCompile(USE_ASM + 'var g = 0; function h() { g=(g+1)|0; return g|0 } return h');
+var h1 = code();
+assertEq(h1(), 1);
+assertEq(h1(), 2);
+var h2 = code();
+assertEq(h2(), 1);
+assertEq(h1(), 3);
+assertEq(h2(), 2);
+assertEq(h1(), 4);
+
+var code = asmCompile(USE_ASM + "return {}");
+var h1 = code();
+var h2 = code();
+assertEq(h1 === h2, false);
+assertEq(Object.keys(h1).length, 0);
+assertEq(Object.keys(h2).length, 0);
diff --git a/js/src/jit-test/tests/asm.js/testCompoundPlusMinus.js b/js/src/jit-test/tests/asm.js/testCompoundPlusMinus.js
new file mode 100644
index 000000000..9b070541e
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testCompoundPlusMinus.js
@@ -0,0 +1,14 @@
+load(libdir + "asm.js");
+
+assertAsmTypeFail(USE_ASM + "function f(i,j,k) { i=i|0;j=+j;k=+k; return (i+(j+k))|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f(i,j,k) { i=i|0;j=j|0;k=+k; return +((i+j)+k) } return f");
+assertAsmTypeFail('imp', USE_ASM + "var ffi=imp.ffi; function f(i) { i=i|0; return (i+ffi())|0 } return f");
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j,k) { i=i|0;j=j|0;k=k|0; return (i+j+k)|0 } return f"))(1,2,3), 6);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j,k) { i=i|0;j=j|0;k=k|0; return (i+j-k)|0 } return f"))(1,2,3), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j,k) { i=i|0;j=j|0;k=k|0; return (i-j+k)|0 } return f"))(1,2,3), 2);
+
+const INT32_MAX = Math.pow(2,31)-1;
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (i+i+i+i+i+i+i+i+i+i)|0 } return f"))(INT32_MAX), (10*INT32_MAX)|0);
+const INT32_MIN = -Math.pow(2,31);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (i+i+i+i+i+i+i+i+i+i)|0 } return f"))(INT32_MIN), (10*INT32_MIN)|0);
diff --git a/js/src/jit-test/tests/asm.js/testControlFlow.js b/js/src/jit-test/tests/asm.js/testControlFlow.js
new file mode 100644
index 000000000..40711cd6c
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testControlFlow.js
@@ -0,0 +1,374 @@
+load(libdir + "asm.js");
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=+j; if (i) return j; return j+1.0 } return f"))(0, 1.2), 1.2+1.0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=+j; if (i) return j; return +~~i } return f"))(1,1.4), 1.4);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; if (i) return j^0; return i^1 } return f"))(1, 1), 1);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; if (i) return j^0; return i|0 } return f"))(1,8), 8);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; if ((i|0) == 0) return 10; else if ((i|0) == 1) return 12; else if ((i|0) == 2) return 14; return 0} return f"))(2), 14);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; if ((i|0) == 0) return 10; else if ((i|0) == 1) return 12; else if ((i|0) == 2) return 14; else return 16; return 0} return f"))(3), 16);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; if ((i|0) == 0) i = 10; else if ((i|0) == 1) return 12; return (i|0) } return f"))(0), 10);
+
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; if (i) return 0; } return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; if (i) return 0; else return 1 } return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; if (i) return 0; return 1.0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { if (0) return 0; 1 } return f");
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { while (0) {} return 0} return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { for (;0;) {} return 0} return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { do {} while(0); return 0} return f"))(), 0);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { while (0) ; return 0} return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { for (;0;) ; return 0} return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { do ; while(0); return 0} return f"))(), 0);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { do {} while (0); while (0); return 0} return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i = 0; do {} while (0); return i|0} return f"))(), 0);
+
+assertAsmTypeFail(USE_ASM + "function f(d) {d=+d; while (d) {}; return 0} return f");
+assertAsmTypeFail(USE_ASM + "function f(d) {d=+d; for (;d;) {}; return 0} return f");
+assertAsmTypeFail(USE_ASM + "function f(d) {d=+d; do {} while (d); return 0} return f");
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f(j) {j=j|0; var i=0; while ((i|0) < (j|0)) i=(i+4)|0; return i|0} return f"))(6), 8);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(j) {j=j|0; var i=0; for (;(i|0) < (j|0);) i=(i+4)|0; return i|0} return f"))(6), 8);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(j) {j=j|0; var i=0; do { i=(i+4)|0; } while ((i|0) < (j|0)); return i|0} return f"))(6), 8);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { while(1) return 42; return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { for(;1;) return 42; return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { do return 42; while(1); return 0 } return f"))(), 42);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while(1) { if (i) return 13; return 42 } return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;1;) { if (i) return 13; return 42 } return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do { if (i) return 13; return 42 } while(1); return 0 } return f"))(), 42);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while(1) { break; while(1) {} } return 42 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;;) { break; for(;;) {} } return 42 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do { break; do {} while(1) {} } while(1); return 42 } return f"))(), 42);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=1; while(1) { if (i) return 42; return 13 } return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=1; for(;1;) { if (i) return 42; return 13 } return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=1; do { if (i) return 42; return 13 } while(1); return 0 } return f"))(), 42);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while(1) { if (i) return 13; else return 42; return 13 } return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;;) { if (i) return 13; else return 42; return 13 } return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do { if (i) return 13; else return 42; return 13 } while(1); return 0 } return f"))(), 42);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while((i|0) < 3) { if (i) return 42; i=(i+1)|0 } return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;(i|0) < 3;) { if (i) return 42; i=(i+1)|0 } return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do { if (i) return 42; i=(i+1)|0 } while((i|0) < 3); return 0 } return f"))(), 42);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while((i|0) < 3) { if (!i) i=(i+1)|0; return 42 } return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;(i|0) < 3;) { if (!i) i=(i+1)|0; return 42 } return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do { if (!i) i=(i+1)|0; return 42 } while((i|0) < 3); return 0 } return f"))(), 42);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42; return i|0; while(1) {} return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42; return i|0; for(;1;) {} return 0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42; return i|0; do {} while(1); return 0 } return f"))(), 42);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while((i|0) < 10) if ((i|0) == 4) break; else i=(i+1)|0; return i|0 } return f"))(), 4);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(; (i|0) < 10;) if ((i|0) == 4) break; else i=(i+1)|0; return i|0 } return f"))(), 4);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do if ((i|0) == 4) break; else i=(i+1)|0; while((i|0) < 10); return i|0 } return f"))(), 4);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0,sum=0; while ((i=(i+1)|0)<2) { sum=(sum+1)|0; if ((i&1)==0) continue; sum=(sum+100)|0 } return sum|0 } return f"))(), 101);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0,sum=0; for (;(i=(i+1)|0)<2;) { sum=(sum+1)|0; if ((i&1)==0) continue; sum=(sum+100)|0 } return sum|0 } return f"))(), 101);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0,sum=0; do { sum=(sum+1)|0; if ((i&1)==0) continue; sum=(sum+100)|0 } while((i=(i+1)|0)<2); return sum|0 } return f"))(), 102);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; x:a:y:while(1) { i=1; while(1) { i=2; break a; } i=3; } return i|0 } return f"))(), 2);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; x:a:y:for(;;) { i=1; while(1) { i=2; break a; } i=3; } return i|0 } return f"))(), 2);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; x:a:y:do { i=1; while(1) { i=2; break a; } i=3; } while(1); return i|0 } return f"))(), 2);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; a:b:while((i|0) < 5) { i=(i+1)|0; while(1) continue b; } return i|0 } return f"))(), 5);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; a:b:for(;(i|0) < 5;) { i=(i+1)|0; while(1) continue b; } return i|0 } return f"))(), 5);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; a:b:do { i=(i+1)|0; while(1) continue b; } while((i|0) < 5); return i|0 } return f"))(), 5);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; return 0; a:b:while((i|0) < 5) { i=(i+1)|0; while(1) continue b; } return i|0 } return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; return 0; a:b:for(;(i|0) < 5;) { i=(i+1)|0; while(1) continue b; } return i|0 } return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; return 0; a:b:do { i=(i+1)|0; while(1) continue b; } while((i|0) < 5); return i|0 } return f"))(), 0);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42; a:{ break a; i=2; } b:{ c:{ break b; i=3 } i=4 } return i|0 } return f"))(), 42);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; a:b:for(;(i|0) < 5;i=(i+1)|0) { while(1) continue b; } return i|0 } return f"))(), 5);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,sum=0; for(i=1;(i|0)<4;i=(i+1)|0) sum=(sum+i)|0; return sum|0 } return f"))(), 6);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,sum=0; for(i=1;(i|0)<8;i=(i+1)|0) { if ((i&1) == 0) continue; sum=(sum+i)|0; } return sum|0 } return f"))(), 16);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while(1) { i=(i+1)|0; if ((i|0) > 10) break; } return i|0 } return f"))(), 11);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;1;i=(i+1)|0) { if ((i|0) > 10) break; } return i|0 } return f"))(), 11);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do { if ((i|0) > 10) break; i=(i+1)|0 } while(1); return i|0 } return f"))(), 11);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; while(1){ if ((i|0)>0) break; while (1) { i=i+1|0; if ((i|0)==1) break; } } return i|0; } return f"))(), 1);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; for(;;){ if ((i|0)>0) break; while (1) { i=i+1|0; if ((i|0)==1) break; } } return i|0; } return f"))(), 1);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; do{ if ((i|0)>0) break; while (1) { i=i+1|0; if ((i|0)==1) break; } }while(1); return i|0; } return f"))(), 1);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0,sum=0; while(1){ if ((i|0)>5) break; while (1) { i=i+1|0; sum=(sum+i)|0; if ((i|0)>3) break; } } return sum|0; } return f"))(), 21);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0,sum=0; for(;;){ if ((i|0)>5) break; while (1) { i=i+1|0; sum=(sum+i)|0; if ((i|0)>3) break; } } return sum|0; } return f"))(), 21);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0,sum=0; do{ if ((i|0)>5) break; while (1) { i=i+1|0; sum=(sum+i)|0; if ((i|0)>3) break; } }while(1); return sum|0; } return f"))(), 21);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; while(1) { if (i) { break; } else { return i|0 } i = 1 } return i|0 } return f"))(3), 3);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; for(;1;) { if (i) { break; } else { return i|0 } i = 1 } return i|0 } return f"))(3), 3);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; do { if (i) { break; } else { return i|0 } i = 1 } while (0); return i|0 } return f"))(3), 3);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; while(1) { if (i) { return i|0 } else { return i|0 } i = 1 } return i|0 } return f"))(3), 3);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; for(;;) { if (i) { return i|0 } else { return i|0 } i = 1 } return i|0 } return f"))(3), 3);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; do { if (i) { return i|0 } else { return i|0 } i = 1 } while (0); return i|0 } return f"))(3), 3);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {var j=1,i=0; while(j){ if(0) continue; j=i } return j|0 } return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {var j=1,i=0; for(;j;){ if(0) continue; j=i } return j|0 } return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {var j=1,i=0; do{ if(0) continue; j=i } while(j) return j|0 } return f"))(), 0);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; for(;;) { return i|0 } return 0 } return f"))(42), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(n) { n=n|0; var i=0,s=0; for(;;i=(i+1)|0) { if (~~i==~~n) return s|0; s=(s+i)|0 } return 0 } return f"))(8), 28);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(n,m) { n=n|0;m=m|0; var i=0,sum=0; while((n|0)>(m|0) ? ((i|0)<(n|0))|0 : ((i|0)<(m|0))|0) { sum = (sum+i)|0; i=(i+1)|0 } return sum|0 } return f"));
+assertEq(f(1,5), 10);
+assertEq(f(6,5), 15);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(n,m) { n=n|0;m=m|0; var i=0,sum=0; for(; (n|0)>(m|0) ? ((i|0)<(n|0))|0 : ((i|0)<(m|0))|0; i=(i+1)|0) { sum = (sum+i)|0 } return sum|0 } return f"));
+assertEq(f(1,5), 10);
+assertEq(f(6,5), 15);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(n,m) { n=n|0;m=m|0; var i=0,sum=0; do { sum = (sum+i)|0; i=(i+1)|0 } while((n|0)>(m|0) ? ((i|0)<(n|0))|0 : ((i|0)<(m|0))|0); return sum|0 } return f"));
+assertEq(f(1,5), 10);
+assertEq(f(6,5), 15);
+
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case 1: return 0; case 1: return 0 } return 0} return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case 1: return 0; case 2: return 0; case 1: return 0 } return 0} return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; switch(1) { case 1: return 0; case 1: return 0 } return 0} return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0; switch(i) {}; return i|0 } return f");
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) {}; return i|0 } return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) { default: i=42 } return i|0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) { default: i=42; break } return i|0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) { case 0: i=42 } return i|0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) { case 0: i=42; break } return i|0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) { case 0: default: i=42 } return i|0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=0; switch(i|0) { case 0: default: i=42; break } return i|0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=1; switch(i|0) { case 0: case 2: break; default: i=42 } return i|0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=1; switch(i|0) { case 0: case 2: break; default: i=42; break } return i|0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 42; switch(1) { case 1: return 13 } return 14 } return f"))(), 42);
+
+var exp = asmLink(asmCompile(USE_ASM + "var x=0; function a() { return x|0 } function b(i) { i=i|0; x=i } function c(i) { i=i|0; if (i) b(i); } return {a:a,b:b,c:c}"));
+assertEq(exp.c(10), undefined);
+assertEq(exp.a(), 10);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case 1: i=-1; break; case 133742: i=2; break; default: i=42; break } return i|0 } return f"));
+assertEq(f(1), -1);
+assertEq(f(2), 42);
+assertEq(f(133742), 2);
+assertEq(f(133743), 42);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case 1: i=42; break; default: i=13 } return i|0 } return f"));
+assertEq(f(-1), 13);
+assertEq(f(0), 13);
+assertEq(f(1), 42);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case -1: i=42; break; default: i=13 } return i|0 } return f"));
+assertEq(f(-1), 42);
+assertEq(f(0), 13);
+assertEq(f(1), 13);
+assertEq(f(0xffffffff), 42);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var sum=0; switch(i|0) { case -1: sum=(sum+1)|0; case 1: sum=(sum+1)|0; case 3: sum=(sum+1)|0; default: sum=(sum+100)|0; } return sum|0 } return f"));
+assertEq(f(-1), 103);
+assertEq(f(0), 100);
+assertEq(f(1), 102);
+assertEq(f(2), 100);
+assertEq(f(3), 101);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var sum=0; switch(i|0) { case -1: sum=10; break; case 1: sum=11; break; case 3: sum=12; break; default: sum=13; } return sum|0 } return f"));
+assertEq(f(-1), 10);
+assertEq(f(0), 13);
+assertEq(f(1), 11);
+assertEq(f(2), 13);
+assertEq(f(3), 12);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=8,sum=0; a:for(; (i|0)<20; i=(i+1)|0) { switch(i&3) { case 0:case 1:sum=(sum+i)|0;break;case 2:sum=(sum+100)|0;continue;default:break a} sum=(sum+10)|0; } sum=(sum+1000)|0; return sum|0 } return f"))(), 1137);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { a: do{break a;}while(0); a: do{break a;}while(0); return 42 } return f"))(), 42);
+assertEq(asmLink(asmCompile('g', USE_ASM + "function f() { g:{ return 42 } return 13 } return f"), null)(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(x) {x=x|0;switch (x|0) {case 31:return 13;case 9: {x = 3;if ((x|0) <= 0) {return -1;}}}return 1;} return f"))(31), 13);
+
+var imp = { ffi:function() { throw "Wrong" } };
+assertEq(asmLink(asmCompile('glob','imp', USE_ASM + "var ffi=imp.ffi; function f() { var i=0; return (i+1)|0; return ffi(i|0)|0 } return f"), null, imp)(), 1);
+
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() {var k = 1;if (1) {for(k = 1; k|0; k=k-1|0) {}} return 1}; return f'))(), 1);
+
+// Ternaries conditionals
+//
+// Basic ternaries
+var f = asmLink(asmCompile(USE_ASM + "function f() { return 0; if (1) return -1; return -2} return f"));
+assertEq(f(5), 0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(x) { x=x|0; var a=2;if(x?1:0)a=1;else a=0; return a|0 } return f"));
+assertEq(f(1), 1);
+assertEq(f(0), 0);
+
+var guard = (function() {
+ var called_ = false;
+ return {
+ called: function(){ return called_ },
+ call: function(){ called_ = true }
+ }
+})();
+
+var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + "var func=ffi.func; function f(x) { x=x|0; var a=2;if(x?1:1)a=1; else {func();a=0}return a|0 } return f"), this, {func: guard.call});
+assertEq(f(1), 1);
+assertEq(f(0), 1);
+assertEq(guard.called(), false);
+
+var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + "var func=ffi.func; function f(x) { x=x|0; var a=2;if(x?0:0){a=1; func()}else a=0;return a|0 } return f"), this, {func: guard.call});
+assertEq(f(1), 0);
+assertEq(f(0), 0);
+assertEq(guard.called(), false);
+
+var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + "var func=ffi.func; function f(x,y) { x=x|0;y=y|0; var a=2;if(x?func()|0:y)a=1;else a=0; return a|0 } return f"), this, {func: guard.call});
+assertEq(f(0,1), 1);
+assertEq(guard.called(), false);
+
+var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + "var func=ffi.func; function f(x,y) { x=x|0;y=y|0; var a=2;if(x?y:func()|0)a=1;else a=0; return a|0 } return f"), this, {func: guard.call});
+assertEq(f(1,0), 0);
+assertEq(guard.called(), false);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y) { x=x|0;y=y|0; var a=2;if(x?0:y)a=1;else a=0; return a|0 } return f"));
+assertEq(f(1,1), 0);
+assertEq(f(1,0), 0);
+assertEq(f(0,0), 0);
+assertEq(f(0,1), 1);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y) { x=x|0;y=y|0; var a=2;if(x?y:1)a=1;else a=0; return a|0 } return f"));
+assertEq(f(1,1), 1);
+assertEq(f(1,0), 0);
+assertEq(f(0,0), 1);
+assertEq(f(0,1), 1);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2;if(x?y:z)a=1;else a=0; return a|0 } return f"));
+for (var i = 0; i < 2; ++i)
+ for (var j = 0; j < 2; ++j)
+ for (var k = 0; k < 2; ++k)
+ assertEq(f(i,j,k), ((i && j) || (!i && k))|0);
+
+// Complex ternaries
+function CheckTwoArgsTwoOptions(f) {
+ function check(x,y) {
+ return (x > 2 && y < 5) | 0;
+ }
+ for (var a = -10; a < 10; a++)
+ for (var b = -10; b < 10; b++)
+ assertEq(f(a,b), check(a,b));
+}
+
+function CheckThreeArgsTwoOptions(f) {
+ function check(x,y,z) {
+ return (x > 2 && y < 5 && z > -1) | 0;
+ }
+ for (var a = -10; a < 10; a++)
+ for (var b = -10; b < 10; b++)
+ for (var c = -10; c < 10; c++)
+ assertEq(f(a,b,c), check(a,b,c));
+}
+
+// Ternaries with && semantics
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y) { x=x|0;y=y|0; var z=0; if((x|0) > 2 ? (y|0) < 5 : 0) z=1; return z|0;} return f"));
+CheckTwoArgsTwoOptions(f);
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y) { x=x|0;y=y|0; var z=2; if((x|0) > 2 ? (y|0) < 5 : 0) z=1; else z=0; return z|0;} return f"));
+CheckTwoArgsTwoOptions(f);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=0; if((x|0) > 2 ? ((y|0) < 5 ? (z|0) > -1 : 0) : 0) a=1; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if((x|0) > 2 ? ((y|0) < 5 ? (z|0) > -1 : 0) : 0) a=1; else a=0; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=0; if((x|0) > 2 ? (y|0) < 5 : 0) {if ((z|0) > -1) a=1}; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if((x|0) > 2 ? (y|0) < 5 : 0) {if ((z|0) > -1) a=1; else a=0;} else a=0; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=0; if(((x|0) == 3 ? 1 : ((x|0) > 3)) ? ((y|0) < 5 ? (z|0) > -1 : 0) : 0) a=1; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if(((x|0) == 3 ? 1 : ((x|0) > 3)) ? ((y|0) < 5 ? (z|0) > -1 : 0) : 0) a=1; else a=0; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=0; if((x|0) == 3 ? 1 : (x|0) > 3) {if ((y|0) < 5 ? (z|0) > -1 : 0) a=1;} return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if((x|0) == 3 ? 1 : (x|0) > 3) {if ((y|0) < 5 ? (z|0) > -1 : 0) a=1; else a=0;} else a=0; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+
+// Ternaries with || semantics
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y) { x=x|0;y=y|0; var z=1; if((x|0) <= 2 ? 1 : (y|0) >= 5) z=0; return z|0;} return f"));
+CheckTwoArgsTwoOptions(f);
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y) { x=x|0;y=y|0; var z=2; if((x|0) <= 2 ? 1 : (y|0) >= 5) z=0; else z=1; return z|0;} return f"));
+CheckTwoArgsTwoOptions(f);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=1; if((x|0) <= 2 ? 1 : ((y|0) >= 5 ? 1 : (z|0) <= -1)) a=0; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if((x|0) <= 2 ? 1 : ((y|0) >= 5 ? 1 : (z|0) <= -1)) a=0; else a=1; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=1; if((x|0) <= 2 ? 1 : (y|0) >= 5) a=0; else if ((z|0) <= -1) a=0; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if((x|0) <= 2 ? 1 : (y|0) >= 5) a=0; else if ((z|0) <= -1) a=0; else a=1; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=1; if(((x|0) != 3 ? ((x|0) <= 3) : 0) ? 1 : ((y|0) >= 5 ? 1 : (z|0) <= -1)) a=0; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+var f = asmLink(asmCompile(USE_ASM + "function f(x,y,z) { x=x|0;y=y|0;z=z|0; var a=2; if(((x|0) != 3 ? ((x|0) <= 3) : 0) ? 1 : ((y|0) >= 5 ? 1 : (z|0) <= -1)) a=0; else a=1; return a|0;} return f"));
+CheckThreeArgsTwoOptions(f);
+
+// Massive test
+var code = '"use asm";\
+ function g(x,y) {\
+ x=x|0;\
+ y=y|0;\
+ var z = 0;\
+ if ((y|0) == 1337) {\
+ z = 1;\
+ } else if ((x|0) == 1 ? 1 : ((x|0) < 0 ? (y|0) == 1 : 0)) {\
+ z = 2;\
+ } else if ((x|0) == 2) {\
+ z = 3;\
+ } else if ((x|0) == 3 ? 1 : (x|0) == 4) {\
+ z = 4;\
+ } else if ((x|0) == 5 ? (y|0) > 5 : 0) {\
+ z = 5;\
+ } else {\
+ z = 6;\
+ }\
+ return z|0;\
+ }\
+ return g;';
+
+var m = asmLink(asmCompile(code));
+
+assertEq(m(0, 1337), 1);
+assertEq(m(0, 1338), 6);
+assertEq(m(0, 0), 6);
+assertEq(m(0, 1), 6);
+assertEq(m(0, 1336), 6);
+assertEq(m(1, 1337), 1);
+assertEq(m(2, 1337), 1);
+assertEq(m(3, 1337), 1);
+assertEq(m(4, 1337), 1);
+assertEq(m(5, 1337), 1);
+
+assertEq(m(1, 10), 2);
+assertEq(m(1, 1336), 2);
+assertEq(m(-1, 10), 6);
+assertEq(m(-1, 2), 6);
+assertEq(m(-1, -1), 6);
+assertEq(m(-1, 1), 2);
+assertEq(m(-9, 1), 2);
+
+assertEq(m(2, 1), 3);
+assertEq(m(2, 0), 3);
+assertEq(m(2, 6), 3);
+
+assertEq(m(3, 1), 4);
+assertEq(m(3, 0), 4);
+assertEq(m(3, 6), 4);
+assertEq(m(3, 3), 4);
+assertEq(m(4, 1), 4);
+assertEq(m(4, 0), 4);
+assertEq(m(4, 6), 4);
+assertEq(m(4, 3), 4);
+
+assertEq(m(5, -1), 6);
+assertEq(m(5, 4), 6);
+assertEq(m(5, 5), 6);
+assertEq(m(5, 6), 5);
+assertEq(m(5, 10), 5);
diff --git a/js/src/jit-test/tests/asm.js/testDebugModeDisables.js b/js/src/jit-test/tests/asm.js/testDebugModeDisables.js
new file mode 100644
index 000000000..56b1c4dde
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testDebugModeDisables.js
@@ -0,0 +1,9 @@
+// |jit-test|
+
+load(libdir + "asm.js");
+
+// Turn on debugging for the current global.
+var g = newGlobal();
+var dbg = new g.Debugger(this);
+
+assertAsmTypeFail("'use asm'; function f() {} return f");
diff --git a/js/src/jit-test/tests/asm.js/testExpressions.js b/js/src/jit-test/tests/asm.js/testExpressions.js
new file mode 100644
index 000000000..0e04ac0db
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testExpressions.js
@@ -0,0 +1,403 @@
+load(libdir + "asm.js");
+
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i+j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i+j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i-j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i-j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i*j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i*j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0; return (i*j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0; return (i*1048576)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0; return (i*-1048576)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0; return (i + (j*4))|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var two30 = 1073741824; return (((two30 * 524288 * 16) + 1) & 1)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i/j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i/j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=1,j=1; return (i/j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i%j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i%j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0.0,j=0; return (i<j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0.0; return (i<j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0; return (i<j)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0.0; return (-i)|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0; return (-(i+j))|0 } return f");
+
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0,k=0; k = (i|0)/(k|0) } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0,k=0; k = (i>>>0)/(k>>>0) } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0,k=0; k = (i|0)%(k|0) } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var i=0,j=0,k=0; k = (i>>>0)%(k>>>0) } return f");
+
+const UINT32_MAX = Math.pow(2,32)-1;
+const INT32_MIN = -Math.pow(2,31);
+const INT32_MAX = Math.pow(2,31)-1;
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (i*2)|0 } return f"));
+assertEq(f(0), 0);
+assertEq(f(INT32_MIN), (2*INT32_MIN)|0);
+assertEq(f(INT32_MAX), (2*INT32_MAX)|0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (2*i)|0 } return f"));
+assertEq(f(0), 0);
+assertEq(f(INT32_MIN), (2*INT32_MIN)|0);
+assertEq(f(INT32_MAX), (2*INT32_MAX)|0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (i*1048575)|0 } return f"));
+assertEq(f(0), 0);
+assertEq(f(2), (1048575*2)|0);
+assertEq(f(-1), (1048575*-1)|0);
+assertEq(f(INT32_MIN), (1048575*INT32_MIN)|0);
+assertEq(f(INT32_MAX), (1048575*INT32_MAX)|0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (1048575*i)|0 } return f"));
+assertEq(f(0), 0);
+assertEq(f(2), (1048575*2)|0);
+assertEq(f(-1), (1048575*-1)|0);
+assertEq(f(INT32_MIN), (1048575*INT32_MIN)|0);
+assertEq(f(INT32_MAX), (1048575*INT32_MAX)|0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=0; j=~i; return j|0 } return f"));
+assertEq(f(0), ~0);
+assertEq(f(3), ~3);
+assertEq(f(-3), ~-3);
+assertEq(f(INT32_MAX), ~INT32_MAX);
+assertEq(f(INT32_MIN), ~INT32_MIN);
+assertEq(f(UINT32_MAX), ~UINT32_MAX);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=+i; var j=0; j=~~i; return j|0 } return f"));
+assertEq(f(0), 0);
+assertEq(f(3.5), 3);
+assertEq(f(-3.5), -3);
+assertEq(f(INT32_MAX), INT32_MAX);
+assertEq(f(INT32_MIN), INT32_MIN);
+assertEq(f(UINT32_MAX), -1);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=0.0; j=+~~i; return +j } return f"));
+assertEq(f(0), 0);
+assertEq(f(INT32_MAX), INT32_MAX);
+assertEq(f(INT32_MIN), INT32_MIN);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=0.1; j=+(i>>>0); return +j } return f"));
+assertEq(f(0), 0);
+assertEq(f(INT32_MAX), INT32_MAX);
+assertEq(f(UINT32_MAX), UINT32_MAX);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return (-i)|0 } return f"));
+assertEq(f(0), 0);
+assertEq(f(-0), 0);
+assertEq(f(1), -1);
+assertEq(f(INT32_MAX), INT32_MIN+1);
+assertEq(f(INT32_MIN), INT32_MIN);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=+i; return +(-i) } return f"));
+assertEq(f(0), -0);
+assertEq(f(-0), 0);
+assertEq(f(-1), 1);
+assertEq(f(1), -1);
+assertEq(f(Math.pow(2,50)), -Math.pow(2,50));
+assertEq(f(1.54e20), -1.54e20);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i|0) < (j|0))|0 } return f"));
+assertEq(f(0, 1), 1);
+assertEq(f(1, 0), 0);
+assertEq(f(1, 1), 0);
+assertEq(f(INT32_MIN, INT32_MAX), 1);
+assertEq(f(INT32_MAX, INT32_MIN), 0);
+assertEq(f(0, INT32_MAX), 1);
+assertEq(f(INT32_MAX, 0), 0);
+assertEq(f(INT32_MIN, 0), 1);
+assertEq(f(0, INT32_MIN), 0);
+assertEq(f(UINT32_MAX, 0), 1);
+assertEq(f(0, UINT32_MAX), 0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i>>>0) < (j>>>0))|0 } return f"));
+assertEq(f(0, 1), 1);
+assertEq(f(1, 0), 0);
+assertEq(f(1, 1), 0);
+assertEq(f(INT32_MIN, INT32_MAX), 0);
+assertEq(f(INT32_MAX, INT32_MIN), 1);
+assertEq(f(0, INT32_MAX), 1);
+assertEq(f(INT32_MAX, 0), 0);
+assertEq(f(INT32_MIN, 0), 0);
+assertEq(f(0, INT32_MIN), 1);
+assertEq(f(UINT32_MAX, 0), 0);
+assertEq(f(0, UINT32_MAX), 1);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)==(j|0); return k|0 } return f"));
+assertEq(f(1,2), 0);
+assertEq(f(1,1), 1);
+assertEq(f(2,1), 0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)!=(j|0); return k|0 } return f"));
+assertEq(f(1,2), 1);
+assertEq(f(1,1), 0);
+assertEq(f(2,1), 1);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)<(j|0); return k|0 } return f"));
+assertEq(f(1,2), 1);
+assertEq(f(1,1), 0);
+assertEq(f(1,0), 0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)>(j|0); return k|0 } return f"));
+assertEq(f(1,2), 0);
+assertEq(f(1,1), 0);
+assertEq(f(1,0), 1);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)<=(j|0); return k|0 } return f"));
+assertEq(f(1,2), 1);
+assertEq(f(1,1), 1);
+assertEq(f(1,0), 0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k=0; k=(i|0)>=(j|0); return k|0 } return f"));
+assertEq(f(1,2), 0);
+assertEq(f(1,1), 1);
+assertEq(f(1,0), 1);
+
+assertEq(asmLink(asmCompile(USE_ASM + "const I=2; function f(i) { i=i|0; var k=0; k=(i|0)<I; return k|0 } return f"))(1), 1);
+assertEq(asmLink(asmCompile(USE_ASM + "const I=2; function f(i) { i=i|0; var k=0; k=(i>>>0)<I; return k|0 } return f"))(1), 1);
+assertEq(asmLink(asmCompile(USE_ASM + "const I=-2; function f(i) { i=i|0; var k=0; k=(i|0)<I; return k|0 } return f"))(-1), 0);
+assertAsmTypeFail(USE_ASM + "const I=-2; function f(i) { i=i|0; var k=0; k=(i>>>0)<I; return k|0 } return f");
+assertAsmTypeFail(USE_ASM + "const I=0x80000000; function f(i) { i=i|0; var k=0; k=(i|0)<I; return k|0 } return f");
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i|0)/(j|0))|0 } return f"));
+assertEq(f(4,2), 2);
+assertEq(f(3,2), 1);
+assertEq(f(3,-2), -1);
+assertEq(f(-3,-2), 1);
+assertEq(f(0, -1), 0);
+assertEq(f(0, INT32_MAX), 0);
+assertEq(f(0, INT32_MIN), 0);
+assertEq(f(INT32_MAX, 0), 0);
+assertEq(f(INT32_MIN, 0), 0);
+assertEq(f(-1, INT32_MAX), 0);
+assertEq(f(-1, INT32_MIN), 0);
+assertEq(f(INT32_MAX, -1), -INT32_MAX);
+assertEq(f(INT32_MIN, -1), INT32_MIN); // !!
+assertEq(f(INT32_MAX, INT32_MAX), 1);
+assertEq(f(INT32_MAX, INT32_MIN), 0);
+assertEq(f(INT32_MIN, INT32_MAX), -1);
+assertEq(f(INT32_MIN, INT32_MIN), 1);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i>>>0)/(j>>>0))|0 } return f"));
+assertEq(f(4,2), 2);
+assertEq(f(3,2), 1);
+assertEq(f(3,-2), 0);
+assertEq(f(-3,-2), 0);
+assertEq(f(0, -1), 0);
+assertEq(f(0, INT32_MAX), 0);
+assertEq(f(0, INT32_MIN), 0);
+assertEq(f(0, UINT32_MAX), 0);
+assertEq(f(INT32_MAX, 0), 0);
+assertEq(f(INT32_MIN, 0), 0);
+assertEq(f(UINT32_MAX, 0), 0);
+assertEq(f(-1, INT32_MAX), 2);
+assertEq(f(-1, INT32_MIN), 1);
+assertEq(f(-1, UINT32_MAX), 1);
+assertEq(f(INT32_MAX, -1), 0);
+assertEq(f(INT32_MIN, -1), 0);
+assertEq(f(UINT32_MAX, -1), 1);
+assertEq(f(INT32_MAX, INT32_MAX), 1);
+assertEq(f(INT32_MAX, INT32_MIN), 0);
+assertEq(f(UINT32_MAX, INT32_MAX), 2);
+assertEq(f(INT32_MAX, UINT32_MAX), 0);
+assertEq(f(UINT32_MAX, UINT32_MAX), 1);
+assertEq(f(INT32_MIN, INT32_MAX), 1);
+assertEq(f(INT32_MIN, UINT32_MAX), 0);
+assertEq(f(INT32_MIN, INT32_MIN), 1);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k = 0; k = (i|0)%(j|0)|0; return k|0 } return f"));
+assertEq(f(4,2), 0);
+assertEq(f(3,2), 1);
+assertEq(f(3,-2), 1);
+assertEq(f(-3,-2), -1);
+assertEq(f(0, -1), 0);
+assertEq(f(0, INT32_MAX), 0);
+assertEq(f(0, INT32_MIN), 0);
+assertEq(f(INT32_MAX, 0), 0);
+assertEq(f(INT32_MIN, 0), 0);
+assertEq(f(-1, INT32_MAX), -1);
+assertEq(f(-1, INT32_MIN), -1);
+assertEq(f(INT32_MAX, -1), 0);
+assertEq(f(INT32_MIN, -1), 0); // !!
+assertEq(f(INT32_MAX, INT32_MAX), 0);
+assertEq(f(INT32_MAX, INT32_MIN), INT32_MAX);
+assertEq(f(INT32_MIN, INT32_MAX), -1);
+assertEq(f(INT32_MIN, INT32_MIN), 0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k = 0; k = (i|0)%4|0; return k|0 } return f"));
+assertEq(f(0), 0);
+assertEq(f(-1), -1);
+assertEq(f(-3), -3);
+assertEq(f(-4), 0);
+assertEq(f(INT32_MIN), 0);
+assertEq(f(3), 3);
+assertEq(f(4), 0);
+assertEq(f(INT32_MAX), 3);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var k = 0; k = (i>>>0)%(j>>>0)|0; return k|0 } return f"));
+assertEq(f(4,2), 0);
+assertEq(f(3,2), 1);
+assertEq(f(3,-2), 3);
+assertEq(f(-3,-2), -3);
+assertEq(f(0, -1), 0);
+assertEq(f(0, INT32_MAX), 0);
+assertEq(f(0, INT32_MIN), 0);
+assertEq(f(0, UINT32_MAX), 0);
+assertEq(f(INT32_MAX, 0), 0);
+assertEq(f(INT32_MIN, 0), 0);
+assertEq(f(UINT32_MAX, 0), 0);
+assertEq(f(-1, INT32_MAX), 1);
+assertEq(f(-1, INT32_MIN), INT32_MAX);
+assertEq(f(-1, UINT32_MAX), 0);
+assertEq(f(INT32_MAX, -1), INT32_MAX);
+assertEq(f(INT32_MIN, -1), INT32_MIN);
+assertEq(f(UINT32_MAX, -1), 0);
+assertEq(f(INT32_MAX, INT32_MAX), 0);
+assertEq(f(INT32_MAX, INT32_MIN), INT32_MAX);
+assertEq(f(UINT32_MAX, INT32_MAX), 1);
+assertEq(f(INT32_MAX, UINT32_MAX), INT32_MAX);
+assertEq(f(UINT32_MAX, UINT32_MAX), 0);
+assertEq(f(INT32_MIN, INT32_MAX), 1);
+assertEq(f(INT32_MIN, UINT32_MAX), INT32_MIN);
+assertEq(f(INT32_MIN, INT32_MIN), 0);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (4 / 2)|0 } return f"))(), 2);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (3 / 2)|0 } return f"))(), 1);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (4 % 2)|0 } return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (3 % 2)|0 } return f"))(), 1);
+
+assertAsmTypeFail(USE_ASM + "function f() { var i=42,j=1.1; return +(i?i:j) } return f");
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 0; 1 ? 1 : 1; return 0; } return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,j=1.1; return +(i?+(i|0):j) } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,j=1; return (i?i:j)|0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var i=42,j=1; return 13; return (i?i:j)|0 } return f"))(), 13);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (0 > (-(~~1) >>> 0)) | 0; } return f"))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 0 < 4294967294 | 0; } return f"))(), 1);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return ((i|0)>(j|0)?(i+10)|0:(j+100)|0)|0 } return f"));
+assertEq(f(2, 4), 104);
+assertEq(f(-2, -4), 8);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j,k) { i=i|0;j=j|0;k=k|0; return ((i|0)>(j|0) ? (i|0)>(k|0) ? i : k : (j|0)>(k|0) ? j : k)|0 } return f"));
+assertEq(f(1,2,3), 3);
+assertEq(f(1,3,2), 3);
+assertEq(f(2,1,3), 3);
+assertEq(f(2,3,1), 3);
+assertEq(f(3,1,2), 3);
+assertEq(f(3,2,1), 3);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; var a=0,b=0; a=i>>>0 < 4294967292; b=(i|0) < -4; return (j ? a : b)|0 } return f"));
+assertEq(f(1,true), 1);
+assertEq(f(-1,true), 0);
+assertEq(f(-5,true), 1);
+assertEq(f(1,false), 0);
+assertEq(f(-1,false), 0);
+assertEq(f(-5,false), 1);
+
+assertAsmTypeFail('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return (i32[0]+1)|0 } return f");
+new Float64Array(BUF_64KB)[0] = 2.3;
+assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return +(f64[0] + 2.0) } return f"), this, null, BUF_64KB)(), 2.3+2);
+assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return +(f64[0] - 2.0) } return f"), this, null, BUF_64KB)(), 2.3-2);
+assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return +(f64[0] * 2.0) } return f"), this, null, BUF_64KB)(), 2.3*2);
+assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return +(f64[0] / 2.0) } return f"), this, null, BUF_64KB)(), 2.3/2);
+assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return +(f64[0] % 2.0) } return f"), this, null, BUF_64KB)(), 2.3%2);
+assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "function f() { return +-f64[0] } return f"), this, null, BUF_64KB)(), -2.3);
+assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "var sqrt=glob.Math.sqrt; function f() { return +sqrt(f64[0]) } return f"), this, null, BUF_64KB)(), Math.sqrt(2.3));
+new Int32Array(BUF_64KB)[0] = 42;
+assertEq(asmLink(asmCompile('glob','imp','b', USE_ASM + HEAP_IMPORTS + "var imul=glob.Math.imul; function f() { return imul(i32[0], 2)|0 } return f"), this, null, BUF_64KB)(), 84);
+
+// beware ye phis of comparisons and integers
+var f = asmLink(asmCompile(USE_ASM + "function g(i) { i=i|0; if (i) { i = ((i|0) == 2); } else { i=(i-1)|0 } return i|0; } return g "));
+assertEq(f(0), -1);
+assertEq(f(1), 0);
+assertEq(f(2), 1);
+var f = asmLink(asmCompile(USE_ASM + "function g(i) { i=i|0; if (i) { i = !i } else { i=(i-1)|0 } return i|0; } return g "));
+assertEq(f(0), -1);
+assertEq(f(1), 0);
+assertEq(f(2), 0);
+
+// beware ye constant-evaluate of boolean-producing operators
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (4 | (2 == 2))|0 } return f"))(), 5);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (4 | (!2))|0 } return f"))(), 4);
+
+// get that order-of-operations right!
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob','imp','buf', USE_ASM + "var i32=new glob.Int32Array(buf); var x=0; function a() { return x|0 } function b() { x=42; return 0 } function f() { i32[((b()|0) & 0x3) >> 2] = a()|0 } return f"), this, null, buf)();
+assertEq(new Int32Array(buf)[0], 42);
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { var a=0,i=0; for (; ~~i!=4; i=(i+1)|0) { a = (a*5)|0; if (+(a>>>0) != 0.0) return 1; } return 0; } return f"))(), 0)
+
+// Signed integer division by a power of two.
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return ((i|0)/1)|0; } return f;"));
+for (let i = 0; i < 31; i++) {
+ assertEq(f(Math.pow(2,i)), Math.pow(2,i));
+ assertEq(f(Math.pow(2,i)-1), Math.pow(2,i)-1);
+ assertEq(f(-Math.pow(2,i)), -Math.pow(2,i));
+ assertEq(f(-Math.pow(2,i)-1), -Math.pow(2,i)-1);
+}
+assertEq(f(INT32_MIN), INT32_MIN);
+assertEq(f(INT32_MAX), INT32_MAX);
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return ((i|0)/2)|0; } return f;"));
+for (let i = 0; i < 31; i++) {
+ assertEq(f(Math.pow(2,i)), (Math.pow(2,i)/2)|0);
+ assertEq(f(Math.pow(2,i)-1), ((Math.pow(2,i)-1)/2)|0);
+ assertEq(f(-Math.pow(2,i)), (-Math.pow(2,i)/2)|0);
+ assertEq(f(-Math.pow(2,i)-1), ((-Math.pow(2,i)-1)/2)|0);
+}
+assertEq(f(INT32_MIN), (INT32_MIN/2)|0);
+assertEq(f(INT32_MAX), (INT32_MAX/2)|0);
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return ((i|0)/4)|0; } return f;"));
+for (let i = 0; i < 31; i++) {
+ assertEq(f(Math.pow(2,i)), (Math.pow(2,i)/4)|0);
+ assertEq(f(Math.pow(2,i)-1), ((Math.pow(2,i)-1)/4)|0);
+ assertEq(f(-Math.pow(2,i)), (-Math.pow(2,i)/4)|0);
+ assertEq(f(-Math.pow(2,i)-1), ((-Math.pow(2,i)-1)/4)|0);
+}
+assertEq(f(INT32_MIN), (INT32_MIN/4)|0);
+assertEq(f(INT32_MAX), (INT32_MAX/4)|0);
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return ((i|0)/1073741824)|0; } return f;"));
+for (let i = 0; i < 31; i++) {
+ assertEq(f(Math.pow(2,i)), (Math.pow(2,i)/Math.pow(2,30))|0);
+ assertEq(f(Math.pow(2,i)-1), ((Math.pow(2,i)-1)/Math.pow(2,30))|0);
+ assertEq(f(-Math.pow(2,i)), (-Math.pow(2,i)/Math.pow(2,30))|0);
+ assertEq(f(-Math.pow(2,i)-1), ((-Math.pow(2,i)-1)/Math.pow(2,30))|0);
+}
+assertEq(f(INT32_MIN), (INT32_MIN/Math.pow(2,30))|0);
+assertEq(f(INT32_MAX), (INT32_MAX/Math.pow(2,30))|0);
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return ((((i|0)/1)|0)+i)|0; } return f;"));
+for (let i = 0; i < 31; i++) {
+ assertEq(f(Math.pow(2,i)), (Math.pow(2,i) * 2)|0);
+ assertEq(f(Math.pow(2,i) - 1), ((Math.pow(2,i) - 1) * 2)|0);
+ assertEq(f(-Math.pow(2,i)), (-Math.pow(2,i) * 2)|0);
+ assertEq(f(-Math.pow(2,i) - 1), ((-Math.pow(2,i) - 1) * 2)|0);
+}
+assertEq(f(INT32_MIN), (INT32_MIN * 2)|0);
+assertEq(f(INT32_MAX), (INT32_MAX * 2)|0);
+
+// Signed integer division by a power of two - with a non-negative numerator!
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; i=(i&2147483647)|0; return ((i|0)/1)|0; } return f;"));
+for (let i = 0; i < 31; i++) {
+ assertEq(f(Math.pow(2,i)), Math.pow(2,i));
+ assertEq(f(Math.pow(2,i+1)-1), Math.pow(2,i+1)-1);
+}
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; i=(i&2147483647)|0; return ((i|0)/2)|0; } return f;"));
+for (let i = 0; i < 31; i++) {
+ assertEq(f(Math.pow(2,i)), (Math.pow(2,i)/2)|0);
+ assertEq(f(Math.pow(2,i+1)-1), ((Math.pow(2,i+1)-1)/2)|0);
+}
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; i=(i&2147483647)|0; return ((i|0)/4)|0; } return f;"));
+for (let i = 0; i < 31; i++) {
+ assertEq(f(Math.pow(2,i)), (Math.pow(2,i)/4)|0);
+ assertEq(f(Math.pow(2,i+1)-1), ((Math.pow(2,i+1)-1)/4)|0);
+}
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; i=(i&2147483647)|0; return ((i|0)/1073741824)|0; } return f;"));
+for (let i = 0; i < 31; i++) {
+ assertEq(f(Math.pow(2,i)), (Math.pow(2,i)/Math.pow(2,30))|0);
+ assertEq(f(Math.pow(2,i+1)-1), ((Math.pow(2,i+1)-1)/Math.pow(2,30))|0);
+}
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; i=(i&2147483647)|0; return ((((i|0)/1)|0)+i)|0; } return f;"));
+for (let i = 0; i < 31; i++) {
+ assertEq(f(Math.pow(2,i)), (Math.pow(2,i) * 2)|0);
+ assertEq(f(Math.pow(2,i+1) - 1), ((Math.pow(2,i+1) - 1) * 2)|0);
+}
+assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f(x, y) { x = x|0; y = y|0; g = (x>>>0)%(y>>>0)|0; return (x|0)%(y|0)|0; } return f;"))(0xff40001, 0xfff80000), 0x40001);
diff --git a/js/src/jit-test/tests/asm.js/testFFI.js b/js/src/jit-test/tests/asm.js/testFFI.js
new file mode 100644
index 000000000..cc6b5af20
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testFFI.js
@@ -0,0 +1,164 @@
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+function ffi(a,b,c,d) {
+ return a+b+c+d;
+}
+
+var f = asmLink(asmCompile('global','imp', USE_ASM + 'var ffi=imp.ffi; function g() { return 1 } function f() { var i=0; i=g()|0; return ((ffi(4,5,6,7)|0)+i)|0 } return f'), null, {ffi:ffi});
+assertEq(f(1), 23);
+
+var counter = 0;
+function inc() { return counter++ }
+function add1(x) { return x+1 }
+function add2(x,y) { return x+y }
+function add3(x,y,z) { return x+y+z }
+function addN() {
+ var sum = 0;
+ for (var i = 0; i < arguments.length; i++)
+ sum += arguments[i];
+ return sum;
+}
+var imp = { inc:inc, add1:add1, add2:add2, add3:add3, addN:addN, identity: x => x };
+
+assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { incc() } return f');
+assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { var i = 0; return (i + inc)|0 } return f');
+assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { inc = 0 } return f');
+assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return (inc() + 1)|0 } return f');
+assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return +((inc()|0) + 1.1) } return f');
+assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return +(inc() + 1.1) } return f');
+assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return (+inc() + 1)|0 } return f');
+assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { var i = 0; inc(i>>>0) } return f');
+assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { if (0) return inc(); return } return f');
+assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { inc(inc()) } return f');
+assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { g(inc()) } function g() {} return f');
+assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { inc()|inc() } return f');
+
+assertAsmLinkFail(asmCompile('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return inc()|0 } return f'), null, {});
+assertAsmLinkFail(asmCompile('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return inc()|0 } return f'), null, {inc:0});
+assertAsmLinkFail(asmCompile('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return inc()|0 } return f'), null, {inc:{}});
+
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var inc=imp.inc; function g() { inc() } return g'), null, imp)(), undefined);
+assertEq(counter, 1);
+
+var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var inc=imp.inc; function g() { return inc()|0 } return g'), null, imp);
+assertEq(f(), 1);
+assertEq(counter, 2);
+assertEq(f(), 2);
+assertEq(counter, 3);
+
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add1=imp.add1; function g(i) { i=i|0; return add1(i|0)|0 } return g'), null, imp)(9), 10);
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'const add1=imp.add1; function g(i) { i=i|0; return add1(i|0)|0 } return g'), null, imp)(9), 10);
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add3=imp.add3; function g() { var i=1,j=3,k=9; return add3(i|0,j|0,k|0)|0 } return g'), null, imp)(), 13);
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'const add3=imp.add3; function g() { var i=1,j=3,k=9; return add3(i|0,j|0,k|0)|0 } return g'), null, imp)(), 13);
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add3=imp.add3; function g() { var i=1.4,j=2.3,k=32.1; return +add3(i,j,k) } return g'), null, imp)(), 1.4+2.3+32.1);
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'const add3=imp.add3; function g() { var i=1.4,j=2.3,k=32.1; return +add3(i,j,k) } return g'), null, imp)(), 1.4+2.3+32.1);
+
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add3=imp.add3; function f(i,j,k) { i=i|0;j=+j;k=k|0; return add3(i|0,j,k|0)|0 } return f'), null, imp)(1, 2.5, 3), 6);
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var addN=imp.addN; function f() { return +addN(1,2,3,4.1,5,6.1,7,8.1,9.1,10,11.1,12,13,14.1,15.1,16.1,17.1,18.1) } return f'), null, imp)(), 1+2+3+4.1+5+6.1+7+8.1+9.1+10+11.1+12+13+14.1+15.1+16.1+17.1+18.1);
+
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add2=imp.add2; function f(i,j) { i=i|0;j=+j; return +(+(add2(i|0,1)|0) + +add2(j,1) + +add2(+~~i,j)) } return f'), null, imp)(2, 5.5), 3+(5.5+1)+(2+5.5));
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var addN=imp.addN; function f(i,j) { i=i|0;j=+j; return +(+addN(i|0,j,3,j,i|0) + +addN() + +addN(j,j,j)) } return f'), null, imp)(1, 2.2), (1+2.2+3+2.2+1)+(2.2+2.2+2.2));
+
+counter = 0;
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var addN=imp.addN,inc=imp.inc; function f() { return ((addN(inc()|0,inc(3.3)|0,inc()|0)|0) + (addN(inc(0)|0)|0))|0 } return f'), null, imp)(), 6);
+assertEq(counter, 4);
+
+var recurse = function(i,j) { if (i == 0) return j; return f(i-1,j+1)+j }
+imp.recurse = recurse;
+var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var r=imp.recurse; function f(i,j) { i=i|0;j=+j; return +r(i|0,j) } return f'), null, imp);
+assertEq(f(0,3.3), 3.3);
+assertEq(f(1,3.3), 3.3+4.3);
+assertEq(f(2,3.3), 3.3+4.3+5.3);
+
+function maybeThrow(i, j) {
+ if (i == 0)
+ throw j;
+ try {
+ return f(i-1, j);
+ } catch(e) {
+ assertEq(typeof e, "number");
+ return e;
+ }
+}
+var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i, j) { i=i|0;j=j|0; return ffi(i|0, (j+1)|0)|0 } return f'), null, {ffi:maybeThrow});
+assertThrowsValue(function() { f(0,0) }, 1);
+assertThrowsValue(function() { f(0,Math.pow(2,31)-1) }, -Math.pow(2,31));
+assertEq(f(1,0), 2);
+assertEq(f(2,0), 3);
+assertEq(f(3,0), 4);
+assertEq(f(4,5), 10);
+
+var recurse = function(i,j) { if (i == 0) throw j; f(i-1,j) }
+var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function g(i,j,k) { i=i|0;j=+j;k=k|0; if (!(k|0)) ffi(i|0,j)|0; else g(i, j+1.0, (k-1)|0) } function f(i,j) { i=i|0;j=+j; g(i,j,4) } return f'), null, {ffi:recurse});
+assertThrowsValue(function() { f(0,2.4) }, 2.4+4);
+assertThrowsValue(function() { f(1,2.4) }, 2.4+8);
+assertThrowsValue(function() { f(8,2.4) }, 2.4+36);
+
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var identity=imp.identity; function g(x) { x=+x; return +identity(x) } return g'), null, imp)(13.37), 13.37);
+
+// Test asm.js => ion paths
+setJitCompilerOption("ion.warmup.trigger", 10);
+setJitCompilerOption("baseline.warmup.trigger", 0);
+setJitCompilerOption("offthread-compilation.enable", 0);
+
+// In registers on x64 and ARM, on the stack for x86
+function ffiIntFew(a,b,c,d) { return d+1 }
+var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=i|0; return ffi(i|0,(i+1)|0,(i+2)|0,(i+3)|0)|0 } return f'), null, {ffi:ffiIntFew});
+for (var i = 0; i < 40; i++)
+ assertEq(f(i), i+4);
+
+// Stack and registers for x64 and ARM, stack for x86
+function ffiIntMany(a,b,c,d,e,f,g,h,i,j) { return j+1 }
+var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=i|0; return ffi(i|0,(i+1)|0,(i+2)|0,(i+3)|0,(i+4)|0,(i+5)|0,(i+6)|0,(i+7)|0,(i+8)|0,(i+9)|0)|0 } return f'), null, {ffi:ffiIntMany});
+for (var i = 0; i < 15; i++)
+ assertEq(f(i), i+10);
+
+// In registers on x64 and ARM, on the stack for x86
+function ffiDoubleFew(a,b,c,d) { return d+1 }
+var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=+i; return +ffi(i,i+1.0,i+2.0,i+3.0) } return f'), null, {ffi:ffiDoubleFew});
+for (var i = 0; i < 15; i++)
+ assertEq(f(i), i+4);
+
+// Stack and registers for x64 and ARM, stack for x86
+function ffiDoubleMany(a,b,c,d,e,f,g,h,i,j) { return j+1 }
+var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=+i; return +ffi(i,i+1.0,i+2.0,i+3.0,i+4.0,i+5.0,i+6.0,i+7.0,i+8.0,i+9.0) } return f'), null, {ffi:ffiDoubleMany});
+for (var i = 0; i < 15; i++)
+ assertEq(f(i), i+10);
+
+// Test the throw path
+function ffiThrow(n) { if (n == 14) throw 'yolo'; }
+var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=i|0; ffi(i >> 0); } return f'), null, {ffi:ffiThrow});
+var i = 0;
+try {
+ for (; i < 15; i++)
+ f(i);
+ throw 'assume unreachable';
+} catch (e) {
+ assertEq(e, 'yolo');
+ assertEq(i, 14);
+}
+
+// OOL conversion paths
+var INT32_MAX = Math.pow(2, 31) - 1;
+function ffiOOLConvertInt(n) { if (n == 40) return valueToConvert; return 42; }
+var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=i|0; return ffi(i >> 0) | 0; } return f'), null, {ffi:ffiOOLConvertInt});
+for (var i = 0; i < 40; i++)
+ assertEq(f(i), 42);
+valueToConvert = INT32_MAX + 1;
+assertEq(f(40), INT32_MAX + 1 | 0);
+function testBadConversions(f) {
+ valueToConvert = {valueOf: function () { throw "FAIL"; }};
+ assertThrowsValue(() => f(40), "FAIL");
+ valueToConvert = Symbol();
+ assertThrowsInstanceOf(() => f(40), TypeError);
+}
+testBadConversions(f);
+
+function ffiOOLConvertDouble(n) { if (n == 40) return valueToConvert; return 42.5; }
+var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function f(i) { i=i|0; return +ffi(i >> 0); } return f'), null, {ffi:ffiOOLConvertDouble});
+for (var i = 0; i < 40; i++)
+ assertEq(f(i), 42.5);
+valueToConvert = {valueOf: function() { return 13.37 }};
+assertEq(f(40), 13.37);
+testBadConversions(f);
diff --git a/js/src/jit-test/tests/asm.js/testFastHeapAccess.js b/js/src/jit-test/tests/asm.js/testFastHeapAccess.js
new file mode 100644
index 000000000..09bd89693
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testFastHeapAccess.js
@@ -0,0 +1,81 @@
+load(libdir + "asm.js");
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; u32[((i<<2)+32 & 0xffff)>>2] = j } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+for (var i = 0; i < 100; i++)
+ f(i, i);
+var u32 = new Uint32Array(BUF_64KB);
+for (var i = 0; i < 100; i++)
+ assertEq(u32[8+i], i);
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return u32[((i<<2)+32 & 0xffff)>>2]|0 } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+for (var i = 0; i < 100; i++)
+ assertEq(f(i), i);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; u32[(i<<2 & 0xffff)>>2] = j } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+for (var i = 0; i < 100; i++)
+ f(i, i);
+var u32 = new Uint32Array(BUF_64KB);
+for (var i = 0; i < 100; i++)
+ assertEq(u32[i], i);
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return u32[(i<<2 & 0xffff)>>2]|0 } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+for (var i = 0; i < 100; i++)
+ assertEq(f(i), i);
+
+// For legacy compatibility, test Int8/Uint8 accesses with no shift.
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; u8[i+20 & 0xffff] = j } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+for (var i = 0; i < 100; i++)
+ f(i, i);
+var u8 = new Uint8Array(BUF_64KB);
+for (var i = 0; i < 100; i++)
+ assertEq(u8[i+20], i);
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return u8[i+20 & 0xffff]|0 } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+for (var i = 0; i < 100; i++)
+ assertEq(f(i), i);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; u8[(i+20 & 0xffff)>>0] = j } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+for (var i = 0; i < 100; i++)
+ f(i, i);
+var u8 = new Uint8Array(BUF_64KB);
+for (var i = 0; i < 100; i++)
+ assertEq(u8[i+20], i);
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return u8[(i+20 & 0xffff)>>0]|0 } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+for (var i = 0; i < 100; i++)
+ assertEq(f(i), i);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j,k) {i=i|0;j=j|0;k=k|0; i32[(i + (j<<2) & 0xffff) >> 2] = k } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+for (var i = 0; i < 100; i++)
+ f(32, i, i);
+var u32 = new Uint32Array(BUF_64KB);
+for (var i = 0; i < 100; i++)
+ assertEq(u32[8+i], i);
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; return i32[(i + (j<<2) & 0xffff) >> 2]|0 } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+for (var i = 0; i < 100; i++)
+ assertEq(f(32, i), i);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j,k) {i=i|0;j=j|0;k=k|0; i32[(((i + (j<<2))|0) + 16 & 0xffff) >> 2] = k } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+for (var i = 0; i < 100; i++)
+ f(32, i, i);
+var u32 = new Uint32Array(BUF_64KB);
+for (var i = 0; i < 100; i++)
+ assertEq(u32[8+i+4], i);
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; return i32[(((i + (j<<2))|0) + 16 & 0xffff) >> 2]|0 } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+for (var i = 0; i < 100; i++)
+ assertEq(f(32, i), i);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=j|0; return ((i32[(i+(j<<2)&0xffff)>>2]|0) + (i32[(((i+(j<<2))|0)+4&0xffff)>>2]|0))|0 } return f');
+var f = asmLink(code, this, null, BUF_64KB);
+var i32 = new Uint32Array(BUF_64KB);
+i32[11] = 3;
+i32[12] = 97;
+assertEq(f(12,8), 100);
diff --git a/js/src/jit-test/tests/asm.js/testFloat32.js b/js/src/jit-test/tests/asm.js/testFloat32.js
new file mode 100644
index 000000000..34f893b07
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testFloat32.js
@@ -0,0 +1,321 @@
+load(libdir + "asm.js");
+const TO_FLOAT32 = "var toF = glob.Math.fround;";
+const HEAP32 = "var f32 = new glob.Float32Array(heap);";
+const HEAP64 = "var f64 = new glob.Float64Array(heap);"
+var heap = new ArrayBuffer(BUF_MIN);
+
+// Module linking
+assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() {} return f"), null);
+assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() {} return f"), {fround: Math.fround});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() {} return f"), {Math: {fround: Math.imul}});
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() {} return f"), {Math:{fround: Math.fround}})(), undefined);
+
+// Argument coercions
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = unknown(x); } return f");
+assertAsmTypeFail('glob', USE_ASM + "function f(i) { i = toF(i); } return f");
+assertAsmTypeFail('glob', USE_ASM + "var cos = glob.Math.cos; function f(x) { x = cos(x); } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(); } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x, x); } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF('hi'); } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(loat); } return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(i) { i = toF(i); } return f"), this)(), undefined);
+
+// Local variables declarations
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = unknown(); } return f");
+assertAsmTypeFail('glob', USE_ASM + "var cos = glob.Math.cos; function f() { var i = cos(); } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(); } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(x, x); } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF('hi'); } return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5); } return f"), this)(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); } return f"), this)(), undefined);
+
+// Return values
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(4, 4); } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(); } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF({}); } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(x); } return f");
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(42); } return f"), this)(), 42);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(0.); } return f"), this)(), 0);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(-0.); } return f"), this)(), -0);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var inf = glob.Infinity; function f() { return toF(inf); } return f"), this)(), Infinity);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(13.37); } return f"), this)(), Math.fround(13.37));
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return +toF(4.); } return f"), this)(), 4);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return +~~toF(4.5); } return f"), this)(), 4);
+
+// Assign values
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); i = 5; return toF(i); } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); i = 6.; return toF(i); } return f");
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(-0.); return toF(i); } return f"), this)(), -0);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(0.); return toF(i); } return f"), this)(), 0);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); return toF(i); } return f"), this)(), 5);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); i = toF(42); return toF(i); } return f"), this)(), 42);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); i = toF(6.); return toF(i); } return f"), this)(), 6);
+
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { var i = toF(5.); f32[0] = toF(6.); i = f32[0]; return toF(i); } return f");
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { var i = toF(5.); f32[0] = toF(6.); i = toF(f32[0]); return toF(i); } return f"), this, null, heap)(), 6);
+
+// Special array assignments (the other ones are tested in testHeapAccess)
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { var i = 5.; f32[0] = i; return toF(f32[0]); } return f"), this, null, heap)(), 5);
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "var f64 = new glob.Float64Array(heap); function f() { var i = toF(5.); f64[0] = i; return +f64[0]; } return f"), this, null, heap)(), 5);
+
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 1.5; return +f32[0]; } return f"), this, null, heap)(), 1.5);
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + HEAP64 + "function f() { f64[0] = 1.5; return toF(f64[0]); } return f"), this, null, heap)(), 1.5);
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + HEAP64 + "function f() { f32[0] = toF(42); f64[0] = f32[0]; return +f64[0]; } return f"), this, null, heap)(), 42);
+
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = toF(-1.4013e-45) / toF(42.); } return f"), this, null, heap)(), undefined);
+
+// Coercions
+// -> from Float32
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var n = 0; n = toF(4.5) | 0; } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { var i = toF(5.); var n = 0; n = i | 0; return n | 0; } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x); var n = 0; n = ~~(x + x) >>> 0; return n | 0; } return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x); var n = 0.; n = +x; return +n; } return f"), this)(16.64), Math.fround(16.64));
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x); var n = 0; n = ~~x; return n | 0; } return f"), this)(16.64), 16);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x); var n = 0; n = ~~x >>> 0; return n | 0; } return f"), this)(16.64), 16);
+
+// -> from float?
+function makeCoercion(coercionFunc) {
+ return USE_ASM + HEAP32 + TO_FLOAT32 + "function f(x) { x = toF(x); f32[0] = x; return " + coercionFunc('f32[0]') + " } return f";
+}
+assertAsmTypeFail('glob', 'ffi', 'heap', makeCoercion(x => x + '|0'));
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', makeCoercion(x => '+' + x)), this, null, heap)(16.64), Math.fround(16.64));
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', makeCoercion(x => 'toF(' + x + ')')), this, null, heap)(16.64), Math.fround(16.64));
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', makeCoercion(x => '~~+' + x + '|0')), this, null, heap)(16.64), 16);
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', makeCoercion(x => '~~toF(' + x + ')|0')), this, null, heap)(16.64), 16);
+
+// -> to Float32
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = x|0; return toF(~~x); } return f"), this)(23), 23);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = x|0; return toF(x >> 0); } return f"), this)(23), 23);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = +x; return toF(x); } return f"), this)(13.37), Math.fround(13.37));
+
+UINT32_MAX = Math.pow(2, 32)-1;
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = x|0; return toF(x >>> 0); } return f"), this)(-1), Math.fround(UINT32_MAX));
+var tof = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = x|0; return toF(x>>>0) } return f"), this);
+for (x of [0, 1, 10, 64, 1025, 65000, Math.pow(2,30), Math.pow(2,31), Math.pow(2,32)-2, Math.pow(2,32)-1])
+ assertEq(tof(x), Math.fround(x));
+
+// Global variables imports
+assertAsmTypeFail('glob', USE_ASM + "var x = toF(); function f() {} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = some(3); function f() {} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = toF(); function f() {} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = toF(3, 4); function f() {} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = toF({x: 3}); function f() {} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = toF(true); function f() {} return f");
+assertAsmTypeFail('glob', USE_ASM + "var x = toF(3);" + TO_FLOAT32 + "function f() {} return f");
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var x = toF(3.5); function f() {} return f"), this)(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var x = toF(3); function f() {} return f"), this)(), undefined);
+assertEq(asmLink(asmCompile('glob', 'ffi', USE_ASM + TO_FLOAT32 + "var x = toF(ffi.x); function f() {} return f"), this, {x:3})(), undefined);
+assertEq(asmLink(asmCompile('glob', 'ffi', USE_ASM + TO_FLOAT32 + "var x = toF(ffi.x); function f() {} return f"), this, {x:3.5})(), undefined);
+
+// Global variables uses
+values = [2.01, 13.37, -3.141592653]
+specials = [NaN, Infinity]
+
+for (v of values) {
+ assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var x = toF(" + v + "); function f() {return toF(x);} return f"), this)(), Math.fround(v));
+ assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "const x = toF(" + v + "); function f() {return toF(x);} return f"), this)(), Math.fround(v));
+ assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var x = toF(0.); function f() {x = toF(" + v + "); return toF(x);} return f"), this)(), Math.fround(v));
+ assertEq(asmLink(asmCompile('glob', 'ffi', USE_ASM + TO_FLOAT32 + "var x = toF(ffi.x); function f() {return toF(x);} return f"), this, {x:v})(), Math.fround(v));
+}
+
+for (v of specials) {
+ assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var special = glob." + v + "; var g=toF(0.); function f() {g=toF(special); return toF(g);} return f"), this)(), Math.fround(v));
+}
+
+// Math builtins
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var imul = glob.Math.imul; function f() {var x = toF(1.5), y = toF(2.4); return imul(x, y) | 0;} return f");
+
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var abs = glob.Math.abs; function f() {var x = toF(1.5); return abs(x) | 0;} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var abs = glob.Math.abs; function f() {var x = toF(1.5); return +abs(x);} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var abs = glob.Math.abs; function f() {var x = toF(1.5); return +toF(abs(x));} return f"), this)(), 1.5);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var abs = glob.Math.abs; function f() {var x = toF(1.5); return toF(abs(x))} return f"), this)(), Math.fround(1.5));
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var abs = glob.Math.abs; function f() {var x = toF(-1.5); return toF(abs(x))} return f"), this)(), Math.fround(1.5));
+
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(1.5); return sqrt(x) | 0;} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(1.5); return +sqrt(x);} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(1.5); return +toF(sqrt(x));} return f"), this)(), Math.fround(Math.sqrt(Math.fround(1.5))));
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(2.25); return toF(sqrt(x))} return f"), this)(), Math.fround(1.5));
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(-1.); return toF(sqrt(x))} return f"), this)(), NaN);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; var inf = glob.Infinity; function f() {var x = toF(0.); x = toF(inf); return toF(sqrt(x))} return f"), this)(), Infinity);
+
+// float?s
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f(x) { x = toF(x); f32[0] = x; return toF(sqrt(f32[0])) } return f"), this, null, heap)(64), Math.fround(8));
+
+// The only other Math functions that can receive float32 as arguments and that strictly commute are floor and ceil (see
+// also bug 969203).
+var floorModule = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.floor; function f(x) {x = toF(x); return toF(g(x))} return f"), this);
+for (v of [-10.5, -1.2345, -1, 0, 1, 3.141592653, 13.37, Math.Infinity, NaN])
+ assertEq(floorModule(v), Math.fround(Math.floor(Math.fround(v))));
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var floor = glob.Math.floor; function f(x) { x = toF(x); f32[0] = x; return toF(floor(f32[0])) } return f"), this, null, heap)(13.37), 13);
+
+var ceilModule = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.ceil; function f(x) {x = toF(x); return toF(g(x))} return f"), this);
+for (v of [-10.5, -1.2345, -1, 0, 1, 3.141592653, 13.37, Math.Infinity, NaN])
+ assertEq(ceilModule(v), Math.fround(Math.ceil(Math.fround(v))));
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var ceil = glob.Math.ceil; function f(x) { x = toF(x); f32[0] = x; return toF(ceil(f32[0])) } return f"), this, null, heap)(13.37), 14);
+
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = toF(x); return toF(g(x))} return f");
+
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = toF(x); return +(g(x))} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = x|0; return toF(g(x))} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = toF(x); return g(x) | 0} return f");
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = +x; return toF(g(+x))} return f"), this)(5), Math.fround(Math.cos(5)));
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = +x; return toF(g(x))} return f"), this)(5), Math.fround(Math.cos(5)));
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) { x = toF(x); return toF(+g(+x)) } return f"), this, null, heap)(3.14159265358), -1);
+
+// Math functions with arity of two are not specialized for floats, so we shouldn't feed them with floats arguments or
+// return type
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return toF(g(x, 2.))} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return +g(x, 2.)} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return toF(g(+x, 2.))} return f"), this)(3), 9);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return +g(+x, 2.)} return f"), this)(3), 9);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return toF(+g(+x, 2.))} return f"), this)(3), 9);
+
+// Other function calls
+// -> Signature comparisons
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function g(x){x=toF(x); return toF(x);} function f() {var x=toF(4.); var y=toF(0.); var z = 0.; y=toF(g(x)); z = +g(x); return toF(z); } return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt=glob.Math.sqrt; function g(x){x=toF(x); return toF(sqrt(x));} function f() {var x=toF(4.); var y=toF(0.); var z = 0.; y = toF(g(x)); z = +toF(g(x)); return toF(z); } return f"), this)(), 2);
+
+// -> FFI
+var FFI = "var ffi = env.ffi;";
+assertAsmTypeFail('glob', 'env', USE_ASM + TO_FLOAT32 + FFI + "function f() {var x = toF(3.14); return +ffi(x);} return f");
+assertAsmTypeFail('glob', 'env', USE_ASM + TO_FLOAT32 + FFI + "function f() {var x = toF(3.14); return toF(ffi(+x));} return f");
+
+var env = {ffi: function(x) { return x+1; }}; // use registers
+assertEq(asmLink(asmCompile('glob', 'env', USE_ASM + TO_FLOAT32 + FFI + "function f(x) {x = toF(x); return toF(+ffi(+x));} return f"), this, env)(5), Math.fround(6));
+env = {ffi: function(a,b,c,d,e,f,g,h,i) { return a+b+c+d+e+f+g+h+i; }}; // use stack arguments (> 8 arguments on linux x64)
+assertEq(asmLink(asmCompile('glob', 'env', USE_ASM + TO_FLOAT32 + FFI + "function f(x) {x = toF(x); return toF(+ffi(+x, 1., 2., 3., 4., 5., -5., -4., 1.));} return f"), this, env)(5), Math.fround(12));
+
+// -> Internal calls
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function g(x){x=toF(x);return toF(+x + 1.);} function f(x) {x = +x; return toF(g(x));} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function g(x){x=toF(x);return toF(+x + 1.);} function f(x) {x = x|0; return toF(g(x));} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function g(x){x=toF(x);return toF(+x + 1.);} function f(x) {x = x|0; return toF(g(x));} return f");
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function g(x){x=toF(x);return toF(+x + 1.);} function f(x) {x = toF(x); return toF(g(x));} return f"), this, env)(5), Math.fround(6));
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function g(x,y){x=toF(x);y=toF(y);return toF(+x + +y);} function f(x) {x = toF(x); return toF(g(x, toF(1.)));} return f"), this, env)(5), Math.fround(6));
+
+// --> internal calls with unused return values
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = 4; function s(x) { x = +x; g = (g + ~~x)|0; return g|0;} function f(x) { x = +x; toF(s(x)); return g|0} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = 4; function s(x) { x = +x; g = (g + ~~x)|0; return toF(g|0);} function f(x) { x = +x; toF(s(x)); return g|0} return f"), this)(3), 7);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = 4; function s(x) { x = toF(x); g = (g + ~~x)|0; return toF(g|0);} function f(x) { x = toF(x); return (toF(s(x)), g)|0} return f"), this)(3), 7);
+
+// --> coerced calls
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = 4; function s(x) { x = toF(x); g = (g + ~~x)|0; return +(g|0);} function f(x) { x = toF(x); return toF(+s(x))} return f"), this)(3), 7);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = 4; function s(x) { x = toF(x); g = (g + ~~x)|0; return g|0;} function f(x) { x = toF(x); return toF(s(x)|0)} return f"), this)(3), 7);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = 4; function s(x) { x = toF(x); g = (g + ~~x)|0; return toF(g|0);} function f(x) { x = toF(x); return toF(toF(s(x)))} return f"), this)(3), 7);
+
+// --> test pressure on registers in internal calls when there are |numArgs| arguments
+for (numArgs of [5, 9, 17, 33, 65, 129]) {
+ let code = (function(n) {
+ let args = "", coercions = "", sum = "", call="x";
+ for (let i = 0; i < n; i++) {
+ let name = 'a' + i;
+ args += name + ((i == n-1)?'':',');
+ coercions += name + '=toF(' + name + ');';
+ sum += ((i>0)?'+':'') + ' +' + name;
+ call += (i==0)?'':',toF(' + i + '.)'
+ }
+ return "function g(" + args + "){" + coercions + "return toF(" + sum + ");}"
+ +"function f(x) { x = toF(x); return toF(g(" + call + "))}";
+ })(numArgs);
+ assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + code + "return f"), this, env)(5), Math.fround(5 + numArgs * (numArgs-1) / 2));
+}
+
+// -> Pointer calls
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function a(x){x=toF(x);return toF(+x + .5);} function b(x){x=toF(x);return toF(+x - .5);} function f(x, n) {x=+x;n=n|0;return toF(t[n&1](x));} var t=[a,b]; return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function a(x){x=toF(x);return toF(+x + .5);} function b(x){x=toF(x);return toF(+x - .5);} function f(x, n) {x=x|0;n=n|0;return toF(t[n&1](x));} var t=[a,b]; return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function a(x){x=toF(x);return toF(+x + .5);} function b(x){x=toF(x);return toF(+x - .5);} function f(x, n) {x=toF(x);n=n|0;return t[n&1](x)|0;} var t=[a,b]; return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function a(x){x=toF(x);return toF(+x + .5);} function b(x){x=toF(x);return toF(+x - .5);} function f(x, n) {x=toF(x);n=n|0;return +t[n&1](x);} var t=[a,b]; return f");
+
+code = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function a(x){x=toF(x);return toF(+x + .5);} function b(x){x=toF(x);return toF(+x - .5);}"
+ + "function f(x, n) {x=toF(x);n=n|0;return toF(t[n&1](x));} var t=[a,b]; return f"), this);
+assertEq(code(0, 0), .5);
+assertEq(code(0, 1), -.5);
+assertEq(code(13.37, 0), Math.fround(13.37 + .5));
+assertEq(code(13.37, 1), Math.fround(13.37 - .5));
+
+// Arithmetic operations
+// -> mul
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3 * toF(4.));} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3. * toF(4.)); } return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return +(toF(3.) * toF(4.));} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3) * toF(4) * toF(5));} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.) * toF(4.)); } return f"), this)(), 12);
+
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3 * f32[0]);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3. * f32[0]);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return +(toF(3.) * f32[0]);} return f");
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(toF(3.) * f32[0]);} return f"), this, null, heap)(), 12);
+
+var mul = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x=toF(x); return toF(x * toF(4.));} return f"), this);
+assertEq(mul(Infinity), Infinity);
+assertEq(mul(NaN), NaN);
+assertEq(mul(0), 0);
+assertEq(mul(1), 4);
+assertEq(mul(0.33), Math.fround(0.33 * 4));
+
+// -> add
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3 + toF(4.));} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3.5 + toF(4.));} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return +(toF(3.5) + toF(4.));} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) + toF(4.)); } return f"), this)(), 7.5);
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) + toF(4.) + toF(4.5));} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(toF(3.5) + toF(4.)) + toF(4.5)); } return f"), this)(), 12);
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(toF(3) + f32[0]);} return f"), this, null, heap)(), 7);
+
+// --> no additions with float? or floatish
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3 + f32[0]);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3. + f32[0]);} return f");
+
+// -> sub
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3 - toF(4.));} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3.5 - toF(4.));} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return +(toF(3.5) - toF(4.));} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) - toF(4.)); } return f"), this)(), -.5);
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) - toF(4.) - toF(4.5));} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(toF(3.5) - toF(4.)) - toF(4.5)); } return f"), this)(), -5);
+
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) + toF(4.) - toF(4.5));} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) - toF(4.) + toF(4.5));} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(toF(3.5) + toF(4.)) - toF(4.5)); } return f"), this)(), 3);
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(toF(3.5) - toF(4.)) + toF(4.5)); } return f"), this)(), 4);
+
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3 - f32[0]);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3. - f32[0]);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return +(toF(3) - f32[0]);} return f");
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(toF(3) - f32[0]);} return f"), this, null, heap)(), -1);
+
+// -> div
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3 / toF(4.));} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(3.5 / toF(4.));} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return +(toF(3.5) / toF(4.));} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(12.) / toF(4.)); } return f"), this)(), 3);
+
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3 / f32[0]);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return toF(3. / f32[0]);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 4.; return +(toF(3) / f32[0]);} return f");
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { f32[0] = 2.; return toF(toF(4) / f32[0]);} return f"), this, null, heap)(), 2);
+
+// -> mod
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "function f() { return toF(toF(3.5) % toF(4.));} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { return toF(f32[0] % toF(4.));} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { return toF(toF(3.5) % f32[0]);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { return toF(f32[1] % f32[0]);} return f");
+
+// Comparisons
+for (op of ['==', '!=', '<', '>', '<=', '>=']) {
+ let code = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x); if( x " + op + " toF(3.) ) return 1; else return 0; return -1; } return f"), this);
+ let ternary = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = toF(x); return ((x " + op + " toF(3.)) ? 1 : 0)|0 } return f"), this);
+ for (v of [-5, 0, 2.5, 3, 13.37, NaN, Infinity]) {
+ let expected = eval("("+ v + " " + op + " 3)|0");
+ assertEq(code(v) | 0, expected);
+ assertEq(ternary(v) | 0, expected);
+ }
+
+ assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { if( f32[0] " + op + " toF(3.) ) return 1; else return 0; return -1; } return f");
+ assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + TO_FLOAT32 + HEAP32 + "function f() { if( (toF(1.) + toF(2.)) " + op + " toF(3.) ) return 1; else return 0; return -1; } return f");
+}
+
diff --git a/js/src/jit-test/tests/asm.js/testFloatingPoint.js b/js/src/jit-test/tests/asm.js/testFloatingPoint.js
new file mode 100644
index 000000000..bad22028e
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testFloatingPoint.js
@@ -0,0 +1,134 @@
+load(libdir + "asm.js");
+
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 1.1 } return f"))(), 1.1);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; return +(+(i|0) + .1) } return f"))(1), 1.1);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(d) { d=+d; return +d } return f"))(1.1), 1.1);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return +(d+e) } return f"))(1.0, .1), 1.1);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i,e) { i=i|0;e=+e; return +(+~~i+e) } return f"))(1, .1), 1.1);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(d,i) { d=+d;i=i|0; return +(d + +(i|0)) } return f"))(.1, 1), 1.1);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return +(d-e) } return f"))(1.1, .8), (1.1-.8));
+assertEq(asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return +(d*e) } return f"))(1.1, 2.2), (1.1*2.2));
+assertEq(asmLink(asmCompile(USE_ASM + "function g() { var i=2; return (~~(i=(i+1)|0))|0 } return g"))(), 3);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return (d<e)|0 } return f"));
+assertEq(f(1.1, 2.2), 1);
+assertEq(f(1.1, 1.1), 0);
+assertEq(f(2.1, 1.1), 0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return (d<=e)|0 } return f"));
+assertEq(f(1.1, 2.2), 1);
+assertEq(f(1.1, 1.1), 1);
+assertEq(f(2.1, 1.1), 0);
+assertEq(f(NaN, 1.1), 0);
+assertEq(f(1.1, NaN), 0);
+assertEq(f(NaN, NaN), 0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return (d>e)|0 } return f"));
+assertEq(f(2.1, 1.1), 1);
+assertEq(f(1.1, 1.1), 0);
+assertEq(f(1.1, 2.1), 0);
+assertEq(f(NaN, 1.1), 0);
+assertEq(f(1.1, NaN), 0);
+assertEq(f(NaN, NaN), 0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return (d>=e)|0 } return f"));
+assertEq(f(2.1, 1.1), 1);
+assertEq(f(1.0, 1.1), 0);
+assertEq(f(1.1, 2.1), 0);
+assertEq(f(NaN, 1.1), 0);
+assertEq(f(1.1, NaN), 0);
+assertEq(f(NaN, NaN), 0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return (d==e)|0 } return f"));
+assertEq(f(2.1, 1.1), 0);
+assertEq(f(1.1, 1.1), 1);
+assertEq(f(1.1, 2.1), 0);
+assertEq(f(NaN, 1.1), 0);
+assertEq(f(1.1, NaN), 0);
+assertEq(f(NaN, NaN), 0);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return (d!=e)|0 } return f"));
+assertEq(f(2.1, 1.1), 1);
+assertEq(f(1.1, 1.1), 0);
+assertEq(f(1.1, 2.1), 1);
+assertEq(f(NaN, 1.1), 1);
+assertEq(f(1.1, NaN), 1);
+assertEq(f(NaN, NaN), 1);
+
+var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return +(d/e) } return f"));
+assertEq(f(1.1, .1), (1.1/.1));
+assertEq(f(1.1, 0), (1.1/0));
+assertEq(f(1.1, -0), (1.1/-0));
+
+var f = asmLink(asmCompile(USE_ASM + "function f(d,e) { d=+d;e=+e; return +(d%e) } return f"));
+assertEq(f(1.1, .1), (1.1%.1));
+assertEq(f(1.1, 0), (1.1%0));
+assertEq(f(1.1, -0), (1.1%-0));
+
+var f = asmLink(asmCompile(USE_ASM + "function f(d) { d=+d; var i = 0; i = ~~d; return i|0 } return f"));
+assertEq(f(1.0), 1);
+assertEq(f(1.9), 1);
+assertEq(f(1.9999), 1);
+assertEq(f(2.0), 2);
+assertEq(f(Math.pow(2,40)), ~~Math.pow(2,40));
+assertEq(f(-Math.pow(2,40)), ~~-Math.pow(2,40));
+assertEq(f(4000000000), ~~4000000000);
+assertEq(f(-4000000000), ~~-4000000000);
+assertEq(f(NaN), 0);
+assertEq(f(Infinity), 0);
+assertEq(f(-Infinity), 0);
+
+assertAsmTypeFail(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return +((i|0)/(j|0)) } return f");
+assertAsmTypeFail(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return +(i+j) } return f");
+assertAsmTypeFail(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return +(i-j) } return f");
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return +(((i|0)/(j|0))|0) } return f"));
+assertEq(f(1,0), 0);
+assertEq(f(-Math.pow(2,31),-1), -Math.pow(2,31));
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i,j) { i=i|0;j=j|0; return +(((i|0)%(j|0))|0) } return f"));
+assertEq(f(1,0), 0);
+assertEq(f(-Math.pow(2,31),-1), 0);
+
+var {f,g} = asmLink(asmCompile(USE_ASM + "function f() { return 3.5 } function g(d) { d=+d; return +(d+3.5) } return {f:f,g:g}"));
+assertEq(f(), 3.5);
+assertEq(g(1), 1+3.5);
+
+var buf = new ArrayBuffer(BUF_MIN);
+var f64 = new Float64Array(buf);
+var i32 = new Int32Array(buf);
+var u32 = new Uint32Array(buf);
+var f = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[0] } return f'), this, null, buf);
+f64[0] = 0;
+assertEq(f(), 0);
+f64[0] = -1;
+assertEq(f(), -1);
+f64[0] = 1;
+assertEq(f(), 1);
+f64[0] = Infinity;
+assertEq(f(), Infinity);
+f64[0] = -Infinity;
+assertEq(f(), -Infinity);
+
+function ffi(d) { str = String(d) }
+var g = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'var ffi=imp.ffi; function g() { ffi(+f64[0]) } return g'), this, {ffi:ffi}, buf);
+var h = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function g() { return +(+f64[0] < 0.0 ? -+f64[0] : +f64[0]) } return g'), this, null, buf)
+
+function ffi1() { return 2.6 }
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "var ffi1=imp.ffi1; function g() { var i=0,j=0.0; i=ffi1()|0; j=+ffi1(); return +(+(i|0)+j) } return g"), null, {ffi1:ffi1})(), 2+2.6);
+
+// that sounds dangerous!
+var a = [0,1,0xffff0000,0x7fff0000,0xfff80000,0x7ff80000,0xfffc0000,0x7ffc0000,0xffffffff,0x0000ffff,0x00008fff7];
+for (i of a) {
+ for (j of a) {
+ u32[0] = i;
+ u32[1] = j;
+
+ assertEq(f(), f64[0]);
+
+ g();
+ assertEq(str, String(f64[0]));
+
+ assertEq(h(), Math.abs(f64[0]));
+ }
+}
diff --git a/js/src/jit-test/tests/asm.js/testFunctionPtr.js b/js/src/jit-test/tests/asm.js/testFunctionPtr.js
new file mode 100644
index 000000000..9998356f0
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testFunctionPtr.js
@@ -0,0 +1,74 @@
+load(libdir + "asm.js");
+
+assertAsmTypeFail('imp', USE_ASM + "function f() {} var imp=[f]; return f");
+assertAsmTypeFail(USE_ASM + "function f() {} var eval=[f]; return f");
+assertAsmTypeFail(USE_ASM + "var tbl=0; function f() {} var tbl=[f]; return f");
+assertAsmTypeFail(USE_ASM + "function f() {} var tbl; return f");
+assertAsmTypeFail(USE_ASM + "function f() {} var tbl=[]; return f");
+assertAsmTypeFail(USE_ASM + "function f() {} var tbl=[f,f,f]; return f");
+assertAsmTypeFail(USE_ASM + "function f() {} var tbl=[1]; return f");
+assertAsmTypeFail(USE_ASM + "var g = 0; function f() {} var tbl=[g]; return f");
+assertAsmTypeFail(USE_ASM + "function f() {} function g(i) {i=i|0} var tbl=[f,g]; return f");
+assertAsmTypeFail(USE_ASM + "function f() {} function g() {return 0} var tbl=[f,g]; return f");
+assertAsmTypeFail(USE_ASM + "function f(i) {i=i|0} function g(i) {i=+i} var tbl=[f,g]; return f");
+assertAsmTypeFail(USE_ASM + "function f() {return 0} function g() {return 0.0} var tbl=[f,g]; return f");
+assertAsmTypeFail(USE_ASM + "var tbl=0; function g() {tbl[0&1]()|0} return g");
+assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 42 } var tbl=[f]; return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 0} function g() {return 1} var tbl=[f,g]; return f"))(), 0);
+
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return ([])[i&1]()|0 } var tbl=[f,f]; return g");
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return f[i&1]()|0 } var tbl=[f,f]; return g");
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i]()|0 } var tbl=[f,f]; return g");
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&0]()|0 } var tbl=[f,f]; return g");
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&3]()|0 } var tbl=[f,f]; return g");
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i,j) { i=i|0;j=+j; return tbl[j&1]()|0 } var tbl=[f,f]; return g");
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&1](1)|0 } var tbl=[f,f]; return g");
+assertAsmTypeFail(USE_ASM + "function f(i) {i=i|0} function g(i) { i=i|0; return tbl[i&1]()|0 } var tbl=[f,f]; return g");
+assertAsmTypeFail(USE_ASM + "function f(i) {i=i|0} function g(i) { i=i|0; return tbl[i&1](3.0)|0 } var tbl=[f,f]; return g");
+assertAsmTypeFail(USE_ASM + "function f(d) {d=+d} function g(i) { i=i|0; return tbl[i&1](3)|0 } var tbl=[f,f]; return g");
+assertAsmTypeFail(USE_ASM + "function g() {tbl[0&1]()|0} return g");
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&1]()|0 } var tbl=[f,f]; return g"))(0), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&1]()|0 } const tbl=[f,f]; return g"))(0), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl[i&1]()|0 } var tbl=[f,g]; return h"))(1), 13);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl[i&1]()|0 } const tbl=[f,g]; return h"))(1), 13);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl2[i&1]()|0 } var tbl1=[f,g]; var tbl2=[g,f]; return h"))(1), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl2[i&1]()|0 } const tbl1=[f,g]; const tbl2=[g,f]; return h"))(1), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl2[i&3]()|0 } var tbl1=[f,g]; var tbl2=[g,g,g,f]; return h"))(3), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl2[i&3]()|0 } const tbl1=[f,g]; const tbl2=[g,g,g,f]; return h"))(3), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl1[i&1]()|0 } var tbl1=[f,g]; var tbl2=[g,g,g,f]; return h"))(1), 13);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl1[i&1]()|0 } const tbl1=[f,g]; const tbl2=[g,g,g,f]; return h"))(1), 13);
+assertEq(asmLink(asmCompile(USE_ASM + "var i=0,j=0; function f() {return i|0} function g() {return j|0} function h(x) { x=x|0; i=5;j=10; return tbl2[x&3]()|0 } var tbl1=[f,g]; var tbl2=[g,g,g,f]; return h"))(3), 5);
+assertEq(asmLink(asmCompile(USE_ASM + "var i=0,j=0; function f() {return i|0} function g() {return j|0} function h(x) { x=x|0; i=5;j=10; return tbl2[x&3]()|0 } const tbl1=[f,g]; const tbl2=[g,g,g,f]; return h"))(3), 5);
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "var ffi=imp.ffi; function f() {return ffi()|0} function g() {return 13} function h(x) { x=x|0; return tbl2[x&3]()|0 } var tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 20);
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "const ffi=imp.ffi; function f() {return ffi()|0} function g() {return 13} function h(x) { x=x|0; return tbl2[x&3]()|0 } const tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 20);
+assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "var ffi=imp.ffi; var i=0; function f() {return ((ffi()|0)+i)|0} function g() {return 13} function h(x) { x=x|0; i=2; return tbl2[x&3]()|0 } var tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 22)
+;assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "const ffi=imp.ffi; var i=0; function f() {return ((ffi()|0)+i)|0} function g() {return 13} function h(x) { x=x|0; i=2; return tbl2[x&3]()|0 } const tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 22);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) {i=i|0; return +((i+1)|0)} function g(d) { d=+d; return +(d+2.5) } function h(i,j) { i=i|0;j=j|0; return +tbl2[i&1](+tbl1[i&1](j)) } var tbl1=[f,f]; var tbl2=[g,g]; return h"))(0,10), 11+2.5);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) {i=i|0; return +((i+1)|0)} function g(d) { d=+d; return +(d+2.5) } function h(i,j) { i=i|0;j=j|0; return +tbl2[i&1](+tbl1[i&1](j)) } const tbl1=[f,f]; const tbl2=[g,g]; return h"))(0,10), 11+2.5);
+
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0]()|0 } var tbl=[f]; return g");
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() { return tbl[0&0]()|0 } var tbl=[f]; return g"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() { return tbl[0&0]()|0 } const tbl=[f]; return g"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f1() {return 42} function f2() {return 13} function g() { return tbl[1&1]()|0 } var tbl=[f1,f2]; return g"))(), 13);
+assertEq(asmLink(asmCompile(USE_ASM + "function f1() {return 42} function f2() {return 13} function g() { return tbl[1&1]()|0 } const tbl=[f1,f2]; return g"))(), 13);
+
+// Test some literal constant paths.
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&4294967295]()|0 } var tbl=[f]; return g");
+assertAsmTypeFail(USE_ASM + "const i=4294967295; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g");
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&-1]()|0 } var tbl=[f]; return g");
+assertAsmTypeFail(USE_ASM + "const i=-1; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g");
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&0x80000000]()|0 } var tbl=[f]; return g");
+assertAsmTypeFail(USE_ASM + "const i=0x80000000; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g");
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&-2147483648]()|0 } var tbl=[f]; return g");
+assertAsmTypeFail(USE_ASM + "const i=-2147483648; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g");
+assertAsmTypeFail(USE_ASM + "const i=0; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g");
+// Limited by the inability to test really large tables.
+assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&0x7fffffff]()|0 } var tbl=[f]; return g");
+
+var f = asmLink(asmCompile(USE_ASM + "function f1(d) {d=+d; return +(d/2.0)} function f2(d) {d=+d; return +(d+10.0)} function g(i,j) { i=i|0;j=+j; return +tbl[i&1](+tbl[(i+1)&1](j)) } var tbl=[f1,f2]; return g"));
+assertEq(f(0,10.2), (10.2+10)/2);
+assertEq(f(1,10.2), (10.2/2)+10);
+
+var f = asmLink(asmCompile('glob','imp', USE_ASM + "var ffi=imp.ffi; function f(){return 13} function g(){return 42} function h(i) { i=i|0; var j=0; ffi(1); j=TBL[i&7]()|0; ffi(1.5); return j|0 } var TBL=[f,g,f,f,f,f,f,f]; return h"), null, {ffi:function(){}});
+for (var i = 0; i < 100; i++)
+ assertEq(f(i), (i%8 == 1) ? 42 : 13);
diff --git a/js/src/jit-test/tests/asm.js/testGlobals.js b/js/src/jit-test/tests/asm.js/testGlobals.js
new file mode 100644
index 000000000..1e9fc3ac9
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testGlobals.js
@@ -0,0 +1,164 @@
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+assertAsmTypeFail(USE_ASM + "var i; function f(){} return f");
+assertEq(asmLink(asmCompile(USE_ASM + "var i=0; function f(){} return f"))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + "const i=0; function f(){} return f"))(), undefined);
+assertEq(asmLink(asmCompile(USE_ASM + "var i=42; function f(){ return i|0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "const i=42; function f(){ return i|0 } return f"))(), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "var i=4.2; function f(){ return +i } return f"))(), 4.2);
+assertEq(asmLink(asmCompile(USE_ASM + "const i=4.2; function f(){ return +i } return f"))(), 4.2);
+assertAsmTypeFail(USE_ASM + "var i=42; function f(){ return +(i+.1) } return f");
+assertAsmTypeFail(USE_ASM + "const i=42; function f(){ return +(i+.1) } return f");
+assertAsmTypeFail(USE_ASM + "var i=1.2; function f(){ return i|0 } return f");
+assertAsmTypeFail(USE_ASM + "const i=1.2; function f(){ return i|0 } return f");
+assertAsmTypeFail(USE_ASM + "var i=0; function f(e){ e=+e; i=e } return f");
+assertAsmTypeFail(USE_ASM + "var d=0.1; function f(i){ i=i|0; d=i } return f");
+assertEq(asmLink(asmCompile(USE_ASM + "var i=13; function f(j) { j=j|0; i=j; return i|0 } return f"))(42), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "var d=.1; function f(e) { e=+e; d=e; return +e } return f"))(42.1), 42.1);
+assertEq(asmLink(asmCompile(USE_ASM + "var i=13; function f(i, j) { i=i|0; j=j|0; i=j; return i|0 } return f"))(42,43), 43);
+assertEq(asmLink(asmCompile(USE_ASM + "var i=13; function f(j) { j=j|0; var i=0; i=j; return i|0 } return f"))(42), 42);
+
+var f = asmLink(asmCompile(USE_ASM + "var i=13; function f(j) { j=j|0; if ((j|0) != -1) { i=j } else { return i|0 } return 0 } return f"));
+assertEq(f(-1), 13);
+assertEq(f(42), 0);
+assertEq(f(-1), 42);
+
+assertAsmTypeFail(USE_ASM + "var i=13; function f() { var j=i; return j|0 } return f");
+assertAsmTypeFail(USE_ASM + "var i=13.37; function f() { var j=i; return +j } return f");
+assertAsmTypeFail('global', USE_ASM + "var f32 = global.Math.fround; var i=f32(13.37); function f() { var j=i; return f32(j) } return f");
+
+assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { var j=i; return +j } return f'), {Infinity:Infinity})(), Infinity);
+assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { var j=i; return +j } return f'), {NaN:NaN})(), NaN);
+
+assertEq(asmLink(asmCompile(USE_ASM + "const i=13; function f() { var j=i; return j|0 } return f"))(), 13);
+assertEq(asmLink(asmCompile(USE_ASM + "const i=13.37; function f() { var j=i; return +j } return f"))(), 13.37);
+assertEq(asmLink(asmCompile('global', USE_ASM + "var f32 = global.Math.fround; const i=f32(13.37); function f() { var j=i; return f32(j) } return f"), this)(), Math.fround(13.37));
+
+assertAsmTypeFail(USE_ASM + "function f() { var j=i; return j|0 } return f");
+assertAsmTypeFail(USE_ASM + "function i(){} function f() { var j=i; return j|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f() { var j=i; return j|0 } var i = [f]; return f");
+assertAsmTypeFail('global', USE_ASM + "var i=global.Math.fround; function f() { var j=i; return j|0 } return f");
+assertAsmTypeFail('global', 'imp', USE_ASM + "var i=imp.f; function f() { var j=i; return j|0 } return f");
+assertAsmTypeFail('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { var j=i; return j|0 } return f");
+assertAsmTypeFail('global', 'imp', USE_ASM + "var i=+imp.i; function f() { var j=i; return +j } return f");
+assertAsmTypeFail('global', 'imp', USE_ASM + "const i=imp.i|0; function f() { var j=i; return j|0 } return f");
+assertAsmTypeFail('global', 'imp', USE_ASM + "const i=+imp.i; function f() { var j=i; return +j } return f");
+assertAsmTypeFail('global', 'imp', 'heap', USE_ASM + "var i=new global.Float32Array(heap); function f() { var j=i; return +j } return f");
+
+assertAsmTypeFail('global', USE_ASM + "var i=global; function f() { return i|0 } return f");
+assertAsmTypeFail('global', USE_ASM + "const i=global; function f() { return i|0 } return f");
+assertAsmTypeFail('global', USE_ASM + "var i=global|0; function f() { return i|0 } return f");
+assertAsmTypeFail('global', USE_ASM + "const i=global|0; function f() { return i|0 } return f");
+assertAsmTypeFail('global', USE_ASM + "var j=0;var i=j.i|0; function f() { return i|0 } return f");
+assertAsmTypeFail('global', USE_ASM + "var i=global.i|0; function f() { return i|0 } return f");
+assertAsmTypeFail('global', USE_ASM + "const i=global.i|0; function f() { return i|0 } return f");
+assertAsmTypeFail('global', USE_ASM + "var i=global.i|0; function f() { return i|0 } return f");
+assertAsmTypeFail('global', USE_ASM + 'var i=global.Infinity; function f() { i = 0.0 } return f');
+assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), undefined);
+assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'const i=global.Infinity; function f() { return +i } return f'), undefined);
+assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), null);
+assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'const i=global.Infinity; function f() { return +i } return f'), null);
+assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), 3);
+assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), {});
+assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), {Infinity:NaN});
+assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), {Infinity:-Infinity});
+assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), {Infinity:Infinity})(), Infinity);
+assertEq(asmLink(asmCompile('global', USE_ASM + 'const i=global.Infinity; function f() { return +i } return f'), {Infinity:Infinity})(), Infinity);
+assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), this)(), Infinity);
+assertEq(asmLink(asmCompile('global', USE_ASM + 'const i=global.Infinity; function f() { return +i } return f'), this)(), Infinity);
+assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), undefined);
+assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), null);
+assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), 3);
+assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), {});
+assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), {Infinity:Infinity});
+assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), {Infinity:-Infinity});
+assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), {NaN:NaN})(), NaN);
+assertEq(asmLink(asmCompile('global', USE_ASM + 'const i=global.NaN; function f() { return +i } return f'), {NaN:NaN})(), NaN);
+assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), this)(), NaN);
+assertEq(asmLink(asmCompile('global', USE_ASM + 'const i=global.NaN; function f() { return +i } return f'), this)(), NaN);
+
+assertAsmLinkFail(asmCompile('glob','foreign','buf', USE_ASM + 'var t = new glob.Int32Array(buf); function f() {} return f'), {get Int32Array(){return Int32Array}}, null, new ArrayBuffer(4096))
+assertAsmLinkFail(asmCompile('glob','foreign','buf', USE_ASM + 'const t = new glob.Int32Array(buf); function f() {} return f'), {get Int32Array(){return Int32Array}}, null, new ArrayBuffer(4096))
+assertAsmLinkFail(asmCompile('glob','foreign','buf', USE_ASM + 'var t = new glob.Int32Array(buf); function f() {} return f'), new Proxy(this, {}), null, new ArrayBuffer(4096))
+assertAsmLinkFail(asmCompile('glob','foreign','buf', USE_ASM + 'const t = new glob.Int32Array(buf); function f() {} return f'), new Proxy(this, {}), null, new ArrayBuffer(4096))
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Math.sin; function f() {} return f'), {get Math(){return Math}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Math.sin; function f() {} return f'), new Proxy(this, {}));
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Math.sin; function f() {} return f'), {Math:{get sin(){return Math.sin}}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Math.sin; function f() {} return f'), {Math:new Proxy(Math, {})});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Infinity; function f() {} return f'), {get Infinity(){return Infinity}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Infinity; function f() {} return f'), new Proxy(this, {}));
+assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x|0; function f() {} return f'), null, {get x(){return 42}})
+assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.x; function f() {} return f'), null, {get x(){return 42}})
+assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x|0; function f() {} return f'), null, new Proxy({x:42}, {}));
+assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.x; function f() {} return f'), null, new Proxy({x:42}, {}));
+assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x; function f() {} return f'), null, {get x(){return function(){}}})
+assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x; function f() {} return f'), null, new Proxy({x:function(){}}, {}));
+assertAsmTypeFail('global', 'imp', USE_ASM + "var i=imp; function f() { return i|0 } return f");
+assertAsmTypeFail('global', 'imp', USE_ASM + "var j=0;var i=j.i|0; function f() { return i|0 } return f");
+assertAsmLinkAlwaysFail(asmCompile('global','imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f"), null, undefined);
+assertAsmLinkAlwaysFail(asmCompile('global','imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f"), this, undefined);
+assertAsmLinkAlwaysFail(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f"), null, null);
+assertAsmLinkAlwaysFail(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f"), this, null);
+assertAsmLinkFail(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f"), this, 42);
+assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f")(null, {i:42})), 42);
+assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=imp.i|0; function f() { return i|0 } return f")(null, {i:42})), 42);
+assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f")(null, {i:1.4})), 1);
+assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=imp.i|0; function f() { return i|0 } return f")(null, {i:1.4})), 1);
+assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=+imp.i; function f() { return +i } return f")(null, {i:42})), 42);
+assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=+imp.i; function f() { return +i } return f")(null, {i:42})), 42);
+assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=+imp.i; function f() { return +i } return f")(this, {i:1.4})), 1.4);
+assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=+imp.i; function f() { return +i } return f")(this, {i:1.4})), 1.4);
+assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f() { var i=42; while (1) { break; } g = i; return g|0 } return f"))(), 42);
+assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.x; function f() {} return f'), null, {x:{valueOf:function() { return 42 }}});
+assertAsmLinkFail(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x|0; function f() {} return f'), null, {x:{valueOf:function() { return 42 }}});
+assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.x|0; function f() { return i|0} return f'), null, {x:"blah"})(), 0);
+assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.x; function f() { return +i} return f'), null, {x:"blah"})(), NaN);
+assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var tof = glob.Math.fround; var i = tof(foreign.x); function f() { return +i} return f'), this, {x:"blah"})(), NaN);
+assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var i = foreign.x|0; function f() { return i|0} return f')(null, {x:Symbol("blah")}), TypeError);
+assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var i = +foreign.x; function f() { return +i} return f')(null, {x:Symbol("blah")}), TypeError);
+assertThrowsInstanceOf(() => asmCompile('glob','foreign',USE_ASM + 'var tof = glob.Math.fround; var i = tof(foreign.x); function f() { return +i} return f')(this, {x:Symbol("blah")}), TypeError);
+
+// Temporary workaround; this test can be removed when Emscripten is fixed and
+// the fix has propagated out to most apps:
+assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = foreign.i|0; function f() { return i|0} return f'), null, {i:function(){}})(), 0);
+assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var i = +foreign.i; function f() { return +i} return f'), null, {i:function(){}})(), NaN);
+assertEq(asmLink(asmCompile('glob','foreign', USE_ASM + 'var tof = glob.Math.fround; var i = tof(foreign.i); function f() { return +i} return f'), this, {i:function(){}})(), NaN);
+var module = asmCompile('glob','foreign', USE_ASM + 'var i = foreign.i|0; function f() { return i|0} return f');
+var fun = function() {}
+fun.valueOf = function() {}
+assertAsmLinkFail(module, null, {i:fun});
+var fun = function() {}
+fun.toString = function() {}
+assertAsmLinkFail(module, null, {i:fun});
+var fun = function() {}
+var origFunToString = Function.prototype.toString;
+Function.prototype.toString = function() {}
+assertAsmLinkFail(module, null, {i:fun});
+Function.prototype.toString = origFunToString;
+assertEq(asmLink(module, null, {i:fun})(), 0);
+Function.prototype.valueOf = function() {}
+assertAsmLinkFail(module, null, {i:fun});
+delete Function.prototype.valueOf;
+assertEq(asmLink(module, null, {i:fun})(), 0);
+var origObjValueOf = Object.prototype.valueOf;
+Object.prototype.valueOf = function() {}
+assertAsmLinkFail(module, null, {i:fun});
+Object.prototype.valueOf = origObjValueOf;
+assertEq(asmLink(module, null, {i:fun})(), 0);
+Object.prototype.toString = function() {}
+assertEq(asmLink(module, null, {i:fun})(), 0);
+
+var f1 = asmCompile('global', 'foreign', 'heap', USE_ASM + 'var i32 = new global.Int32Array(heap); function g() { return i32[4]|0 } return g');
+var global = this;
+var ab = new ArrayBuffer(4096);
+var p = new Proxy(global,
+ {has:function(name) { f1(global, null, ab); return true},
+ getOwnPropertyDescriptor:function(name) { return {configurable:true, value:Int32Array}}});
+new Int32Array(ab)[4] = 42;
+assertEq(f1(p, null, ab)(), 42);
+
+// GVN checks
+assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f() { var x = 0; g = 1; x = g; return (x+g)|0 } return f"))(), 2);
+assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f() { var x = 0; g = 1; x = g; g = 2; return (x+g)|0 } return f"))(), 3);
+assertEq(asmLink(asmCompile(USE_ASM + "var g=0; var h=0; function f() { var x = 0; g = 1; x = g; h = 3; return (x+g)|0 } return f"))(), 2);
diff --git a/js/src/jit-test/tests/asm.js/testHeapAccess.js b/js/src/jit-test/tests/asm.js/testHeapAccess.js
new file mode 100644
index 000000000..d5c69082f
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testHeapAccess.js
@@ -0,0 +1,515 @@
+load(libdir + "asm.js");
+
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[0>>2] = 4.0; return i32[0>>2]|0; } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[0>>2] = 4; return +f32[0>>2]; } return f');
+
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { var x=0,y=0; return i8[x+y]|0 } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { var x=0,y=0; return u8[x+y]|0 } return f');
+
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[0>>0]|0 }; return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[0>>1]|0 }; return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[0>>4]|0 }; return f');
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[0]|0 }; return f'), this, null, new ArrayBuffer(BUF_MIN))(), 0);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i = i32[i>>2]|0; return i|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0), 0);
+
+setCachingEnabled(true);
+
+// In order to allow following tests work on both big-endian and little-
+// endian architectures we need to define least significant byte (lsb) and
+// least significant word (lsw).
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i8[0]|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+var lsb=0;
+var lsw=0
+if (f(0x12345678) == 0x12) {
+ lsb=3;
+ lsw=1;
+}
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i8[' + lsb + ']|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0),0);
+assertEq(f(0x7f),0x7f);
+assertEq(f(0xff),-1);
+assertEq(f(0x100),0);
+
+{
+ var buf = new ArrayBuffer(BUF_MIN);
+ var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + '/* not a clone */ function f(i) {i=i|0; i32[0] = i; return i8[' + lsb + ']|0}; return f');
+ var f = asmLink(code, this, null, buf);
+ assertEq(f(0),0);
+ assertEq(f(0x7f),0x7f);
+ assertEq(f(0xff),-1);
+ assertEq(f(0x100),0);
+
+ // Bug 1088655
+ assertEq(asmLink(asmCompile('stdlib', 'foreign', 'heap', USE_ASM + 'var i32=new stdlib.Int32Array(heap); function f(i) {i=i|0;var j=0x10000;return (i32[j>>2] = i)|0 } return f'), this, null, buf)(1), 1);
+}
+
+setCachingEnabled(false);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u8[' + lsb + ']|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0),0);
+assertEq(f(0x7f),0x7f);
+assertEq(f(0xff),0xff);
+assertEq(f(0x100),0);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i16[' + lsw + ']|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0),0);
+assertEq(f(0x7fff),0x7fff);
+assertEq(f(0xffff),-1);
+assertEq(f(0x10000),0);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u16[' + lsw + ']|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0),0);
+assertEq(f(0x7fff),0x7fff);
+assertEq(f(0xffff),0xffff);
+assertEq(f(0x10000),0);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i32[0]|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0),0);
+assertEq(f(0x7fffffff),0x7fffffff);
+assertEq(f(0xffffffff),-1);
+assertEq(f(0x100000000),0);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u32[0]|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0),0);
+assertEq(f(0x7fffffff),0x7fffffff);
+assertEq(f(0xffffffff),-1);
+assertEq(f(0x100000000),0);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return i8[' + lsb + ']|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0),0);
+assertEq(f(0x7f),0x7f);
+assertEq(f(0xff),-1);
+assertEq(f(0x100),0);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i32[0] = i; return u8[' + lsb + ']|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0),0);
+assertEq(f(0x7f),0x7f);
+assertEq(f(0xff),0xff);
+assertEq(f(0x100),0);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i8[0] = i; return i8[0]|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0),0);
+assertEq(f(0x7f),0x7f);
+assertEq(f(0xff),-1);
+assertEq(f(0x100),0);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; i8[0] = i; return u8[0]|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0),0);
+assertEq(f(0x7f),0x7f);
+assertEq(f(0xff),0xff);
+assertEq(f(0x100),0);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=+j; f64[i>>3] = j; return (~~+f64[i>>3])|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0, 1.3), 1);
+assertEq(f(BUF_MIN-8, 2.5), 2);
+assertEq(f(BUF_MIN, 3.8), 0);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=+j; f64[i>>3] = j; return (~~f64[i>>3])|0}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0, 1.3), 1);
+assertEq(f(BUF_MIN-8, 2.5), 2);
+assertEq(f(BUF_MIN, 3.8), 0);
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i,j) {i=i|0;j=+j; f64[i>>3] = j; return +f64[i>>3]}; return f');
+var f = asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+assertEq(f(0, 1.3), 1.3);
+assertEq(f(BUF_MIN-8, 2.5), 2.5);
+assertEq(f(BUF_MIN, 3.8), NaN);
+
+var i32 = new Int32Array(BUF_MIN);
+i32[0] = 42;
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[1] = i32[0] }; return f'), this, null, i32.buffer)();
+assertEq(i32[1], 42);
+
+var f64 = new Float64Array(BUF_MIN);
+f64[0] = 42;
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[1] = f64[0] }; return f'), this, null, f64.buffer)();
+assertEq(f64[1], 42);
+
+var i32 = new Int32Array(BUF_MIN/4);
+i32[0] = 13;
+i32[1] = 0xfffeeee;
+var f = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return i32[((i<<2)+1)>>2]|0 }; return f'), this, null, i32.buffer);
+assertEq(f(0), 13);
+assertEq(f(1), 0xfffeeee);
+var f = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return i32[((i<<2)+2)>>2]|0 }; return f'), this, null, i32.buffer);
+assertEq(f(0), 13);
+assertEq(f(1), 0xfffeeee);
+var f = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return i32[(i<<1)>>2]|0 }; return f'), this, null, i32.buffer);
+assertEq(f(0), 13);
+assertEq(f(1), 13);
+assertEq(f(2), 0xfffeeee);
+assertEq(f(3), 0xfffeeee);
+
+var f = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return i32[(i<<2)>>2]|0 }; return f'), this, null, i32.buffer);
+assertEq(f(0), 13);
+assertEq(f(1), 0xfffeeee);
+
+var f = asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) {i=i|0; return i32[((i<<2)+4)>>2]|0 }; return f'), this, null, i32.buffer);
+assertEq(f(0), 0xfffeeee);
+
+// For legacy compatibility, test Int8/Uint8 accesses with no shift.
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[7&0xffff] = 41 } return f'), this, null, BUF_64KB)();
+assertEq(new Uint8Array(BUF_64KB)[7], 41);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[7&0xffff] = -41 } return f'), this, null, BUF_64KB)();
+assertEq(new Int8Array(BUF_64KB)[7], -41);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[(7&0xffff)>>0] = 41 } return f'), this, null, BUF_64KB)();
+assertEq(new Uint8Array(BUF_64KB)[7], 41);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[(7&0xffff)>>0] = -41 } return f'), this, null, BUF_64KB)();
+assertEq(new Int8Array(BUF_64KB)[7], -41);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u16[(6&0xffff)>>1] = 0xabc } return f'), this, null, BUF_64KB)();
+assertEq(new Uint16Array(BUF_64KB)[3], 0xabc);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i16[(6&0xffff)>>1] = -0xabc } return f'), this, null, BUF_64KB)();
+assertEq(new Int16Array(BUF_64KB)[3], -0xabc);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u32[(4&0xffff)>>2] = 0xabcde } return f'), this, null, BUF_64KB)();
+assertEq(new Uint32Array(BUF_64KB)[1], 0xabcde);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[(4&0xffff)>>2] = -0xabcde } return f'), this, null, BUF_64KB)();
+assertEq(new Int32Array(BUF_64KB)[1], -0xabcde);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[(4&0xffff)>>2] = 1.0 } return f'), this, null, BUF_64KB)();
+assertEq(new Float32Array(BUF_64KB)[1], 1.0);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[(8&0xffff)>>3] = 1.3 } return f'), this, null, BUF_64KB)();
+assertEq(new Float64Array(BUF_64KB)[1], 1.3);
+
+new Float32Array(BUF_64KB)[1] = 1.0;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f32[(4&0xffff)>>2] } return f'), this, null, BUF_64KB)(), 1.0);
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'var toFloat32 = glob.Math.fround; function f() { return toFloat32(f32[(4&0xffff)>>2]) } return f'), this, null, BUF_64KB)(), 1.0);
+new Float64Array(BUF_64KB)[1] = 1.3;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[(8&0xffff)>>3] } return f'), this, null, BUF_64KB)(), 1.3);
+
+asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u8[255]; u8[i] } return f');
+// For legacy compatibility, test Int8/Uint8 accesses with no shift.
+asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u8[i&0xff]; u8[255] } return f');
+asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u8[(i&0xff)>>0]; u8[255] } return f');
+asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u32[63]; u32[i>>2] } return f');
+asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u32[i>>2]; u32[63] } return f');
+
+var code = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u32[64] } return f');
+asmLink(code, this, null, new ArrayBuffer(BUF_MIN));
+
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; u32[12] = i } return f'), this, null, BUF_64KB)(11);
+assertEq(new Int32Array(BUF_64KB)[12], 11);
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[12]|0 } return f'), this, null, BUF_64KB)(), 11);
+new Float64Array(BUF_64KB)[0] = 3.5;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +-f64[0] } return f'), this, null, BUF_64KB)(), -3.5);
+
+// Test constant loads.
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[1] = -1 } return f'), this, null, buf)();
+assertEq(new Uint8Array(buf)[0], 0);
+assertEq(new Uint8Array(buf)[1], 255);
+assertEq(new Uint8Array(buf)[2], 0);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[4095] = -1 } return f'), this, null, buf)();
+assertEq(new Uint8Array(buf)[4094], 0);
+assertEq(new Uint8Array(buf)[4095], 255);
+assertEq(new Uint8Array(buf)[4096], 0);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[4096] = -1 } return f'), this, null, buf)();
+assertEq(new Uint8Array(buf)[4095], 0);
+assertEq(new Uint8Array(buf)[4096], 255);
+assertEq(new Uint8Array(buf)[4097], 0);
+assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[' + BUF_MIN + '] = -1 } return f'), this, null, buf);
+var buf = new ArrayBuffer(262144);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u8[258048] = -1 } return f'), this, null, buf)();
+assertEq(new Uint8Array(buf)[258047], 0);
+assertEq(new Uint8Array(buf)[258048], 255);
+assertEq(new Uint8Array(buf)[258049], 0);
+
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[1] = -1 } return f'), this, null, buf)();
+assertEq(new Int8Array(buf)[0], 0);
+assertEq(new Int8Array(buf)[1], -1);
+assertEq(new Int8Array(buf)[2], 0);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[4095] = -1 } return f'), this, null, buf)();
+assertEq(new Int8Array(buf)[4094], 0);
+assertEq(new Int8Array(buf)[4095], -1);
+assertEq(new Int8Array(buf)[4096], 0);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[4096] = -1 } return f'), this, null, buf)();
+assertEq(new Int8Array(buf)[4095], 0);
+assertEq(new Int8Array(buf)[4096], -1);
+assertEq(new Int8Array(buf)[4097], 0);
+assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[' + BUF_MIN + '] = -1 } return f'), this, null, buf);
+var buf = new ArrayBuffer(262144);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i8[258048] = -1 } return f'), this, null, buf)();
+assertEq(new Int8Array(buf)[258047], 0);
+assertEq(new Int8Array(buf)[258048], -1);
+assertEq(new Int8Array(buf)[258049], 0);
+
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u16[1] = -1 } return f'), this, null, buf)();
+assertEq(new Uint16Array(buf)[0], 0);
+assertEq(new Uint16Array(buf)[1], 65535);
+assertEq(new Uint16Array(buf)[2], 0);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u16[' + (BUF_MIN/2-1) + '] = -1 } return f'), this, null, buf)();
+assertEq(new Uint16Array(buf)[BUF_MIN/2-2], 0);
+assertEq(new Uint16Array(buf)[BUF_MIN/2-1], 65535);
+assertEq(new Uint16Array(buf)[BUF_MIN/2], undefined);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u16[' + (BUF_MIN/4) + '] = -1 } return f'), this, null, buf)();
+assertEq(new Uint16Array(buf)[BUF_MIN/4-1], 0);
+assertEq(new Uint16Array(buf)[BUF_MIN/4], 65535);
+assertEq(new Uint16Array(buf)[BUF_MIN/4+1], 0);
+assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u16[' + (BUF_MIN/2) + '] = -1 } return f'), this, null, buf);
+var buf = new ArrayBuffer(262144);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u16[126976] = -1 } return f'), this, null, buf)();
+assertEq(new Uint16Array(buf)[126975], 0);
+assertEq(new Uint16Array(buf)[126976], 65535);
+assertEq(new Uint16Array(buf)[126977], 0);
+
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i16[1] = -1 } return f'), this, null, buf)();
+assertEq(new Int16Array(buf)[0], 0);
+assertEq(new Int16Array(buf)[1], -1);
+assertEq(new Int16Array(buf)[2], 0);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i16[' + (BUF_MIN/2-1) + '] = -1 } return f'), this, null, buf)();
+assertEq(new Int16Array(buf)[BUF_MIN/2-2], 0);
+assertEq(new Int16Array(buf)[BUF_MIN/2-1], -1);
+assertEq(new Int16Array(buf)[BUF_MIN/2], undefined);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i16[' + (BUF_MIN/4) + '] = -1 } return f'), this, null, buf)();
+assertEq(new Int16Array(buf)[BUF_MIN/4-1], 0);
+assertEq(new Int16Array(buf)[BUF_MIN/4], -1);
+assertEq(new Int16Array(buf)[BUF_MIN/4+1], 0);
+assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i16[' + (BUF_MIN/2) + '] = -1 } return f'), this, null, buf);
+var buf = new ArrayBuffer(262144);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i16[126976] = -1 } return f'), this, null, buf)();
+assertEq(new Int16Array(buf)[126975], 0);
+assertEq(new Int16Array(buf)[126976], -1);
+assertEq(new Int16Array(buf)[126977], 0);
+
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u32[1] = -1 } return f'), this, null, buf)();
+assertEq(new Uint32Array(buf)[0], 0);
+assertEq(new Uint32Array(buf)[1], 4294967295);
+assertEq(new Uint32Array(buf)[2], 0);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u32[' + (BUF_MIN/4-1) + '] = -1 } return f'), this, null, buf)();
+assertEq(new Uint32Array(buf)[BUF_MIN/4-2], 0);
+assertEq(new Uint32Array(buf)[BUF_MIN/4-1], 4294967295);
+assertEq(new Uint32Array(buf)[BUF_MIN/4], undefined);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u32[' + (BUF_MIN/8) + '] = -1 } return f'), this, null, buf)();
+assertEq(new Uint32Array(buf)[BUF_MIN/8-1], 0);
+assertEq(new Uint32Array(buf)[BUF_MIN/8], 4294967295);
+assertEq(new Uint32Array(buf)[BUF_MIN/8+1], 0);
+assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u32[' + (BUF_MIN/4) + '] = -1 } return f'), this, null, buf);
+var buf = new ArrayBuffer(262144);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { u32[61440] = -1 } return f'), this, null, buf)();
+assertEq(new Uint32Array(buf)[61439], 0);
+assertEq(new Uint32Array(buf)[61440], 4294967295);
+assertEq(new Uint32Array(buf)[61441], 0);
+
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[1] = -1 } return f'), this, null, buf)();
+assertEq(new Int32Array(buf)[0], 0);
+assertEq(new Int32Array(buf)[1], -1);
+assertEq(new Int32Array(buf)[2], 0);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[' + (BUF_MIN/4-1) + '] = -1 } return f'), this, null, buf)();
+assertEq(new Int32Array(buf)[BUF_MIN/4-2], 0);
+assertEq(new Int32Array(buf)[BUF_MIN/4-1], -1);
+assertEq(new Int32Array(buf)[BUF_MIN/4], undefined);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[' + (BUF_MIN/8) + '] = -1 } return f'), this, null, buf)();
+assertEq(new Int32Array(buf)[BUF_MIN/8-1], 0);
+assertEq(new Int32Array(buf)[BUF_MIN/8], -1);
+assertEq(new Int32Array(buf)[BUF_MIN/8+1], 0);
+assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[' + (BUF_MIN/4) + '] = -1 } return f'), this, null, buf);
+var buf = new ArrayBuffer(262144);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[61440] = -1 } return f'), this, null, buf)();
+assertEq(new Int32Array(buf)[61439], 0);
+assertEq(new Int32Array(buf)[61440], -1);
+assertEq(new Int32Array(buf)[61441], 0);
+
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[1] = -1.0 } return f'), this, null, buf)();
+assertEq(new Int32Array(buf)[0], 0);
+assertEq(new Float32Array(buf)[1], -1.0);
+assertEq(new Int32Array(buf)[2], 0);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[' + (BUF_MIN/4-1) + '] = -1.0 } return f'), this, null, buf)();
+assertEq(new Int32Array(buf)[BUF_MIN/4-2], 0);
+assertEq(new Float32Array(buf)[BUF_MIN/4-1], -1.0);
+assertEq(new Int32Array(buf)[BUF_MIN/4], undefined);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[' + (BUF_MIN/8) + '] = -1.0 } return f'), this, null, buf)();
+assertEq(new Int32Array(buf)[BUF_MIN/8-1], 0);
+assertEq(new Float32Array(buf)[BUF_MIN/8], -1.0);
+assertEq(new Int32Array(buf)[BUF_MIN/8+1], 0);
+assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[' + (BUF_MIN/4) + '] = -1.0 } return f'), this, null, buf);
+var buf = new ArrayBuffer(262144);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[61440] = -1.0 } return f'), this, null, buf)();
+assertEq(new Float32Array(buf)[61439], 0.0);
+assertEq(new Float32Array(buf)[61440], -1.0);
+assertEq(new Float32Array(buf)[61441], 0.0);
+
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[1] = -1.0 } return f'), this, null, buf)();
+assertEq(new Float64Array(buf)[0], 0.0);
+assertEq(new Float64Array(buf)[1], -1.0);
+assertEq(new Float64Array(buf)[2], 0.0);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[' + (BUF_MIN/8-1) + '] = -1.0 } return f'), this, null, buf)();
+assertEq(new Float64Array(buf)[BUF_MIN/8-2], 0.0);
+assertEq(new Float64Array(buf)[BUF_MIN/8-1], -1.0);
+assertEq(new Float64Array(buf)[BUF_MIN/8], undefined);
+var buf = new ArrayBuffer(BUF_MIN);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[' + (BUF_MIN/16) + '] = -1.0 } return f'), this, null, buf)();
+assertEq(new Float64Array(buf)[BUF_MIN/16-1], 0.0);
+assertEq(new Float64Array(buf)[BUF_MIN/16], -1.0);
+assertEq(new Float64Array(buf)[BUF_MIN/16+1], 0.0);
+assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[' + (BUF_MIN/8) + '] = -1.0 } return f'), this, null, buf);
+var buf = new ArrayBuffer(262144);
+asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f64[28672] = -1.0 } return f'), this, null, buf)();
+assertEq(new Float64Array(buf)[28671], 0.0);
+assertEq(new Float64Array(buf)[28672], -1.0);
+assertEq(new Float64Array(buf)[28673], 0.0);
+
+
+var buf = new ArrayBuffer(BUF_MIN);
+new Uint8Array(buf)[1] = -1;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[1]|0; } return f'), this, null, buf)(),255);
+new Int8Array(buf)[1] = -1;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i8[1]|0; } return f'), this, null, buf)(),-1);
+var buf = new ArrayBuffer(262144);
+new Uint8Array(buf)[126976] = -1;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[126976]|0; } return f'), this, null, buf)(),255);
+new Int8Array(buf)[126976] = -1;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i8[126976]|0; } return f'), this, null, buf)(),-1);
+
+var buf = new ArrayBuffer(BUF_MIN);
+new Uint16Array(buf)[1] = -1;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u16[1]|0; } return f'), this, null, buf)(),65535);
+new Int16Array(buf)[1] = -1;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i16[1]|0; } return f'), this, null, buf)(),-1);
+var buf = new ArrayBuffer(262144);
+new Uint16Array(buf)[126976] = -1;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u16[126976]|0; } return f'), this, null, buf)(),65535);
+new Int16Array(buf)[126976] = -1;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i16[126976]|0; } return f'), this, null, buf)(),-1);
+
+var buf = new ArrayBuffer(BUF_MIN);
+new Uint32Array(buf)[1] = -1;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[1]|0; } return f'), this, null, buf)(),-1);
+new Int32Array(buf)[1] = -1;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[1]|0; } return f'), this, null, buf)(),-1);
+var buf = new ArrayBuffer(262144);
+new Int32Array(buf)[61440] = -1;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return i32[61440]|0; } return f'), this, null, buf)(),-1);
+
+var buf = new ArrayBuffer(BUF_MIN);
+new Float32Array(buf)[1] = -1.0;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f32[1]; } return f'), this, null, buf)(),-1.0);
+new Float32Array(buf)[BUF_MIN/4-1] = -1.0;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f32[' + (BUF_MIN/4-1) + ']; } return f'), this, null, buf)(),-1.0);
+new Float32Array(buf)[BUF_MIN/8] = -1.0;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f32[' + (BUF_MIN/8) + ']; } return f'), this, null, buf)(),-1.0);
+assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f32[' + (BUF_MIN/4) + ']; } return f'), this, null, buf);
+var buf = new ArrayBuffer(262144);
+new Float32Array(buf)[61440] = -1.0;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f32[61440]; } return f'), this, null, buf)(),-1.0);
+
+var buf = new ArrayBuffer(BUF_MIN);
+new Float64Array(buf)[1] = -1.0;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[1]; } return f'), this, null, buf)(),-1.0);
+new Float64Array(buf)[BUF_MIN/8-1] = -1.0;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[' + (BUF_MIN/8-1) + ']; } return f'), this, null, buf)(),-1.0);
+new Float64Array(buf)[BUF_MIN/16] = -1.0;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[' + (BUF_MIN/16) + ']; } return f'), this, null, buf)(),-1.0);
+assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[' + (BUF_MIN/8) + ']; } return f'), this, null, buf);
+var buf = new ArrayBuffer(262144);
+new Float64Array(buf)[28672] = -1.0;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +f64[28672]; } return f'), this, null, buf)(),-1.0);
+
+// Bug 913867
+var buf = new ArrayBuffer(BUF_MIN);
+new Int32Array(buf)[0] = 0x55aa5a5a;
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f1() { i32[0] = 1; return 8; }; function f() { return i32[((f1()|0)&0)>>2]|0; } return f'), this, null, buf)(),1);
+assertEq(new Int32Array(buf)[0], 1);
+
+// Bug 882012
+assertEq(asmLink(asmCompile('stdlib', 'foreign', 'heap', USE_ASM + "var id=foreign.id;var doubles=new stdlib.Float64Array(heap);function g(){doubles[0]=+id(2.0);return +doubles[0];}return g"), this, {id: function(x){return x;}}, BUF_64KB)(), 2.0);
+
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[4294967295]|0; } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=4294967295; function f() { return u8[i]|0; } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[-1]|0; } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-1; function f() { return u8[i]|0; } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[0x80000000]|0; } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=0x80000000; function f() { return u8[i]|0; } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[-2147483648]|0; } return f');
+assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-2147483648; function f() { return u8[i]|0; } return f');
+
+// GVN checks
+var buf = new ArrayBuffer(BUF_MIN);
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'var i=0; function f() { var x = 0, y = 0; u8[0] = 1; u8[1] = 2; x = 0|u8[i]; i = x; y = 0|u8[i]; return y|0;} return f'), this, null, buf)(),2);
+assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'var i=0; function f() { var x = 0, y = 0; u8[0] = 1; u8[1] = 2; x = 0|u8[i]; y = 0|u8[i]; return (x+y)|0;} return f'), this, null, buf)(),2);
+
+// Heap length constraints
+var m = asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f(i) { i=i|0; return u8[i]|0; } return f');
+assertAsmLinkAlwaysFail(m, this, null, new ArrayBuffer(0xffff));
+assertEq(asmLink(m, this, null, new ArrayBuffer(0x10000))(0),0);
+assertAsmLinkFail(m, this, null, new ArrayBuffer(0x10010));
+assertEq(asmLink(m, this, null, new ArrayBuffer(0x20000))(0),0);
+assertAsmLinkFail(m, this, null, new ArrayBuffer(0xfe0000));
+assertAsmLinkFail(m, this, null, new ArrayBuffer(0xfe0010));
+assertAsmLinkFail(m, this, null, new ArrayBuffer(0xfe0000));
+assertAsmLinkFail(m, this, null, new ArrayBuffer(0xff8000));
+var buf = new ArrayBuffer(0x100000);
+new Uint8Array(buf)[0x4242] = 0xAA;
+var f = asmLink(m, this, null, buf);
+assertEq(f(0),0);
+assertEq(f(0x4242),0xAA);
+assertEq(f(0x100000),0);
+assertAsmLinkFail(m, this, null, new ArrayBuffer(0x104000));
+assertEq(asmLink(m, this, null, new ArrayBuffer(0x200000))(0),0);
+assertAsmLinkFail(m, this, null, new ArrayBuffer(0x3f8000));
+assertAsmLinkFail(m, this, null, new ArrayBuffer(0x3fe000));
+assertAsmLinkFail(m, this, null, new ArrayBuffer(0x3fc000));
+assertEq(asmLink(m, this, null, new ArrayBuffer(0x400000))(0),0);
+assertAsmLinkFail(m, this, null, new ArrayBuffer(0x410000));
+assertEq(asmLink(m, this, null, new ArrayBuffer(0x800000))(0),0);
+var buf = new ArrayBuffer(0x1000000);
+new Uint8Array(buf)[0x424242] = 0xAA;
+var f = asmLink(m, this, null, buf);
+assertEq(f(0),0);
+assertEq(f(0x424242),0xAA);
+assertEq(f(0x1000000),0);
+assertEq(asmLink(m, this, null, new ArrayBuffer(0x2000000))(0),0);
+assertEq(asmLink(m, this, null, new ArrayBuffer(0x3000000))(0),0);
+
+// Heap offsets
+var asmMod = function test (glob, env, b) {
+ 'use asm';
+ var i8 = new glob.Int8Array(b);
+ function f(i) {
+ i = i | 0;
+ i = i & 1;
+ i = (i - 0x40000)|0;
+ i8[0x3ffff] = 0;
+ return i8[(i + 0x7fffe) >> 0] | 0;
+ }
+ return f;
+};
+var buffer = new ArrayBuffer(0x40000);
+var asm = asmMod(this, {}, buffer);
+assertEq(asm(-1),0);
diff --git a/js/src/jit-test/tests/asm.js/testJumpRange.js b/js/src/jit-test/tests/asm.js/testJumpRange.js
new file mode 100644
index 000000000..bd983544b
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testJumpRange.js
@@ -0,0 +1,46 @@
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+var fatFunc = USE_ASM + '\n';
+for (var i = 0; i < 100; i++)
+ fatFunc += "function f" + i + "() { return ((f" + (i+1) + "()|0)+1)|0 }\n";
+fatFunc += "function f100() { return 42 }\n";
+fatFunc += "return f0";
+
+for (let threshold of [0, 50, 100, 5000, -1]) {
+ setJitCompilerOption("jump-threshold", threshold);
+
+ assertEq(asmCompile(
+ USE_ASM + `
+ function h() { return ((g()|0)+2)|0 }
+ function g() { return ((f()|0)+1)|0 }
+ function f() { return 42 }
+ return h
+ `)()(), 45);
+
+ if (isSimdAvailable() && this.SIMD) {
+ var buf = new ArrayBuffer(BUF_MIN);
+ new Int32Array(buf)[0] = 10;
+ new Float32Array(buf)[1] = 42;
+ assertEq(asmCompile('stdlib', 'ffis', 'buf',
+ USE_ASM + `
+ var H = new stdlib.Uint8Array(buf);
+ var i4 = stdlib.SIMD.Int32x4;
+ var f4 = stdlib.SIMD.Float32x4;
+ var i4load = i4.load;
+ var f4load = f4.load;
+ var toi4 = i4.fromFloat32x4;
+ var i4ext = i4.extractLane;
+ function f(i) { i=i|0; return i4ext(i4load(H, i), 0)|0 }
+ function g(i) { i=i|0; return (i4ext(toi4(f4load(H, i)),1) + (f(i)|0))|0 }
+ function h(i) { i=i|0; return g(i)|0 }
+ return h
+ `)(this, null, buf)(0), 52);
+ }
+
+ enableSPSProfiling();
+ asmLink(asmCompile(USE_ASM + 'function f() {} function g() { f() } function h() { g() } return h'))();
+ disableSPSProfiling();
+
+ assertEq(asmCompile(fatFunc)()(), 142);
+}
diff --git a/js/src/jit-test/tests/asm.js/testLinkErrorAssert.js b/js/src/jit-test/tests/asm.js/testLinkErrorAssert.js
new file mode 100644
index 000000000..9084d72a2
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testLinkErrorAssert.js
@@ -0,0 +1,20 @@
+// This test should not assert.
+
+function asmModule(g, foreign, heap) {
+ "use asm";
+ let HEAP8 = new g.Int8Array(heap);
+
+ function f() { return 99; }
+ return {f: f};
+}
+
+// linking error
+let m = asmModule(this, 2, new ArrayBuffer(4095));
+
+print(m.f());
+
+// linking error
+let m2 = asmModule(this, 2, new ArrayBuffer(2048));
+
+print(m2.f());
+
diff --git a/js/src/jit-test/tests/asm.js/testLiterals.js b/js/src/jit-test/tests/asm.js/testLiterals.js
new file mode 100644
index 000000000..1a24002af
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testLiterals.js
@@ -0,0 +1,50 @@
+load(libdir + 'asm.js');
+
+assertAsmTypeFail(USE_ASM + 'function f(d) { d=+d; var e=0; e=d; return +e } return f');
+assertAsmTypeFail(USE_ASM + 'function f(d) { d=+d; var e=1e1; e=d; return +e } return f');
+assertAsmTypeFail(USE_ASM + 'function f(d) { d=+d; var e=+0; e=d; return +e } return f');
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() { var e=-0; return +e } return f'))(-0), -0);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() { var e=-0.0; return +e } return f'))(-0), -0);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=0.0; e=d; return +e } return f'))(0.1), 0.1);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=-0.0; e=d; return +e } return f'))(0.1), 0.1);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=10.0; e=d; return +e } return f'))(0.1), 0.1);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=-10.0; e=d; return +e } return f'))(0.1), 0.1);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=1.0e2; e=d; return +e } return f'))(0.1), 0.1);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=-1.0e2; e=d; return +e } return f'))(0.1), 0.1);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=1.0e0; e=d; return +e } return f'))(0.1), 0.1);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=-1.0e0; e=d; return +e } return f'))(0.1), 0.1);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return 0.0 } function g() { var d=0.1; d=+f(); return +d } return g'))(), 0);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return -0.0 } function g() { var d=0.1; d=+f(); return +d } return g'))(), -0);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return 10.0 } function g() { var d=0.1; d=+f(); return +d } return g'))(), 10);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return -10.0 } function g() { var d=0.1; d=+f(); return +d } return g'))(), -10.0);
+
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=1e10; j=i; return j|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=9007199254740991e0; j=i; return j|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=9007199254740992e0; j=i; return j|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=9007199254740993e0; j=i; return j|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=-9007199254740991e0; j=i; return j|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=-9007199254740992e0; j=i; return j|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=-9007199254740993e0; j=i; return j|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=1e100; j=i; return j|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=1e10000; j=i; return j|0 } return f");
+assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=1000000000000000000; j=i; return j|0 } return f");
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=1e0; j=i; return j|0 } return f"))(42), 42);
+assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; var j=1e9; j=i; return j|0 } return f"))(42), 42);
+
+assertAsmTypeFail(USE_ASM + 'function f() { var i=-2147483649; return i|0 } return f');
+assertAsmTypeFail(USE_ASM + 'function f() { var i=4294967296; return i|0 } return f');
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() { var i=-2147483648; return i|0 } return f'))(), -2147483648);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f() { var i=4294967295; return i|0 } return f'))(), 4294967295|0);
+assertAsmTypeFail(USE_ASM + 'function f(i) { i=i|0; return (i+-2147483649)|0 } return f');
+assertAsmTypeFail(USE_ASM + 'function f(i) { i=i|0; return (i+4294967296)|0 } return f');
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) { i=i|0; return (i+-2147483648)|0 } return f'))(0), -2147483648);
+assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) { i=i|0; return (i+4294967295)|0 } return f'))(0), 4294967295|0);
+
+assertAsmTypeFail(USE_ASM + 'var i=-2147483649; function f() { return i|0 } return f');
+assertAsmTypeFail(USE_ASM + 'const i=-2147483649; function f() { return i|0 } return f');
+assertAsmTypeFail(USE_ASM + 'var i=4294967296; function f() { return i|0 } return f');
+assertAsmTypeFail(USE_ASM + 'const i=4294967296; function f() { return i|0 } return f');
+assertEq(asmLink(asmCompile(USE_ASM + 'var i=-2147483648; function f() { return i|0 } return f'))(), -2147483648);
+assertEq(asmLink(asmCompile(USE_ASM + 'const i=-2147483648; function f() { return i|0 } return f'))(), -2147483648);
+assertEq(asmLink(asmCompile(USE_ASM + 'var i=4294967295; function f() { return i|0 } return f'))(), 4294967295|0);
+assertEq(asmLink(asmCompile(USE_ASM + 'const i=4294967295; function f() { return i|0 } return f'))(), 4294967295|0);
diff --git a/js/src/jit-test/tests/asm.js/testMathLib.js b/js/src/jit-test/tests/asm.js/testMathLib.js
new file mode 100644
index 000000000..5c2eb9db4
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testMathLib.js
@@ -0,0 +1,189 @@
+load(libdir + "asm.js");
+
+function testUnary(f, g) {
+ var numbers = [NaN, Infinity, -Infinity, -10000, -3.4, -0, 0, 3.4, 10000];
+ for (n of numbers)
+ assertEq(f(n), g(n));
+}
+
+const FROUND = 'var fround=glob.Math.fround;';
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sin; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sin:Math.sqrt}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sin; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sin:null}});
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sin; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sin:Math.sin}}), Math.sin);
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'const sq=glob.Math.sin; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sin:Math.sin}}), Math.sin);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var co=glob.Math.cos; function f(d) { d=+d; return +co(d) } return f'), {Math:{cos:Math.sqrt}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var co=glob.Math.cos; function f(d) { d=+d; return +co(d) } return f'), {Math:{cos:null}});
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'var co=glob.Math.cos; function f(d) { d=+d; return +co(d) } return f'), {Math:{cos:Math.cos}}), Math.cos);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var ta=glob.Math.tan; function f(d) { d=+d; return +ta(d) } return f'), {Math:{tan:Math.sqrt}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var ta=glob.Math.tan; function f(d) { d=+d; return +ta(d) } return f'), {Math:{tan:null}});
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'var ta=glob.Math.tan; function f(d) { d=+d; return +ta(d) } return f'), {Math:{tan:Math.tan}}), Math.tan);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var as=glob.Math.asin; function f(d) { d=+d; return +as(d) } return f'), {Math:{asin:Math.sqrt}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var as=glob.Math.asin; function f(d) { d=+d; return +as(d) } return f'), {Math:{asin:null}});
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'var as=glob.Math.asin; function f(d) { d=+d; return +as(d) } return f'), {Math:{asin:Math.asin}}), Math.asin);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var ac=glob.Math.acos; function f(d) { d=+d; return +ac(d) } return f'), {Math:{acos:Math.sqrt}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var ac=glob.Math.acos; function f(d) { d=+d; return +ac(d) } return f'), {Math:{acos:null}});
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'var ac=glob.Math.acos; function f(d) { d=+d; return +ac(d) } return f'), {Math:{acos:Math.acos}}), Math.acos);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var at=glob.Math.atan; function f(d) { d=+d; return +at(d) } return f'), {Math:{atan:Math.sqrt}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var at=glob.Math.atan; function f(d) { d=+d; return +at(d) } return f'), {Math:{atan:null}});
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'var at=glob.Math.atan; function f(d) { d=+d; return +at(d) } return f'), {Math:{atan:Math.atan}}), Math.atan);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var ce=glob.Math.ceil; function f(d) { d=+d; return +ce(d) } return f'), {Math:{ceil:Math.sqrt}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var ce=glob.Math.ceil; function f(d) { d=+d; return +ce(d) } return f'), {Math:{ceil:null}});
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'var ce=glob.Math.ceil; function f(d) { d=+d; return +ce(d) } return f'), {Math:{ceil:Math.ceil}}), Math.ceil);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var fl=glob.Math.floor; function f(d) { d=+d; return +fl(d) } return f'), {Math:{floor:Math.sqrt}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var fl=glob.Math.floor; function f(d) { d=+d; return +fl(d) } return f'), {Math:{floor:null}});
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'var fl=glob.Math.floor; function f(d) { d=+d; return +fl(d) } return f'), {Math:{floor:Math.floor}}), Math.floor);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var exq=glob.Math.exp; function f(d) { d=+d; return +exq(d) } return f'), {Math:{exp:Math.sqrt}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var exq=glob.Math.exp; function f(d) { d=+d; return +exq(d) } return f'), {Math:{exp:null}});
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'var exq=glob.Math.exp; function f(d) { d=+d; return +exq(d) } return f'), {Math:{exp:Math.exp}}), Math.exp);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var lo=glob.Math.log; function f(d) { d=+d; return +lo(d) } return f'), {Math:{log:Math.sqrt}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var lo=glob.Math.log; function f(d) { d=+d; return +lo(d) } return f'), {Math:{log:null}});
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'var lo=glob.Math.log; function f(d) { d=+d; return +lo(d) } return f'), {Math:{log:Math.log}}), Math.log);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sqrt; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sqrt:Math.sin}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sqrt; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sqrt:null}});
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sqrt; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sqrt:Math.sqrt}}), Math.sqrt);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=+d; return +abs(d) } return f'), {Math:{abs:Math.sin}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=+d; return +abs(d) } return f'), {Math:{abs:null}});
+testUnary(asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=+d; return +abs(d) } return f'), {Math:{abs:Math.abs}}), Math.abs);
+
+var f = asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(i) { i=i|0; return abs(i|0)|0 } return f'), this);
+for (n of [-Math.pow(2,31)-1, -Math.pow(2,31), -Math.pow(2,31)+1, -1, 0, 1, Math.pow(2,31)-2, Math.pow(2,31)-1, Math.pow(2,31)])
+ assertEq(f(n), Math.abs(n|0)|0);
+
+var f = asmLink(asmCompile('glob', USE_ASM + 'var clz32=glob.Math.clz32; function f(i) { i=i|0; return clz32(i)|0 } return f'), this);
+for (n of [0, 1, 2, 15, 16, Math.pow(2,31)-1, Math.pow(2,31), Math.pow(2,31)+1, Math.pow(2,32)-1, Math.pow(2,32), Math.pow(2,32)+1])
+ assertEq(f(n), Math.clz32(n|0));
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var clz32=glob.Math.clz32; function f(i, j) { i=i|0;j=j|0; return (clz32(i) < (j|0))|0 } return f'), this)(0x1, 30), 0);
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var clz32=glob.Math.clz32; function f(i, j) { i=i|0;j=j|0; return (clz32(i) < (j>>>0))|0 } return f'), this)(0x1, 30), 0);
+
+var doubleNumbers = [NaN, Infinity, -Infinity, -10000, -3.4, -0, 0, 3.4, 10000];
+var floatNumbers = [];
+for (var x of doubleNumbers) floatNumbers.push(Math.fround(x));
+var intNumbers = [-Math.pow(2,31), -10000, -3, -1, 0, 3, 10000, Math.pow(2,31), Math.pow(2,31)+1];
+
+function testBinary(f, g, numbers) {
+ for (n of numbers)
+ for (o of numbers)
+ assertEq(f(n,o), g(n,o));
+}
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var po=glob.Math.pow; function f(d,e) { d=+d;e=+e; return +po(d,e) } return f'), {Math:{pow:Math.sin}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var po=glob.Math.pow; function f(d,e) { d=+d;e=+e; return +po(d,e) } return f'), {Math:{pow:null}});
+testBinary(asmLink(asmCompile('glob', USE_ASM + 'var po=glob.Math.pow; function f(d,e) { d=+d;e=+e; return +po(d,e) } return f'), {Math:{pow:Math.pow}}), Math.pow, doubleNumbers);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var at=glob.Math.atan2; function f(d,e) { d=+d;e=+e; return +at(d,e) } return f'), {Math:{atan2:Math.sin}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var at=glob.Math.atan2; function f(d,e) { d=+d;e=+e; return +at(d,e) } return f'), {Math:{atan2:null}});
+testBinary(asmLink(asmCompile('glob', USE_ASM + 'var at=glob.Math.atan2; function f(d,e) { d=+d;e=+e; return +at(d,e) } return f'), {Math:{atan2:Math.atan2}}), Math.atan2, doubleNumbers);
+
+function coercedMin(...args) { for (var i = 0; i < args.length; i++) args[i] = args[i]|0; return Math.min(...args) }
+function coercedMax(...args) { for (var i = 0; i < args.length; i++) args[i] = args[i]|0; return Math.max(...args) }
+assertAsmTypeFail('glob', USE_ASM + 'var min=glob.Math.min; function f(d) { d=+d; return +min(d) } return f');
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + 'var i32=new glob.Int32Array(heap); var min=glob.Math.min; function f() { return min(i32[0], 5)|0 } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var min=glob.Math.min; function f(x) { x=x|0; return min(3 + x, 5)|0 } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var min=glob.Math.min; function f(x) { x=x|0; return min(5, 3 + x)|0 } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var min=glob.Math.min; function f(x) { x=x|0; return min(x, 1)|0 } return f');
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e) { d=+d;e=+e; return +min(d,e) } return f'), {Math:{min:Math.sin}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e) { d=+d;e=+e; return +min(d,e) } return f'), {Math:{min:null}});
+testBinary(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e) { d=+d;e=+e; return +min(d,e) } return f'), {Math:{min:Math.min}}), Math.min, doubleNumbers);
+testBinary(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; var f32=glob.Math.fround; function f(d,e) { d=f32(d);e=f32(e); return f32(min(d,e)) } return f'), this), Math.min, floatNumbers);
+testBinary(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e) { d=d|0;e=e|0; return min(d|0,e|0)|0} return f'), {Math:{min:Math.min}}), coercedMin, intNumbers);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e) { d=+d;e=+e; return +max(d,e) } return f'), {Math:{max:Math.sin}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e) { d=+d;e=+e; return +max(d,e) } return f'), {Math:{max:null}});
+testBinary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e) { d=+d;e=+e; return +max(d,e) } return f'), {Math:{max:Math.max}}), Math.max, doubleNumbers);
+testBinary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; var f32=glob.Math.fround; function f(d,e) { d=f32(d);e=f32(e); return f32(max(d,e)) } return f'), this), Math.max, floatNumbers);
+testBinary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e) { d=d|0;e=e|0; return max(d|0,e|0)|0} return f'), {Math:{max:Math.max}}), coercedMax, intNumbers);
+
+function testTernary(f, g, numbers) {
+ for (n of numbers)
+ for (o of numbers)
+ for (p of numbers)
+ assertEq(f(n,o,p), g(n,o,p));
+}
+
+assertAsmTypeFail('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e,g) { d=+d;e=+e;g=g|0; return +min(d,e,g) } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e,g) { d=d|0;e=e|0;g=+g; return max(d,e,g)|0 } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e,g) { d=+d;e=+e;g=+g; return min(d,e,g)|0 } return f');
+testTernary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e,g) { d=d|0;e=e|0;g=g|0; return +max(d|0,e|0,g|0) } return f'), {Math:{max:Math.max}}), coercedMax, intNumbers);
+testTernary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e,g) { d=d|0;e=e|0;g=g|0; return max(d|0,e|0,g|0)|0 } return f'), {Math:{max:Math.max}}), coercedMax, intNumbers);
+testTernary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d,e,g) { d=+d;e=+e;g=+g; return +max(d,e,g) } return f'), {Math:{max:Math.max}}), Math.max, doubleNumbers);
+testTernary(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; var _=glob.Math.fround; function f(d,e,g) { d=_(d);e=_(e);g=_(g); return _(max(d,e,g)) } return f'), this), Math.max, floatNumbers);
+testTernary(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e,g) { d=d|0;e=e|0;g=g|0; return min(d|0,e|0,g|0)|0 } return f'), {Math:{min:Math.min}}), coercedMin, intNumbers);
+testTernary(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d,e,g) { d=+d;e=+e;g=+g; return +min(d,e,g) } return f'), {Math:{min:Math.min}}), Math.min, doubleNumbers);
+testTernary(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; var _=glob.Math.fround; function f(d,e,g) { d=_(d);e=_(e);g=_(g); return _(min(d,e,g)) } return f'), this), Math.min, floatNumbers);
+
+// Implicit return coercions of math functions
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i) { i=i|0; i = im(i,i); return i|0 } return f'), this)(3), 9);
+assertAsmTypeFail('glob', USE_ASM + 'var im=glob.Math.imul; function f(d) { d=+d; d = im(d, d) } return f');
+assertAsmTypeFail('glob', USE_ASM + FROUND + 'var im=glob.Math.imul; function f(d) { d=fround(d); d = im(d, d) } return f');
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=d|0; d = abs(d|0); return +(d>>>0) } return f'), this)(-1), 1);
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=d|0; var m = 0; m = (-1)>>>0; return (abs(d|0) < (m>>>0))|0 } return f'), this)(42), 1);
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=+d; d = abs(d); return +d } return f'), this)(-1.5), 1.5);
+assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var abs=glob.Math.abs; function f(d) { d=fround(d); d = fround(abs(d)); return +d } return f'), this)(-1.5), 1.5);
+assertAsmTypeFail('glob', USE_ASM + FROUND + 'var abs=glob.Math.abs; function f(d) { d=fround(d); d = abs(d); return +d } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=d|0; var m = 0; m = -1; return (abs(d|0) < (m|0))|0 } return f');
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var sqrt=glob.Math.sqrt; function f(d) { d=+d; d = sqrt(d); return +d } return f'), this)(256), 16);
+assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var sqrt=glob.Math.sqrt; function f(d) { d=fround(d); d = fround(sqrt(d)); return +d } return f'), this)(13.37), Math.fround(Math.sqrt(Math.fround(13.37))));
+assertAsmTypeFail('glob', USE_ASM + FROUND + 'var sqrt=glob.Math.sqrt; function f(d) { d=fround(d); d = sqrt(d); return fround(d) } return f');
+assertAsmTypeFail('glob', USE_ASM + FROUND + 'var sqrt=glob.Math.sqrt; function f(d) { d=fround(d); d = sqrt(d); return d } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var sqrt=glob.Math.sqrt; function f(n) { n=n|0; var d=0.; d = sqrt(n|0) } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var sqrt=glob.Math.sqrt; function f(n) { n=n|0; var d=3.; n = sqrt(d)|0 } return f');
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d) { d=+d; d = min(d, 13.); return +d } return f'), this)(12), 12);
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d) { d=d|0; d = min(d|0, 11); return d|0 } return f'), this)(12), 11);
+assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var min=glob.Math.min; function f(d) { d=fround(d); d = min(d, fround(13.37)); return fround(d) } return f'), this)(14), Math.fround(13.37));
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var sin=glob.Math.sin; function f(d) { d=+d; d = sin(d); return +d } return f'), this)(Math.PI), Math.sin(Math.PI));
+assertAsmTypeFail('glob', USE_ASM + FROUND + 'var sin=glob.Math.sin; function f(d) { d=fround(d); d = sin(d) } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var sin=glob.Math.sin; function f(d) { d=d|0; d = sin(d) } return f');
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var pow=glob.Math.pow; function f(d) { d=+d; d = pow(d,d); return +d } return f'), this)(3), 27);
+assertAsmTypeFail('glob', USE_ASM + FROUND + 'var pow=glob.Math.pow; function f(d) { d=fround(d); d = pow(d, d) } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var pow=glob.Math.pow; function f(d) { d=d|0; d = pow(d, d) } return f');
+
+assertAsmTypeFail('glob', USE_ASM + 'var sin=glob.Math.sin; function f(d) { d=+d; var i=0; i = sin(d)|0; } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var pow=glob.Math.pow; function f(d) { d=+d; var i=0; i = pow(d,d)|0; } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var atan2=glob.Math.atan2; function f(d) { d=+d; var i=0; i = atan2(d,d)|0; } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var sqrt=glob.Math.sqrt; function f(d) { d=+d; sqrt(d)|0; } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=+d; abs(d)|0; } return f');
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var im=glob.Math.imul; function f(i) { i=i|0; var d=0.0; d = +im(i,i); return +d } return f'), this)(42), Math.imul(42, 42));
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(i) { i=i|0; var d=0.0; d = +abs(i|0); return +d } return f'), this)(-42), 42);
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(i) { i=i|0; var d=0.0; d = +min(i|0, 0); return +d } return f'), this)(-42), -42);
+assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var min=glob.Math.min; function f(i) { i=i|0; var d=fround(0); d = fround(min(i|0, 0)); return +d } return f'), this)(-42), -42);
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(i) { i=i|0; var d=0.0; d = +max(i|0, 0); return +d } return f'), this)(-42), 0);
+assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var max=glob.Math.max; function f(i) { i=i|0; var d=fround(0); d = fround(max(i|0, 0)); return +d } return f'), this)(-42), 0);
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var min=glob.Math.min; function f(d) { d=+d; var i=0; i = ~~min(d, 0.)|0; return i|0 } return f'), this)(-42), -42);
+assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var min=glob.Math.min; function f(d) { d=fround(d); var i=0; i = ~~min(d, fround(0))|0; return i|0 } return f'), this)(-42), -42);
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var max=glob.Math.max; function f(d) { d=+d; var i=0; i = ~~max(d, 0.)|0; return i|0 } return f'), this)(-42), 0);
+assertEq(asmLink(asmCompile('glob', USE_ASM + FROUND + 'var max=glob.Math.max; function f(d) { d=fround(d); var i=0; i = ~~max(d, fround(0))|0; return i|0 } return f'), this)(-42), 0);
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + 'var abs=glob.Math.abs; function f(i) { i=i|0; var d=0.0; return +d; +abs(i|0); return 3.0;} return f'), this)(-42), 0);
+
+assertAsmTypeFail('glob', USE_ASM + 'var tau=glob.Math.TAU; function f() {} return f');
+assertAsmTypeFail('glob', USE_ASM + 'var pi=glob.Math.PI; function f() { return pi | 0 } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var pi=glob.Math.PI; function f() { return +pi() } return f');
+assertAsmTypeFail('glob', USE_ASM + 'var pi=glob.Math.PI; function f() { pi = +3; } return f');
+assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + 'var pi=glob.Math.PI; function f() {} return f'), {});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var pi=glob.Math.PI; function f() {} return f'), {Math: {}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var pi=glob.Math.PI; function f() {} return f'), {Math: {PI: Math.cos}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var pi=glob.Math.PI; function f() {} return f'), {Math: {PI: Math.SQRT2}});
+
+for (var c of ['E', 'LN10', 'LN2', 'LOG2E', 'LOG10E', 'PI', 'SQRT1_2', 'SQRT2']) {
+ var f = asmLink(asmCompile('glob', USE_ASM + 'var x=glob.Math.' + c +'; function f() { return +x } return f'), this);
+ assertEq(f(), eval('Math.' + c));
+}
diff --git a/js/src/jit-test/tests/asm.js/testModuleFunctions.js b/js/src/jit-test/tests/asm.js/testModuleFunctions.js
new file mode 100644
index 000000000..2e3c80f45
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testModuleFunctions.js
@@ -0,0 +1,41 @@
+
+function testUniqueness(asmJSModule) {
+ var f = asmJSModule();
+ var g = asmJSModule();
+ assertEq(f === g, false);
+ f.x = 4;
+ assertEq(f.x, 4);
+ assertEq(g.x, undefined);
+}
+
+function deffun() {
+ if (Math.sin) {
+ function inner() { "use asm"; function g() {} return g }
+ }
+ return inner;
+}
+
+testUniqueness(deffun);
+
+function lambda() {
+ var x = function inner() { "use asm"; function g() {} return g };
+ return x;
+}
+
+testUniqueness(lambda);
+
+function inEval() {
+ eval("function inner() { 'use asm'; function g() {} return g }");
+ return inner;
+}
+
+testUniqueness(inEval);
+
+function inWith() {
+ with ({}) {
+ function inner() { "use asm"; function g() {} return g }
+ }
+ return inner;
+}
+
+testUniqueness(inWith);
diff --git a/js/src/jit-test/tests/asm.js/testNeuter.js b/js/src/jit-test/tests/asm.js/testNeuter.js
new file mode 100644
index 000000000..e7c743bf7
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testNeuter.js
@@ -0,0 +1,44 @@
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+if (!isAsmJSCompilationAvailable())
+ quit();
+
+var m = asmCompile('stdlib', 'foreign', 'buffer',
+ `"use asm";
+ var i32 = new stdlib.Int32Array(buffer);
+ function set(i,j) {
+ i=i|0;
+ j=j|0;
+ i32[i>>2] = j;
+ }
+ function get(i) {
+ i=i|0;
+ return i32[i>>2]|0
+ }
+ return {get:get, set:set}`);
+
+var buffer = new ArrayBuffer(BUF_MIN);
+var {get, set} = asmLink(m, this, null, buffer);
+set(4, 42);
+assertEq(get(4), 42);
+assertThrowsInstanceOf(() => detachArrayBuffer(buffer), Error);
+
+var m = asmCompile('stdlib', 'foreign', 'buffer',
+ `"use asm";
+ var i32 = new stdlib.Int32Array(buffer);
+ var ffi = foreign.ffi;
+ function inner(i) {
+ i=i|0;
+ ffi();
+ return i32[i>>2]|0
+ }
+ return inner`);
+
+var buffer = new ArrayBuffer(BUF_MIN);
+function ffi1()
+{
+ assertThrowsInstanceOf(() => detachArrayBuffer(buffer), Error);
+}
+
+var inner = asmLink(m, this, {ffi: ffi1}, buffer);
diff --git a/js/src/jit-test/tests/asm.js/testParallelCompile.js b/js/src/jit-test/tests/asm.js/testParallelCompile.js
new file mode 100644
index 000000000..41f879735
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testParallelCompile.js
@@ -0,0 +1,26 @@
+load(libdir + "asm.js");
+
+if (!isAsmJSCompilationAvailable())
+ quit();
+
+var module = "'use asm';\n";
+for (var i = 0; i < 100; i++) {
+ module += "function f" + i + "(i) {\n";
+ module += " i=i|0; var j=0; j=(i+1)|0; i=(j-4)|0; i=(i+j)|0; return i|0\n";
+ module += "}\n";
+}
+module += "return f0";
+var script = "(function() {\n" + module + "})";
+
+for (var i = 0; i < 10; i++) {
+ try {
+ offThreadCompileScript(script);
+ var f = new Function(module);
+ var g = runOffThreadScript();
+ assertEq(isAsmJSModule(f), true);
+ assertEq(isAsmJSModule(g), true);
+ } catch (e) {
+ // ignore spurious error when offThreadCompileScript can't run in
+ // parallel
+ }
+}
diff --git a/js/src/jit-test/tests/asm.js/testProfiling.js b/js/src/jit-test/tests/asm.js/testProfiling.js
new file mode 100644
index 000000000..564f6f359
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testProfiling.js
@@ -0,0 +1,246 @@
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+// Run test only for asm.js
+if (!isAsmJSCompilationAvailable())
+ quit();
+
+// Single-step profiling currently only works in the ARM simulator
+if (!getBuildConfiguration()["arm-simulator"])
+ quit();
+
+function checkSubSequence(got, expect)
+{
+ var got_i = 0;
+ EXP: for (var exp_i = 0; exp_i < expect.length; exp_i++) {
+ var item = expect[exp_i];
+ // Scan for next match in got.
+ while (got_i < got.length) {
+ if (got[got_i++] == expect[exp_i])
+ continue EXP;
+ }
+ print("MISMATCH: " + got.join(",") + "\n" +
+ " VS " + expect.join(","));
+ return false;
+ }
+ return true;
+}
+
+function assertStackContainsSeq(got, expect)
+{
+ var normalized = [];
+
+ for (var i = 0; i < got.length; i++) {
+ if (got[i].length == 0)
+ continue;
+ var parts = got[i].split(',');
+ for (var j = 0; j < parts.length; j++) {
+ var frame = parts[j];
+ frame = frame.replace(/ \([^\)]*\)/g, "");
+ frame = frame.replace(/(fast|slow) FFI trampoline/g, "<");
+ frame = frame.replace(/entry trampoline/g, ">");
+ frame = frame.replace(/(\/[^\/,<]+)*\/testProfiling.js/g, "");
+ frame = frame.replace(/testBuiltinD2D/g, "");
+ frame = frame.replace(/testBuiltinF2F/g, "");
+ frame = frame.replace(/testBuiltinDD2D/g, "");
+ frame = frame.replace(/assertThrowsInstanceOf/g, "");
+ frame = frame.replace(/^ffi[12]?/g, "");
+ normalized.push(frame);
+ }
+ }
+
+ var gotNorm = normalized.join(',').replace(/,+/g, ",");
+ gotNorm = gotNorm.replace(/^,/, "").replace(/,$/, "");
+
+ assertEq(checkSubSequence(gotNorm.split(','), expect.split(',')), true);
+}
+
+// Test profiling enablement while asm.js is running.
+var stacks;
+var ffi = function(enable) {
+ if (enable == +1)
+ enableSPSProfiling();
+ enableSingleStepProfiling();
+ stacks = disableSingleStepProfiling();
+ if (enable == -1)
+ disableSPSProfiling();
+}
+var f = asmLink(asmCompile('global','ffis',USE_ASM + "var ffi=ffis.ffi; function g(i) { i=i|0; ffi(i|0) } function f(i) { i=i|0; g(i|0) } return f"), null, {ffi});
+f(0);
+assertStackContainsSeq(stacks, "");
+f(+1);
+assertStackContainsSeq(stacks, "");
+f(0);
+assertStackContainsSeq(stacks, "<,g,f,>");
+f(-1);
+assertStackContainsSeq(stacks, "<,g,f,>");
+f(0);
+assertStackContainsSeq(stacks, "");
+
+// Enable profiling for the rest of the tests.
+enableSPSProfiling();
+
+var f = asmLink(asmCompile(USE_ASM + "function f() { return 42 } return f"));
+enableSingleStepProfiling();
+assertEq(f(), 42);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f,>,>");
+
+var m = asmCompile(USE_ASM + "function g(i) { i=i|0; return (i+1)|0 } function f() { return g(42)|0 } return f");
+for (var i = 0; i < 3; i++) {
+ var f = asmLink(m);
+ enableSingleStepProfiling();
+ assertEq(f(), 43);
+ var stacks = disableSingleStepProfiling();
+ assertStackContainsSeq(stacks, ">,f,>,g,f,>,f,>,>");
+}
+
+var m = asmCompile(USE_ASM + "function g1() { return 1 } function g2() { return 2 } function f(i) { i=i|0; return TBL[i&1]()|0 } var TBL=[g1,g2]; return f");
+for (var i = 0; i < 3; i++) {
+ var f = asmLink(m);
+ enableSingleStepProfiling();
+ assertEq(f(0), 1);
+ assertEq(f(1), 2);
+ var stacks = disableSingleStepProfiling();
+ assertStackContainsSeq(stacks, ">,f,>,g1,f,>,f,>,>,>,f,>,g2,f,>,f,>,>");
+}
+
+function testBuiltinD2D(name) {
+ var m = asmCompile('g', USE_ASM + "var fun=g.Math." + name + "; function f(d) { d=+d; return +fun(d) } return f");
+ for (var i = 0; i < 3; i++) {
+ var f = asmLink(m, this);
+ enableSingleStepProfiling();
+ assertEq(f(.1), eval("Math." + name + "(.1)"));
+ var stacks = disableSingleStepProfiling();
+ assertStackContainsSeq(stacks, ">,f,>,native call,>,f,>,>");
+ }
+}
+for (name of ['sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'ceil', 'floor', 'exp', 'log'])
+ testBuiltinD2D(name);
+
+function testBuiltinF2F(name) {
+ var m = asmCompile('g', USE_ASM + "var tof=g.Math.fround; var fun=g.Math." + name + "; function f(d) { d=tof(d); return tof(fun(d)) } return f");
+ for (var i = 0; i < 3; i++) {
+ var f = asmLink(m, this);
+ enableSingleStepProfiling();
+ assertEq(f(.1), eval("Math.fround(Math." + name + "(Math.fround(.1)))"));
+ var stacks = disableSingleStepProfiling();
+ assertStackContainsSeq(stacks, ">,f,>,native call,>,f,>,>");
+ }
+}
+for (name of ['ceil', 'floor'])
+ testBuiltinF2F(name);
+
+function testBuiltinDD2D(name) {
+ var m = asmCompile('g', USE_ASM + "var fun=g.Math." + name + "; function f(d, e) { d=+d; e=+e; return +fun(d,e) } return f");
+ for (var i = 0; i < 3; i++) {
+ var f = asmLink(m, this);
+ enableSingleStepProfiling();
+ assertEq(f(.1, .2), eval("Math." + name + "(.1, .2)"));
+ var stacks = disableSingleStepProfiling();
+ assertStackContainsSeq(stacks, ">,f,>,native call,>,f,>,>");
+ }
+}
+for (name of ['atan2', 'pow'])
+ testBuiltinDD2D(name);
+
+// FFI tests:
+setJitCompilerOption("ion.warmup.trigger", 10);
+setJitCompilerOption("baseline.warmup.trigger", 0);
+setJitCompilerOption("offthread-compilation.enable", 0);
+
+var m = asmCompile('g','ffis', USE_ASM + "var ffi1=ffis.ffi1, ffi2=ffis.ffi2; function f() { return ((ffi1()|0) + (ffi2()|0))|0 } return f");
+
+var ffi1 = function() { return 10 }
+var ffi2 = function() { return 73 }
+var f = asmLink(m, null, {ffi1,ffi2});
+
+// Interp FFI exit
+enableSingleStepProfiling();
+assertEq(f(), 83);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>");
+
+// Ion FFI exit
+for (var i = 0; i < 20; i++)
+ assertEq(f(), 83);
+enableSingleStepProfiling();
+assertEq(f(), 83);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>");
+
+var ffi1 = function() { return { valueOf() { return 20 } } }
+var ffi2 = function() { return { valueOf() { return 74 } } }
+var f = asmLink(m, null, {ffi1,ffi2});
+
+// Interp FFI exit
+enableSingleStepProfiling();
+assertEq(f(), 94);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>"); // TODO: add 'valueOf' once interp shows up
+
+// Ion FFI exit
+for (var i = 0; i < 20; i++)
+ assertEq(f(), 94);
+enableSingleStepProfiling();
+assertEq(f(), 94);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>"); // TODO: add 'valueOf' once interp shows up
+
+var ffi1 = function() { return 15 }
+var ffi2 = function() { return f2() + 17 }
+var {f1,f2} = asmLink(asmCompile('g','ffis', USE_ASM + "var ffi1=ffis.ffi1, ffi2=ffis.ffi2; function f2() { return ffi1()|0 } function f1() { return ffi2()|0 } return {f1:f1, f2:f2}"), null, {ffi1, ffi2});
+// Interpreter FFI exit
+enableSingleStepProfiling();
+assertEq(f1(), 32);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f1,>,<,f1,>,>,<,f1,>,f2,>,<,f1,>,<,f2,>,<,f1,>,f2,>,<,f1,>,>,<,f1,>,<,f1,>,f1,>,>");
+
+
+// Ion FFI exit
+for (var i = 0; i < 20; i++)
+ assertEq(f1(), 32);
+enableSingleStepProfiling();
+assertEq(f1(), 32);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f1,>,<,f1,>,>,<,f1,>,f2,>,<,f1,>,<,f2,>,<,f1,>,f2,>,<,f1,>,>,<,f1,>,<,f1,>,f1,>,>");
+
+
+if (isSimdAvailable() && typeof SIMD !== 'undefined') {
+ // SIMD out-of-bounds exit
+ var buf = new ArrayBuffer(0x10000);
+ var f = asmLink(asmCompile('g','ffi','buf', USE_ASM + 'var f4=g.SIMD.float32x4; var f4l=f4.load; var u8=new g.Uint8Array(buf); function f(i) { i=i|0; return f4l(u8, 0xFFFF + i | 0); } return f'), this, {}, buf);
+ enableSingleStepProfiling();
+ assertThrowsInstanceOf(() => f(4), RangeError);
+ var stacks = disableSingleStepProfiling();
+ // TODO check that expected is actually the correctly expected string, when
+ // SIMD is implemented on ARM.
+ assertStackContainsSeq(stacks, ">,f,>,inline stub,f,>");
+}
+
+
+// Thunks
+setJitCompilerOption("jump-threshold", 0);
+var h = asmLink(asmCompile(USE_ASM + 'function f() {} function g() { f() } function h() { g() } return h'));
+enableSingleStepProfiling();
+h();
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,h,>,g,h,>,f,g,h,>,g,h,>,h,>,>");
+setJitCompilerOption("jump-threshold", -1);
+
+// This takes forever to run.
+// Stack-overflow exit test
+//var limit = -1;
+//var maxct = 0;
+//function ffi(ct) { if (ct == limit) { enableSingleStepProfiling(); print("enabled"); } maxct = ct; }
+//var f = asmLink(asmCompile('g', 'ffis',USE_ASM + "var ffi=ffis.ffi; var ct=0; function rec(){ ct=(ct+1)|0; ffi(ct|0); rec() } function f() { ct=0; rec() } return f"), null, {ffi});
+//// First find the stack limit:
+//var caught = false;
+//try { f() } catch (e) { caught = true; assertEq(String(e).indexOf("too much recursion") >= 0, true) }
+//assertEq(caught, true);
+//limit = maxct;
+//print("Setting limit");
+//var caught = false;
+//try { f() } catch (e) { caught = true; print("caught"); assertEq(String(e).indexOf("too much recursion") >= 0, true) }
+//var stacks = disableSingleStepProfiling();
+//assertEq(String(stacks).indexOf("rec") >= 0, true);
diff --git a/js/src/jit-test/tests/asm.js/testRangeAnalysis.js b/js/src/jit-test/tests/asm.js/testRangeAnalysis.js
new file mode 100644
index 000000000..6418bc1b3
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testRangeAnalysis.js
@@ -0,0 +1,15 @@
+// Bug 894781
+function m(stdlib)
+{
+ "use asm";
+ var abs = stdlib.Math.abs;
+ function f(d)
+ {
+ d = +d;
+ return (~~(5.0 - +abs(d)))|0;
+ }
+ return f;
+}
+var f = m(this);
+assertEq(f(0.2), 4);
+assertEq(f(NaN), 0);
diff --git a/js/src/jit-test/tests/asm.js/testSIMD-16x8.js b/js/src/jit-test/tests/asm.js/testSIMD-16x8.js
new file mode 100644
index 000000000..6f017892c
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testSIMD-16x8.js
@@ -0,0 +1,510 @@
+load(libdir + "asm.js");
+load(libdir + "simd.js");
+load(libdir + "asserts.js");
+
+// Set to true to see more JS debugging spew.
+const DEBUG = false;
+
+if (!isSimdAvailable()) {
+ DEBUG && print("won't run tests as simd extensions aren't activated yet");
+ quit(0);
+}
+
+// Tests for 16x8 SIMD types: Int16x8, Uint16x8, Bool16x8.
+
+const I16x8 = 'var i16x8 = glob.SIMD.Int16x8;'
+const I16x8CHK = 'var i16x8chk = i16x8.check;'
+const I16x8EXT = 'var i16x8ext = i16x8.extractLane;'
+const I16x8REP = 'var i16x8rep = i16x8.replaceLane;'
+const I16x8U16x8 = 'var i16x8u16x8 = i16x8.fromUint16x8Bits;'
+
+const U16x8 = 'var u16x8 = glob.SIMD.Uint16x8;'
+const U16x8CHK = 'var u16x8chk = u16x8.check;'
+const U16x8EXT = 'var u16x8ext = u16x8.extractLane;'
+const U16x8REP = 'var u16x8rep = u16x8.replaceLane;'
+const U16x8I16x8 = 'var u16x8i16x8 = u16x8.fromInt16x8Bits;'
+
+const B16x8 = 'var b16x8 = glob.SIMD.Bool16x8;'
+const B16x8CHK = 'var b16x8chk = b16x8.check;'
+const B16x8EXT = 'var b16x8ext = b16x8.extractLane;'
+const B16x8REP = 'var b16x8rep = b16x8.replaceLane;'
+
+const INT16_MAX = 0x7fff
+const INT16_MIN = -0x10000
+const UINT16_MAX = 0xffff
+
+// Linking
+assertEq(asmLink(asmCompile('glob', USE_ASM + I16x8 + "function f() {} return f"), {SIMD:{Int16x8: SIMD.Int16x8}})(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + U16x8 + "function f() {} return f"), {SIMD:{Uint16x8: SIMD.Uint16x8}})(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + B16x8 + "function f() {} return f"), {SIMD:{Bool16x8: SIMD.Bool16x8}})(), undefined);
+
+// Local variable of Int16x8 type.
+assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Int16x8(1,2,3,4,5,6,7,8);} return f");
+assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8;} return f");
+assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8();} return f");
+assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1);} return f");
+assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1,2,3,4);} return f");
+assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1,2,3,4,5,6,7,8.0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1,2,3,4,5,6,7,8,9);} return f");
+assertAsmTypeFail('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1,2,3,4,5,6,7,8|0);} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1,2,3,4,5,6,7,8);} return f"), this)(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + I16x8 + "function f() {var x=i16x8(1,2,3,4,5,6,7," + (INT16_MAX + 1) + ");} return f"), this)(), undefined);
+
+// Local variable of Uint16x8 type.
+assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Uint16x8(1,2,3,4,5,6,7,8);} return f");
+assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8;} return f");
+assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8();} return f");
+assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1);} return f");
+assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1,2,3,4);} return f");
+assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1,2,3,4,5,6,7,8.0);} return f");
+assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1,2,3,4,5,6,7,8,9);} return f");
+assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1,2,3,4,5,6,7,8|0);} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1,2,3,4,5,6,7,8);} return f"), this)(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + U16x8 + "function f() {var x=u16x8(1,2,3,4,5,6,7," + (UINT16_MAX + 1) + ");} return f"), this)(), undefined);
+
+// Local variable of Bool16x8 type.
+assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Bool16x8(1,0,0,0, 0,0,0,0);} return f");
+assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8;} return f");
+assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8();} return f");
+assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8(1);} return f");
+assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8(1,0,0,0);} return f");
+assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8(1,0,0,0, 0,0,0,1.0);} return f");
+assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8(1,0,0,0, 0,0,0,0|0);} return f");
+assertAsmTypeFail('glob', USE_ASM + B16x8 + "function f() {var x=b16x8(1,0,0,0, 0,0,0,0, 1);} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + B16x8 + "function f() {var x=b16x8(1,0,0,0, 0,-1,-2,0);} return f"), this)(), undefined);
+
+// Only signed Int16x8 allowed as return value.
+assertEqVecArr(asmLink(asmCompile('glob', USE_ASM + I16x8 + "function f() {return i16x8(1,2,3,4,5,6,7,8);} return f"), this)(),
+ [1, 2, 3, 4, 5, 6, 7, 8]);
+assertEqVecArr(asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + "function f() {return i16x8chk(i16x8(1,2,3,32771,5,6,7,8));} return f"), this)(),
+ [1, 2, 3, -32765, 5, 6, 7, 8]);
+assertAsmTypeFail('glob', USE_ASM + U16x8 + "function f() {return u16x8(1,2,3,4,5,6,7,8);} return f");
+assertAsmTypeFail('glob', USE_ASM + U16x8 + U16x8CHK + "function f() {return u16x8chk(u16x8(1,2,3,4,5,6,7,8));} return f");
+
+// Test splat.
+function splat(x) {
+ let r = []
+ for (let i = 0; i < 8; i++)
+ r.push(x);
+ return r
+}
+
+splatB = asmLink(asmCompile('glob', USE_ASM + B16x8 +
+ 'var splat = b16x8.splat;' +
+ 'function f(x) { x = x|0; return splat(x); } return f'), this);
+assertEqVecArr(splatB(true), splat(true));
+assertEqVecArr(splatB(false), splat(false));
+
+
+splatB0 = asmLink(asmCompile('glob', USE_ASM + B16x8 +
+ 'var splat = b16x8.splat;' +
+ 'function f() { var x = 0; return splat(x); } return f'), this);
+assertEqVecArr(splatB0(), splat(false));
+splatB1 = asmLink(asmCompile('glob', USE_ASM + B16x8 +
+ 'var splat = b16x8.splat;' +
+ 'function f() { var x = 1; return splat(x); } return f'), this);
+assertEqVecArr(splatB1(), splat(true));
+
+splatI = asmLink(asmCompile('glob', USE_ASM + I16x8 +
+ 'var splat = i16x8.splat;' +
+ 'function f(x) { x = x|0; return splat(x); } return f'), this);
+for (let x of [0, 1, -1, 0x12345, 0x1234, -1000, -1000000]) {
+ assertEqVecArr(splatI(x), splat(x << 16 >> 16));
+}
+
+splatIc = asmLink(asmCompile('glob', USE_ASM + I16x8 +
+ 'var splat = i16x8.splat;' +
+ 'function f() { var x = 100; return splat(x); } return f'), this);
+assertEqVecArr(splatIc(), splat(100))
+
+splatU = asmLink(asmCompile('glob', USE_ASM + U16x8 + I16x8 + I16x8U16x8 +
+ 'var splat = u16x8.splat;' +
+ 'function f(x) { x = x|0; return i16x8u16x8(splat(x)); } return f'), this);
+for (let x of [0, 1, -1, 0x12345, 0x1234, -1000, -1000000]) {
+ assertEqVecArr(SIMD.Uint16x8.fromInt16x8Bits(splatI(x)), splat(x << 16 >>> 16));
+}
+
+splatUc = asmLink(asmCompile('glob', USE_ASM + U16x8 + I16x8 + I16x8U16x8 +
+ 'var splat = u16x8.splat;' +
+ 'function f() { var x = 200; return i16x8u16x8(splat(x)); } return f'), this);
+assertEqVecArr(SIMD.Uint16x8.fromInt16x8Bits(splatUc()), splat(200))
+
+
+// Test extractLane.
+//
+// The lane index must be a literal int, and we generate different code for
+// different lanes.
+function extractI(a, i) {
+ return asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8EXT +
+ `function f() {var x=i16x8(${a.join(',')}); return i16x8ext(x, ${i})|0; } return f`), this)();
+}
+a = [-1,2,-3,4,-5,6,-7,-8];
+for (var i = 0; i < 8; i++)
+ assertEq(extractI(a, i), a[i]);
+a = a.map(x => -x);
+for (var i = 0; i < 8; i++)
+ assertEq(extractI(a, i), a[i]);
+
+function extractU(a, i) {
+ return asmLink(asmCompile('glob', USE_ASM + U16x8 + U16x8EXT +
+ `function f() {var x=u16x8(${a.join(',')}); return u16x8ext(x, ${i})|0; } return f`), this)();
+}
+a = [1,255,12,13,14,150,200,3];
+for (var i = 0; i < 8; i++)
+ assertEq(extractU(a, i), a[i]);
+a = a.map(x => UINT16_MAX-x);
+for (var i = 0; i < 8; i++)
+ assertEq(extractU(a, i), a[i]);
+
+function extractB(a, i) {
+ return asmLink(asmCompile('glob', USE_ASM + B16x8 + B16x8EXT +
+ `function f() {var x=b16x8(${a.join(',')}); return b16x8ext(x, ${i})|0; } return f`), this)();
+}
+a = [1,1,0,1, 1,0,0,0];
+for (var i = 0; i < 8; i++)
+ assertEq(extractB(a, i), a[i]);
+a = a.map(x => 1-x);
+for (var i = 0; i < 8; i++)
+ assertEq(extractB(a, i), a[i]);
+
+// Test replaceLane.
+function replaceI(a, i) {
+ return asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8REP +
+ `function f(v) {v=v|0; var x=i16x8(${a.join(',')}); return i16x8rep(x,${i},v); } return f`), this);
+}
+a = [-1,2,-3,4,-5,6,-7,-9];
+for (var i = 0; i < 8; i++) {
+ var f = replaceI(a, i);
+ var b = a.slice(0);
+ b[i] = -20;
+ assertEqVecArr(f(-20), b);
+}
+
+function replaceU(a, i) {
+ return asmLink(asmCompile('glob', USE_ASM + U16x8 + U16x8REP + I16x8 + I16x8U16x8 +
+ `function f(v) {v=v|0; var x=u16x8(${a.join(',')}); return i16x8u16x8(u16x8rep(x,${i},v)); } return f`), this);
+}
+a = [65000-1,2,65000-3,4,65000-5,6,65000-7,65000-9];
+for (var i = 0; i < 8; i++) {
+ var rawf = replaceU(a, i);
+ var f = x => SIMD.Uint16x8.fromInt16x8Bits(rawf(x))
+ var b = a.slice(0);
+ b[i] = 1000;
+ assertEqVecArr(f(1000), b);
+}
+
+function replaceB(a, i) {
+ return asmLink(asmCompile('glob', USE_ASM + B16x8 + B16x8REP +
+ `function f(v) {v=v|0; var x=b16x8(${a.join(',')}); return b16x8rep(x,${i},v); } return f`), this);
+}
+a = [1,1,0,1,1,0,0,0];
+for (var i = 0; i < 8; i++) {
+ var f = replaceB(a, i);
+ var b = a.slice(0);
+ let v = 1 - a[i];
+ b[i] = v;
+ assertEqVecArr(f(v), b.map(x => !!x));
+}
+
+
+// Test select.
+selectI = asmLink(asmCompile('glob', USE_ASM + I16x8 + B16x8 + B16x8CHK +
+ 'var select = i16x8.select;' +
+ 'var a = i16x8(-1,2,-3,4,-5, 6,-7, 8);' +
+ 'var b = i16x8( 5,6, 7,8, 9,10,11,12);' +
+ 'function f(x) { x = b16x8chk(x); return select(x, a, b); } return f'), this);
+assertEqVecArr(selectI(SIMD.Bool16x8( 0,0, 1,0, 1,1, 1, 0)),
+ [ 5,6,-3,8,-5,6,-7,12]);
+
+selectU = asmLink(asmCompile('glob', USE_ASM + I16x8 + B16x8 + B16x8CHK + U16x8 + I16x8U16x8 + U16x8I16x8 +
+ 'var select = u16x8.select;' +
+ 'var a = i16x8(-1,2,-3,4,-5, 6,-7, 8);' +
+ 'var b = i16x8( 5,6, 7,8, 9,10,11,12);' +
+ 'function f(x) { x = b16x8chk(x); return i16x8u16x8(select(x, u16x8i16x8(a), u16x8i16x8(b))); } return f'), this);
+assertEqVecArr(selectU(SIMD.Bool16x8( 0,0, 1,0, 1,1, 1, 0)),
+ [ 5,6,-3,8,-5,6,-7,12]);
+
+// Test swizzle.
+function swizzle(vec, lanes) {
+ let r = [];
+ for (let i = 0; i < 8; i++)
+ r.push(vec[lanes[i]]);
+ return r;
+}
+
+function swizzleI(lanes) {
+ let asm = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK +
+ 'var swz = i16x8.swizzle;' +
+ `function f(a) { a = i16x8chk(a); return swz(a, ${lanes.join()}); } return f`), this);
+ let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >> 16);
+ let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >> 16);
+ let v1 = SIMD.Int16x8(...a1);
+ let v2 = SIMD.Int16x8(...a2);
+ assertEqVecArr(asm(v1), swizzle(a1, lanes));
+ assertEqVecArr(asm(v2), swizzle(a2, lanes));
+}
+
+swizzleI([3, 4, 7, 1, 4, 3, 1, 2]);
+swizzleI([0, 0, 0, 0, 0, 0, 0, 0]);
+swizzleI([7, 7, 7, 7, 7, 7, 7, 7]);
+
+function swizzleU(lanes) {
+ let asm = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + U16x8 + U16x8I16x8 + I16x8U16x8 +
+ 'var swz = u16x8.swizzle;' +
+ `function f(a) { a = i16x8chk(a); return i16x8u16x8(swz(u16x8i16x8(a), ${lanes.join()})); } return f`), this);
+ let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >> 16);
+ let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >> 16);
+ let v1 = SIMD.Int16x8(...a1);
+ let v2 = SIMD.Int16x8(...a2);
+ assertEqVecArr(asm(v1), swizzle(a1, lanes));
+ assertEqVecArr(asm(v2), swizzle(a2, lanes));
+}
+
+swizzleU([3, 4, 7, 1, 4, 3, 1, 2]);
+swizzleU([0, 0, 0, 0, 0, 0, 0, 0]);
+swizzleU([7, 7, 7, 7, 7, 7, 7, 7]);
+
+// Out-of-range lane indexes.
+assertAsmTypeFail('glob', USE_ASM + I16x8 + 'var swz = i16x8.swizzle; ' +
+ 'function f() { var x=i16x8(0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7,8); } return f');
+assertAsmTypeFail('glob', USE_ASM + U16x8 + 'var swz = u16x8.swizzle; ' +
+ 'function f() { var x=u16x8(0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7,8); } return f');
+// Missing lane indexes.
+assertAsmTypeFail('glob', USE_ASM + I16x8 + 'var swz = i16x8.swizzle; ' +
+ 'function f() { var x=i16x8(0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7); } return f');
+assertAsmTypeFail('glob', USE_ASM + U16x8 + 'var swz = u16x8.swizzle; ' +
+ 'function f() { var x=u16x8(0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7); } return f');
+
+
+// Test shuffle.
+function shuffle(vec1, vec2, lanes) {
+ let r = [];
+ let vec = vec1.concat(vec2)
+ for (let i = 0; i < 8; i++)
+ r.push(vec[lanes[i]]);
+ return r;
+}
+
+function shuffleI(lanes) {
+ let asm = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK +
+ 'var shuf = i16x8.shuffle;' +
+ `function f(a1, a2) { a1 = i16x8chk(a1); a2 = i16x8chk(a2); return shuf(a1, a2, ${lanes.join()}); } return f`), this);
+ let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >> 16);
+ let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >> 16);
+ let v1 = SIMD.Int16x8(...a1);
+ let v2 = SIMD.Int16x8(...a2);
+ assertEqVecArr(asm(v1, v2), shuffle(a1, a2, lanes));
+}
+
+function shuffleU(lanes) {
+ let asm = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + U16x8 + U16x8I16x8 + I16x8U16x8 +
+ 'var shuf = u16x8.shuffle;' +
+ 'function f(a1, a2) { a1 = i16x8chk(a1); a2 = i16x8chk(a2); ' +
+ `return i16x8u16x8(shuf(u16x8i16x8(a1), u16x8i16x8(a2), ${lanes.join()})); } return f`), this);
+ let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >> 16);
+ let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >> 16);
+ let v1 = SIMD.Int16x8(...a1);
+ let v2 = SIMD.Int16x8(...a2);
+ assertEqVecArr(asm(v1, v2), shuffle(a1, a2, lanes));
+}
+
+shuffleI([0, 0, 0, 0, 0, 0, 0, 0])
+shuffleI([15, 15, 15, 15, 15, 15, 15, 15])
+shuffleI([6, 2, 0, 14, 6, 10, 11, 1])
+
+shuffleU([7, 7, 7, 7, 7, 7, 7, 7])
+shuffleU([8, 15, 15, 15, 15, 15, 15, 15])
+shuffleU([6, 2, 0, 14, 6, 10, 11, 1])
+
+// Test unary operators.
+function unaryI(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK +
+ `var fut = i16x8.${opname};` +
+ 'function f(v) { v = i16x8chk(v); return fut(v); } return f'), this);
+ let a = [65000-1,2,65000-3,4,65000-5,6,65000-7,65000-9];
+ let v = SIMD.Int16x8(...a);
+ assertEqVecArr(simdfunc(v), a.map(lanefunc));
+}
+
+function unaryU(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + U16x8 + I16x8 + I16x8CHK + U16x8I16x8 + I16x8U16x8 +
+ `var fut = u16x8.${opname};` +
+ 'function f(v) { v = i16x8chk(v); return i16x8u16x8(fut(u16x8i16x8(v))); } return f'), this);
+ let a = [65000-1,2,65000-3,4,65000-5,6,65000-7,65000-9];
+ let v = SIMD.Int16x8(...a);
+ assertEqVecArr(SIMD.Uint16x8.fromInt16x8Bits(simdfunc(v)), a.map(lanefunc));
+}
+
+function unaryB(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + B16x8 + B16x8CHK +
+ `var fut = b16x8.${opname};` +
+ 'function f(v) { v = b16x8chk(v); return fut(v); } return f'), this);
+ let a = [1,1,0,1,1,0,0,0];
+ let v = SIMD.Bool16x8(...a);
+ assertEqVecArr(simdfunc(v), a.map(lanefunc));
+}
+
+unaryI('not', x => ~x << 16 >> 16);
+unaryU('not', x => ~x << 16 >>> 16);
+unaryB('not', x => !x);
+unaryI('neg', x => -x << 16 >> 16);
+unaryU('neg', x => -x << 16 >>> 16);
+
+
+// Test binary operators.
+function zipmap(a1, a2, f) {
+ assertEq(a1.length, a2.length);
+ let r = [];
+ for (var i = 0; i < a1.length; i++)
+ r.push(f(a1[i], a2[i]));
+ return r
+}
+
+function binaryI(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK +
+ `var fut = i16x8.${opname};` +
+ 'function f(v1, v2) { v1 = i16x8chk(v1); v2 = i16x8chk(v2); return fut(v1, v2); } return f'), this);
+ let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >> 16);
+ let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >> 16);
+ let ref = zipmap(a1, a2, lanefunc);
+ let v1 = SIMD.Int16x8(...a1);
+ let v2 = SIMD.Int16x8(...a2);
+ assertEqVecArr(simdfunc(v1, v2), ref);
+}
+
+function binaryU(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + U16x8 + I16x8 + I16x8CHK + U16x8I16x8 + I16x8U16x8 +
+ `var fut = u16x8.${opname};` +
+ 'function f(v1, v2) { v1 = i16x8chk(v1); v2 = i16x8chk(v2); return i16x8u16x8(fut(u16x8i16x8(v1), u16x8i16x8(v2))); } return f'), this);
+ let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >>> 16);
+ let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >>> 16);
+ let ref = zipmap(a1, a2, lanefunc);
+ let v1 = SIMD.Int16x8(...a1);
+ let v2 = SIMD.Int16x8(...a2);
+ let res = SIMD.Uint16x8.fromInt16x8Bits(simdfunc(v1, v2));
+ assertEqVecArr(res, ref);
+}
+
+function binaryB(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + B16x8 + B16x8CHK +
+ `var fut = b16x8.${opname};` +
+ 'function f(v1, v2) { v1 = b16x8chk(v1); v2 = b16x8chk(v2); return fut(v1, v2); } return f'), this);
+ let a = [1,1,0,1,1,0,0,0];
+ let v = SIMD.Bool16x8(...a);
+ assertEqVecArr(simdfunc(v), a.map(lanefunc));
+}
+
+binaryI('add', (x, y) => (x + y) << 16 >> 16);
+binaryI('sub', (x, y) => (x - y) << 16 >> 16);
+binaryI('mul', (x, y) => (x * y) << 16 >> 16);
+binaryU('add', (x, y) => (x + y) << 16 >>> 16);
+binaryU('sub', (x, y) => (x - y) << 16 >>> 16);
+binaryU('mul', (x, y) => (x * y) << 16 >>> 16);
+
+binaryI('and', (x, y) => (x & y) << 16 >> 16);
+binaryI('or', (x, y) => (x | y) << 16 >> 16);
+binaryI('xor', (x, y) => (x ^ y) << 16 >> 16);
+binaryU('and', (x, y) => (x & y) << 16 >>> 16);
+binaryU('or', (x, y) => (x | y) << 16 >>> 16);
+binaryU('xor', (x, y) => (x ^ y) << 16 >>> 16);
+
+function sat(x, lo, hi) {
+ if (x < lo) return lo;
+ if (x > hi) return hi;
+ return x
+}
+function isat(x) { return sat(x, -32768, 32767); }
+function usat(x) { return sat(x, 0, 0xffff); }
+
+binaryI('addSaturate', (x, y) => isat(x + y))
+binaryI('subSaturate', (x, y) => isat(x - y))
+binaryU('addSaturate', (x, y) => usat(x + y))
+binaryU('subSaturate', (x, y) => usat(x - y))
+
+
+// Test shift operators.
+function zip1map(a, s, f) {
+ return a.map(x => f(x, s));
+}
+
+function shiftI(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK +
+ `var fut = i16x8.${opname};` +
+ 'function f(v, s) { v = i16x8chk(v); s = s|0; return fut(v, s); } return f'), this);
+ let a = [-1,2,-3,0x80,0x7f,6,0x8000,0x7fff];
+ let v = SIMD.Int16x8(...a);
+ for (let s of [0, 1, 2, 6, 7, 8, 9, 10, 16, 255, -1, -8, -7, -1000]) {
+ let ref = zip1map(a, s, lanefunc);
+ // 1. Test dynamic shift amount.
+ assertEqVecArr(simdfunc(v, s), ref);
+
+ // 2. Test constant shift amount.
+ let cstf = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK +
+ `var fut = i16x8.${opname};` +
+ `function f(v) { v = i16x8chk(v); return fut(v, ${s}); } return f`), this);
+ assertEqVecArr(cstf(v, s), ref);
+ }
+}
+
+function shiftU(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + U16x8 + I16x8 + I16x8CHK + U16x8I16x8 + I16x8U16x8 +
+ `var fut = u16x8.${opname};` +
+ 'function f(v, s) { v = i16x8chk(v); s = s|0; return i16x8u16x8(fut(u16x8i16x8(v), s)); } return f'), this);
+ let a = [-1,2,-3,0x80,0x7f,6,0x8000,0x7fff];
+ let v = SIMD.Int16x8(...a);
+ for (let s of [0, 1, 2, 6, 7, 8, 9, 10, 16, 255, -1, -8, -7, -1000]) {
+ let ref = zip1map(a, s, lanefunc);
+ // 1. Test dynamic shift amount.
+ assertEqVecArr(SIMD.Uint16x8.fromInt16x8Bits(simdfunc(v, s)), ref);
+
+ // 2. Test constant shift amount.
+ let cstf = asmLink(asmCompile('glob', USE_ASM + U16x8 + I16x8 + I16x8CHK + U16x8I16x8 + I16x8U16x8 +
+ `var fut = u16x8.${opname};` +
+ `function f(v) { v = i16x8chk(v); return i16x8u16x8(fut(u16x8i16x8(v), ${s})); } return f`), this);
+ assertEqVecArr(SIMD.Uint16x8.fromInt16x8Bits(cstf(v, s)), ref);
+ }
+}
+
+shiftI('shiftLeftByScalar', (x,s) => (x << (s & 15)) << 16 >> 16);
+shiftU('shiftLeftByScalar', (x,s) => (x << (s & 15)) << 16 >>> 16);
+shiftI('shiftRightByScalar', (x,s) => ((x << 16 >> 16) >> (s & 15)) << 16 >> 16);
+shiftU('shiftRightByScalar', (x,s) => ((x << 16 >>> 16) >>> (s & 15)) << 16 >>> 16);
+
+
+// Comparisons.
+function compareI(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK +
+ `var fut = i16x8.${opname};` +
+ 'function f(v1, v2) { v1 = i16x8chk(v1); v2 = i16x8chk(v2); return fut(v1, v2); } return f'), this);
+ let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >> 16);
+ let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >> 16);
+ let ref = zipmap(a1, a2, lanefunc);
+ let v1 = SIMD.Int16x8(...a1);
+ let v2 = SIMD.Int16x8(...a2);
+ assertEqVecArr(simdfunc(v1, v2), ref);
+}
+
+function compareU(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + I16x8 + I16x8CHK + U16x8 + U16x8I16x8 +
+ `var fut = u16x8.${opname};` +
+ 'function f(v1, v2) { v1 = i16x8chk(v1); v2 = i16x8chk(v2); return fut(u16x8i16x8(v1), u16x8i16x8(v2)); } return f'), this);
+ let a1 = [ -1,2, -3,0x8000,0x7f,6,-7, 8].map(x => x << 16 >>> 16);
+ let a2 = [0x8000,2,0x8000,0x7fff, 0,0, 8,-9].map(x => x << 16 >>> 16);
+ let ref = zipmap(a1, a2, lanefunc);
+ let v1 = SIMD.Int16x8(...a1);
+ let v2 = SIMD.Int16x8(...a2);
+ assertEqVecArr(simdfunc(v1, v2), ref);
+}
+
+compareI("equal", (x,y) => x == y);
+compareU("equal", (x,y) => x == y);
+compareI("notEqual", (x,y) => x != y);
+compareU("notEqual", (x,y) => x != y);
+compareI("lessThan", (x,y) => x < y);
+compareU("lessThan", (x,y) => x < y);
+compareI("lessThanOrEqual", (x,y) => x <= y);
+compareU("lessThanOrEqual", (x,y) => x <= y);
+compareI("greaterThan", (x,y) => x > y);
+compareU("greaterThan", (x,y) => x > y);
+compareI("greaterThanOrEqual", (x,y) => x >= y);
+compareU("greaterThanOrEqual", (x,y) => x >= y);
diff --git a/js/src/jit-test/tests/asm.js/testSIMD-8x16.js b/js/src/jit-test/tests/asm.js/testSIMD-8x16.js
new file mode 100644
index 000000000..160da82a8
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testSIMD-8x16.js
@@ -0,0 +1,524 @@
+load(libdir + "asm.js");
+load(libdir + "simd.js");
+load(libdir + "asserts.js");
+
+// Set to true to see more JS debugging spew.
+const DEBUG = false;
+
+if (!isSimdAvailable()) {
+ DEBUG && print("won't run tests as simd extensions aren't activated yet");
+ quit(0);
+}
+
+// Tests for 8x16 SIMD types: Int8x16, Uint8x16, Bool8x16.
+
+const I8x16 = 'var i8x16 = glob.SIMD.Int8x16;'
+const I8x16CHK = 'var i8x16chk = i8x16.check;'
+const I8x16EXT = 'var i8x16ext = i8x16.extractLane;'
+const I8x16REP = 'var i8x16rep = i8x16.replaceLane;'
+const I8x16U8x16 = 'var i8x16u8x16 = i8x16.fromUint8x16Bits;'
+
+const U8x16 = 'var u8x16 = glob.SIMD.Uint8x16;'
+const U8x16CHK = 'var u8x16chk = u8x16.check;'
+const U8x16EXT = 'var u8x16ext = u8x16.extractLane;'
+const U8x16REP = 'var u8x16rep = u8x16.replaceLane;'
+const U8x16I8x16 = 'var u8x16i8x16 = u8x16.fromInt8x16Bits;'
+
+const B8x16 = 'var b8x16 = glob.SIMD.Bool8x16;'
+const B8x16CHK = 'var b8x16chk = b8x16.check;'
+const B8x16EXT = 'var b8x16ext = b8x16.extractLane;'
+const B8x16REP = 'var b8x16rep = b8x16.replaceLane;'
+
+const INT8_MAX = 127
+const INT8_MIN = -128
+const UINT8_MAX = 255
+
+// Linking
+assertEq(asmLink(asmCompile('glob', USE_ASM + I8x16 + "function f() {} return f"), {SIMD:{Int8x16: SIMD.Int8x16}})(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + U8x16 + "function f() {} return f"), {SIMD:{Uint8x16: SIMD.Uint8x16}})(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + B8x16 + "function f() {} return f"), {SIMD:{Bool8x16: SIMD.Bool8x16}})(), undefined);
+
+// Local variable of Int8x16 type.
+assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Int8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);} return f");
+assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16;} return f");
+assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16();} return f");
+assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1);} return f");
+assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1,2,3,4);} return f");
+assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16.0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);} return f");
+assertAsmTypeFail('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16|0);} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);} return f"), this)(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + I8x16 + "function f() {var x=i8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15," + (INT8_MAX + 1) + ");} return f"), this)(), undefined);
+
+// Local variable of Uint8x16 type.
+assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Uint8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);} return f");
+assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16;} return f");
+assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16();} return f");
+assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1);} return f");
+assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1,2,3,4);} return f");
+assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16.0);} return f");
+assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);} return f");
+assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16|0);} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);} return f"), this)(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + U8x16 + "function f() {var x=u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15," + (UINT8_MAX + 1) + ");} return f"), this)(), undefined);
+
+// Local variable of Bool8x16 type.
+assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Bool8x16(1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1);} return f");
+assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16;} return f");
+assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16();} return f");
+assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16(1);} return f");
+assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16(1,0,0,0);} return f");
+assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16(1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1.0);} return f");
+assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16(1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1|0);} return f");
+assertAsmTypeFail('glob', USE_ASM + B8x16 + "function f() {var x=b8x16(1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1);} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + B8x16 + "function f() {var x=b8x16(1,0,0,0,0,0,0,0,0,1,-1,2,-2,1,1,1);} return f"), this)(), undefined);
+
+// Only signed Int8x16 allowed as return value.
+assertEqVecArr(asmLink(asmCompile('glob', USE_ASM + I8x16 + "function f() {return i8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);} return f"), this)(),
+ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+assertEqVecArr(asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + "function f() {return i8x16chk(i8x16(1,2,3,132,5,6,7,8,9,10,11,12,13,14,15,16));} return f"), this)(),
+ [1, 2, 3, -124, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+assertAsmTypeFail('glob', USE_ASM + U8x16 + "function f() {return u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);} return f");
+assertAsmTypeFail('glob', USE_ASM + U8x16 + U8x16CHK + "function f() {return u8x16chk(u8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));} return f");
+
+// Test splat.
+function splat(x) {
+ let r = []
+ for (let i = 0; i < 16; i++)
+ r.push(x);
+ return r
+}
+
+splatB = asmLink(asmCompile('glob', USE_ASM + B8x16 +
+ 'var splat = b8x16.splat;' +
+ 'function f(x) { x = x|0; return splat(x); } return f'), this);
+assertEqVecArr(splatB(true), splat(true));
+assertEqVecArr(splatB(false), splat(false));
+
+
+splatB0 = asmLink(asmCompile('glob', USE_ASM + B8x16 +
+ 'var splat = b8x16.splat;' +
+ 'function f() { var x = 0; return splat(x); } return f'), this);
+assertEqVecArr(splatB0(), splat(false));
+splatB1 = asmLink(asmCompile('glob', USE_ASM + B8x16 +
+ 'var splat = b8x16.splat;' +
+ 'function f() { var x = 1; return splat(x); } return f'), this);
+assertEqVecArr(splatB1(), splat(true));
+
+splatI = asmLink(asmCompile('glob', USE_ASM + I8x16 +
+ 'var splat = i8x16.splat;' +
+ 'function f(x) { x = x|0; return splat(x); } return f'), this);
+for (let x of [0, 1, -1, 0x1234, 0x12, 1000, -1000000]) {
+ assertEqVecArr(splatI(x), splat(x << 24 >> 24));
+}
+
+splatIc = asmLink(asmCompile('glob', USE_ASM + I8x16 +
+ 'var splat = i8x16.splat;' +
+ 'function f() { var x = 100; return splat(x); } return f'), this);
+assertEqVecArr(splatIc(), splat(100))
+
+splatU = asmLink(asmCompile('glob', USE_ASM + U8x16 + I8x16 + I8x16U8x16 +
+ 'var splat = u8x16.splat;' +
+ 'function f(x) { x = x|0; return i8x16u8x16(splat(x)); } return f'), this);
+for (let x of [0, 1, -1, 0x1234, 0x12, 1000, -1000000]) {
+ assertEqVecArr(SIMD.Uint8x16.fromInt8x16Bits(splatI(x)), splat(x << 24 >>> 24));
+}
+
+splatUc = asmLink(asmCompile('glob', USE_ASM + U8x16 + I8x16 + I8x16U8x16 +
+ 'var splat = u8x16.splat;' +
+ 'function f() { var x = 200; return i8x16u8x16(splat(x)); } return f'), this);
+assertEqVecArr(SIMD.Uint8x16.fromInt8x16Bits(splatUc()), splat(200))
+
+
+// Test extractLane.
+//
+// The lane index must be a literal int, and we generate different code for
+// different lanes.
+function extractI(a, i) {
+ return asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16EXT +
+ `function f() {var x=i8x16(${a.join(',')}); return i8x16ext(x, ${i})|0; } return f`), this)();
+}
+a = [-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,-14,-15,-16];
+for (var i = 0; i < 16; i++)
+ assertEq(extractI(a, i), a[i]);
+a = a.map(x => -x);
+for (var i = 0; i < 16; i++)
+ assertEq(extractI(a, i), a[i]);
+
+function extractU(a, i) {
+ return asmLink(asmCompile('glob', USE_ASM + U8x16 + U8x16EXT +
+ `function f() {var x=u8x16(${a.join(',')}); return u8x16ext(x, ${i})|0; } return f`), this)();
+}
+a = [1,255,12,13,14,150,200,3,4,5,6,7,8,9,10,16];
+for (var i = 0; i < 16; i++)
+ assertEq(extractU(a, i), a[i]);
+a = a.map(x => 255-x);
+for (var i = 0; i < 16; i++)
+ assertEq(extractU(a, i), a[i]);
+
+function extractB(a, i) {
+ return asmLink(asmCompile('glob', USE_ASM + B8x16 + B8x16EXT +
+ `function f() {var x=b8x16(${a.join(',')}); return b8x16ext(x, ${i})|0; } return f`), this)();
+}
+a = [1,1,0,1,1,0,0,0,1,1,1,1,0,0,0,1];
+for (var i = 0; i < 16; i++)
+ assertEq(extractB(a, i), a[i]);
+a = a.map(x => 1-x);
+for (var i = 0; i < 16; i++)
+ assertEq(extractB(a, i), a[i]);
+
+// Test replaceLane.
+function replaceI(a, i) {
+ return asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16REP +
+ `function f(v) {v=v|0; var x=i8x16(${a.join(',')}); return i8x16rep(x,${i},v); } return f`), this);
+}
+a = [-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,-14,-15,-16];
+for (var i = 0; i < 16; i++) {
+ var f = replaceI(a, i);
+ var b = a.slice(0);
+ b[i] = -20;
+ assertEqVecArr(f(-20), b);
+}
+
+function replaceU(a, i) {
+ return asmLink(asmCompile('glob', USE_ASM + U8x16 + U8x16REP + I8x16 + I8x16U8x16 +
+ `function f(v) {v=v|0; var x=u8x16(${a.join(',')}); x=u8x16rep(x,${i},v); return i8x16u8x16(x); } return f`), this);
+}
+a = [256-1,2,256-3,4,256-5,6,256-7,8,256-9,10,256-11,12,256-13,256-14,256-15,256-16];
+for (var i = 0; i < 16; i++) {
+ // Result returned as Int8x16, convert back.
+ var rawf = replaceU(a, i);
+ var f = x => SIMD.Uint8x16.fromInt8x16Bits(rawf(x));
+ var b = a.slice(0);
+ b[i] = 100;
+ assertEqVecArr(f(100), b);
+}
+
+function replaceB(a, i) {
+ return asmLink(asmCompile('glob', USE_ASM + B8x16 + B8x16REP +
+ `function f(v) {v=v|0; var x=b8x16(${a.join(',')}); return b8x16rep(x,${i},v); } return f`), this);
+}
+a = [1,1,0,1,1,0,0,0,1,1,1,1,0,0,0,1];
+for (var i = 0; i < 16; i++) {
+ var f = replaceB(a, i);
+ var b = a.slice(0);
+ v = 1 - a[i];
+ b[i] = v;
+ assertEqVecArr(f(v), b.map(x => !!x));
+}
+
+
+// Test select.
+selectI = asmLink(asmCompile('glob', USE_ASM + I8x16 + B8x16 + B8x16CHK +
+ 'var select = i8x16.select;' +
+ 'var a = i8x16(-1,2,-3,4,-5, 6,-7, 8,-9,10,-11,12,-13,-14,-15,-16);' +
+ 'var b = i8x16( 5,6, 7,8, 9,10,11,12,13,14, 15,16,-77, 45, 32, 0);' +
+ 'function f(x) { x = b8x16chk(x); return select(x, a, b); } return f'), this);
+assertEqVecArr(selectI(SIMD.Bool8x16( 0,0, 1,0, 1,1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1)),
+ [ 5,6,-3,8,-5,6,-7,12,-9,10,15,16,-13,-14,32,-16]);
+
+selectU = asmLink(asmCompile('glob', USE_ASM + I8x16 + B8x16 + B8x16CHK + U8x16 + I8x16U8x16 + U8x16I8x16 +
+ 'var select = u8x16.select;' +
+ 'var a = i8x16(-1,2,-3,4,-5, 6,-7, 8,-9,10,-11,12,-13,-14,-15,-16);' +
+ 'var b = i8x16( 5,6, 7,8, 9,10,11,12,13,14, 15,16,-77, 45, 32, 0);' +
+ 'function f(x) { x = b8x16chk(x); return i8x16u8x16(select(x, u8x16i8x16(a), u8x16i8x16(b))); } return f'), this);
+assertEqVecArr(selectU(SIMD.Bool8x16( 0,0, 1,0, 1,1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1)),
+ [ 5,6,-3,8,-5,6,-7,12,-9,10,15,16,-13,-14,32,-16]);
+
+
+// Test swizzle.
+function swizzle(vec, lanes) {
+ let r = [];
+ for (let i = 0; i < 16; i++)
+ r.push(vec[lanes[i]]);
+ return r;
+}
+
+function swizzleI(lanes) {
+ let asm = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK +
+ 'var swz = i8x16.swizzle;' +
+ `function f(a) { a = i8x16chk(a); return swz(a, ${lanes.join()}); } return f`), this);
+ let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16];
+ let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1];
+ let v1 = SIMD.Int8x16(...a1);
+ let v2 = SIMD.Int8x16(...a2);
+ assertEqVecArr(asm(v1), swizzle(a1, lanes));
+ assertEqVecArr(asm(v2), swizzle(a2, lanes));
+}
+
+swizzleI([10, 1, 7, 5, 1, 2, 6, 8, 5, 13, 0, 6, 2, 8, 0, 9]);
+swizzleI([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+swizzleI([15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15]);
+
+function swizzleU(lanes) {
+ let asm = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + U8x16 + U8x16I8x16 + I8x16U8x16 +
+ 'var swz = u8x16.swizzle;' +
+ `function f(a) { a = i8x16chk(a); return i8x16u8x16(swz(u8x16i8x16(a), ${lanes.join()})); } return f`), this);
+ let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16];
+ let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1];
+ let v1 = SIMD.Int8x16(...a1);
+ let v2 = SIMD.Int8x16(...a2);
+ assertEqVecArr(asm(v1), swizzle(a1, lanes));
+ assertEqVecArr(asm(v2), swizzle(a2, lanes));
+}
+
+swizzleU([10, 1, 7, 5, 1, 2, 6, 8, 5, 13, 0, 6, 2, 8, 0, 9]);
+swizzleU([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+swizzleU([15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15]);
+
+// Out-of-range lane indexes.
+assertAsmTypeFail('glob', USE_ASM + I8x16 + 'var swz = i8x16.swizzle; ' +
+ 'function f() { var x=i8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16); } return f');
+assertAsmTypeFail('glob', USE_ASM + U8x16 + 'var swz = u8x16.swizzle; ' +
+ 'function f() { var x=u8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16); } return f');
+// Missing lane indexes.
+assertAsmTypeFail('glob', USE_ASM + I8x16 + 'var swz = i8x16.swizzle; ' +
+ 'function f() { var x=i8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); } return f');
+assertAsmTypeFail('glob', USE_ASM + U8x16 + 'var swz = u8x16.swizzle; ' +
+ 'function f() { var x=u8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); swz(x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); } return f');
+
+
+// Test shuffle.
+function shuffle(vec1, vec2, lanes) {
+ let r = [];
+ let vec = vec1.concat(vec2);
+ for (let i = 0; i < 16; i++)
+ r.push(vec[lanes[i]]);
+ return r;
+}
+
+function shuffleI(lanes) {
+ let asm = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK +
+ 'var shuf = i8x16.shuffle;' +
+ `function f(a1, a2) { a1 = i8x16chk(a1); a2 = i8x16chk(a2); return shuf(a1, a2, ${lanes.join()}); } return f`), this);
+ let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16];
+ let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1];
+ let v1 = SIMD.Int8x16(...a1);
+ let v2 = SIMD.Int8x16(...a2);
+ assertEqVecArr(asm(v1, v2), shuffle(a1, a2, lanes));
+}
+
+shuffleI([31, 9, 5, 4, 29, 12, 19, 10, 16, 22, 10, 9, 6, 18, 9, 8]);
+shuffleI([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+shuffleI([31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31]);
+
+function shuffleU(lanes) {
+ let asm = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + U8x16 + U8x16I8x16 + I8x16U8x16 +
+ 'var shuf = u8x16.shuffle;' +
+ 'function f(a1, a2) { a1 = i8x16chk(a1); a2 = i8x16chk(a2); ' +
+ `return i8x16u8x16(shuf(u8x16i8x16(a1), u8x16i8x16(a2), ${lanes.join()})); } return f`), this);
+ let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16];
+ let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1];
+ let v1 = SIMD.Int8x16(...a1);
+ let v2 = SIMD.Int8x16(...a2);
+ assertEqVecArr(asm(v1, v2), shuffle(a1, a2, lanes));
+}
+
+shuffleU([31, 9, 5, 4, 29, 12, 19, 10, 16, 22, 10, 9, 6, 18, 9, 8]);
+shuffleU([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+shuffleU([31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31]);
+
+
+// Out-of-range lane indexes.
+assertAsmTypeFail('glob', USE_ASM + I8x16 + 'var shuf = i8x16.shuffle; ' +
+ 'function f() { var x=i8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); shuf(x,x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,32); } return f');
+assertAsmTypeFail('glob', USE_ASM + U8x16 + 'var shuf = u8x16.shuffle; ' +
+ 'function f() { var x=u8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); shuf(x,x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,32); } return f');
+// Missing lane indexes.
+assertAsmTypeFail('glob', USE_ASM + I8x16 + 'var shuf = i8x16.shuffle; ' +
+ 'function f() { var x=i8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); shuf(x,x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); } return f');
+assertAsmTypeFail('glob', USE_ASM + U8x16 + 'var shuf = u8x16.shuffle; ' +
+ 'function f() { var x=u8x16(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); shuf(x,x,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); } return f');
+
+
+// Test unary operators.
+function unaryI(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK +
+ `var fut = i8x16.${opname};` +
+ 'function f(v) { v = i8x16chk(v); return fut(v); } return f'), this);
+ let a = [-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,-14,-15,-16];
+ let v = SIMD.Int8x16(...a);
+ assertEqVecArr(simdfunc(v), a.map(lanefunc));
+}
+
+function unaryU(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + U8x16 + I8x16 + I8x16CHK + U8x16I8x16 + I8x16U8x16 +
+ `var fut = u8x16.${opname};` +
+ 'function f(v) { v = i8x16chk(v); return i8x16u8x16(fut(u8x16i8x16(v))); } return f'), this);
+ let a = [256-1,2,256-3,4,256-5,6,256-7,8,256-9,10,256-11,12,256-13,256-14,256-15,256-16];
+ let v = SIMD.Int8x16(...a);
+ assertEqVecArr(SIMD.Uint8x16.fromInt8x16Bits(simdfunc(v)), a.map(lanefunc));
+}
+
+function unaryB(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + B8x16 + B8x16CHK +
+ `var fut = b8x16.${opname};` +
+ 'function f(v) { v = b8x16chk(v); return fut(v); } return f'), this);
+ let a = [1,1,0,1,1,0,0,0,1,1,1,1,0,0,0,1];
+ let v = SIMD.Bool8x16(...a);
+ assertEqVecArr(simdfunc(v), a.map(lanefunc));
+}
+
+unaryI('not', x => ~x << 24 >> 24);
+unaryU('not', x => ~x << 24 >>> 24);
+unaryB('not', x => !x);
+unaryI('neg', x => -x << 24 >> 24);
+unaryU('neg', x => -x << 24 >>> 24);
+
+
+// Test binary operators.
+function zipmap(a1, a2, f) {
+ assertEq(a1.length, a2.length);
+ let r = [];
+ for (var i = 0; i < a1.length; i++)
+ r.push(f(a1[i], a2[i]));
+ return r
+}
+
+function binaryI(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK +
+ `var fut = i8x16.${opname};` +
+ 'function f(v1, v2) { v1 = i8x16chk(v1); v2 = i8x16chk(v2); return fut(v1, v2); } return f'), this);
+ let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16];
+ let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1];
+ let ref = zipmap(a1, a2, lanefunc);
+ let v1 = SIMD.Int8x16(...a1);
+ let v2 = SIMD.Int8x16(...a2);
+ assertEqVecArr(simdfunc(v1, v2), ref);
+}
+
+function binaryU(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + U8x16 + I8x16 + I8x16CHK + U8x16I8x16 + I8x16U8x16 +
+ `var fut = u8x16.${opname};` +
+ 'function f(v1, v2) { v1 = i8x16chk(v1); v2 = i8x16chk(v2); return i8x16u8x16(fut(u8x16i8x16(v1), u8x16i8x16(v2))); } return f'), this);
+ let a1 = [ -1,2, -3,0x80,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16].map(x => x & 0xff);
+ let a2 = [0x80,2,0x80,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16,0xff].map(x => x & 0xff);
+ let ref = zipmap(a1, a2, lanefunc);
+ let v1 = SIMD.Int8x16(...a1);
+ let v2 = SIMD.Int8x16(...a2);
+ let res = SIMD.Uint8x16.fromInt8x16Bits(simdfunc(v1, v2));
+ assertEqVecArr(res, ref);
+}
+
+function binaryB(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + B8x16 + B8x16CHK +
+ `var fut = b8x16.${opname};` +
+ 'function f(v1, v2) { v1 = b8x16chk(v1); v2 = b8x16chk(v2); return fut(v1, v2); } return f'), this);
+ let a = [1,1,0,1,1,0,0,0,1,1,1,1,0,0,0,1];
+ let v = SIMD.Bool8x16(...a);
+ assertEqVecArr(simdfunc(v), a.map(lanefunc));
+}
+
+binaryI('add', (x, y) => (x + y) << 24 >> 24);
+binaryI('sub', (x, y) => (x - y) << 24 >> 24);
+binaryI('mul', (x, y) => (x * y) << 24 >> 24);
+binaryU('add', (x, y) => (x + y) << 24 >>> 24);
+binaryU('sub', (x, y) => (x - y) << 24 >>> 24);
+binaryU('mul', (x, y) => (x * y) << 24 >>> 24);
+
+binaryI('and', (x, y) => (x & y) << 24 >> 24);
+binaryI('or', (x, y) => (x | y) << 24 >> 24);
+binaryI('xor', (x, y) => (x ^ y) << 24 >> 24);
+binaryU('and', (x, y) => (x & y) << 24 >>> 24);
+binaryU('or', (x, y) => (x | y) << 24 >>> 24);
+binaryU('xor', (x, y) => (x ^ y) << 24 >>> 24);
+
+function sat(x, lo, hi) {
+ if (x < lo) return lo;
+ if (x > hi) return hi;
+ return x
+}
+function isat(x) { return sat(x, -128, 127); }
+function usat(x) { return sat(x, 0, 255); }
+
+binaryI('addSaturate', (x, y) => isat(x + y))
+binaryI('subSaturate', (x, y) => isat(x - y))
+binaryU('addSaturate', (x, y) => usat(x + y))
+binaryU('subSaturate', (x, y) => usat(x - y))
+
+// Test shift operators.
+function zip1map(a, s, f) {
+ return a.map(x => f(x, s));
+}
+
+function shiftI(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK +
+ `var fut = i8x16.${opname};` +
+ 'function f(v, s) { v = i8x16chk(v); s = s|0; return fut(v, s); } return f'), this);
+ let a = [0x80,2,0x80,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16,0xff];
+ let v = SIMD.Int8x16(...a);
+ for (let s of [0, 1, 2, 6, 7, 8, 9, 10, 16, 255, -1, -8, -7, -1000]) {
+ let ref = zip1map(a, s, lanefunc);
+ // 1. Test dynamic shift amount.
+ assertEqVecArr(simdfunc(v, s), ref);
+
+ // 2. Test constant shift amount.
+ let cstf = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK +
+ `var fut = i8x16.${opname};` +
+ `function f(v) { v = i8x16chk(v); return fut(v, ${s}); } return f`), this);
+ assertEqVecArr(cstf(v, s), ref);
+ }
+}
+
+function shiftU(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + U8x16 + I8x16 + I8x16CHK + U8x16I8x16 + I8x16U8x16 +
+ `var fut = u8x16.${opname};` +
+ 'function f(v, s) { v = i8x16chk(v); s = s|0; return i8x16u8x16(fut(u8x16i8x16(v), s)); } return f'), this);
+ let a = [0x80,2,0x80,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16,0xff];
+ let v = SIMD.Int8x16(...a);
+ for (let s of [0, 1, 2, 6, 7, 8, 9, 10, 16, 255, -1, -8, -7, -1000]) {
+ let ref = zip1map(a, s, lanefunc);
+ // 1. Test dynamic shift amount.
+ assertEqVecArr(SIMD.Uint8x16.fromInt8x16Bits(simdfunc(v, s)), ref);
+
+ // 2. Test constant shift amount.
+ let cstf = asmLink(asmCompile('glob', USE_ASM + U8x16 + I8x16 + I8x16CHK + U8x16I8x16 + I8x16U8x16 +
+ `var fut = u8x16.${opname};` +
+ `function f(v) { v = i8x16chk(v); return i8x16u8x16(fut(u8x16i8x16(v), ${s})); } return f`), this);
+ assertEqVecArr(SIMD.Uint8x16.fromInt8x16Bits(cstf(v, s)), ref);
+ }
+}
+
+shiftI('shiftLeftByScalar', (x,s) => (x << (s & 7)) << 24 >> 24);
+shiftU('shiftLeftByScalar', (x,s) => (x << (s & 7)) << 24 >>> 24);
+shiftI('shiftRightByScalar', (x,s) => ((x << 24 >> 24) >> (s & 7)) << 24 >> 24);
+shiftU('shiftRightByScalar', (x,s) => ((x << 24 >>> 24) >>> (s & 7)) << 24 >>> 24);
+
+
+// Comparisons.
+function compareI(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK +
+ `var fut = i8x16.${opname};` +
+ 'function f(v1, v2) { v1 = i8x16chk(v1); v2 = i8x16chk(v2); return fut(v1, v2); } return f'), this);
+ let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16];
+ let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1];
+ let ref = zipmap(a1, a2, lanefunc);
+ let v1 = SIMD.Int8x16(...a1);
+ let v2 = SIMD.Int8x16(...a2);
+ assertEqVecArr(simdfunc(v1, v2), ref);
+}
+
+function compareU(opname, lanefunc) {
+ let simdfunc = asmLink(asmCompile('glob', USE_ASM + I8x16 + I8x16CHK + U8x16 + U8x16I8x16 +
+ `var fut = u8x16.${opname};` +
+ 'function f(v1, v2) { v1 = i8x16chk(v1); v2 = i8x16chk(v2); return fut(u8x16i8x16(v1), u8x16i8x16(v2)); } return f'), this);
+ let a1 = [ -1,2, -3,-128,0x7f,6,-7, 8,-9, 10,-11, 12,-13,-14,-15, -16].map(x => x << 24 >>> 24);
+ let a2 = [-128,2,-128,0x7f, 0,0, 8,-9,10,-11, 12,-13,-14,-15,-16, -1].map(x => x << 24 >>> 24);
+ let ref = zipmap(a1, a2, lanefunc);
+ let v1 = SIMD.Int8x16(...a1);
+ let v2 = SIMD.Int8x16(...a2);
+ assertEqVecArr(simdfunc(v1, v2), ref);
+}
+
+compareI("equal", (x,y) => x == y);
+compareU("equal", (x,y) => x == y);
+compareI("notEqual", (x,y) => x != y);
+compareU("notEqual", (x,y) => x != y);
+compareI("lessThan", (x,y) => x < y);
+compareU("lessThan", (x,y) => x < y);
+compareI("lessThanOrEqual", (x,y) => x <= y);
+compareU("lessThanOrEqual", (x,y) => x <= y);
+compareI("greaterThan", (x,y) => x > y);
+compareU("greaterThan", (x,y) => x > y);
+compareI("greaterThanOrEqual", (x,y) => x >= y);
+compareU("greaterThanOrEqual", (x,y) => x >= y);
diff --git a/js/src/jit-test/tests/asm.js/testSIMD-bitcasts.js b/js/src/jit-test/tests/asm.js/testSIMD-bitcasts.js
new file mode 100644
index 000000000..c5a5fb2bc
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testSIMD-bitcasts.js
@@ -0,0 +1,84 @@
+load(libdir + "asm.js");
+load(libdir + "simd.js");
+load(libdir + "asserts.js");
+
+// Set to true to see more JS debugging spew.
+const DEBUG = false;
+
+if (!isSimdAvailable()) {
+ DEBUG && print("won't run tests as simd extensions aren't activated yet");
+ quit(0);
+}
+
+// Test all bit-casts and normal loads and stores.
+var heap = new ArrayBuffer(BUF_MIN);
+var asU8 = new Uint8Array(heap);
+var allTypes = [
+ "Int8x16",
+ "Int16x8",
+ "Int32x4",
+ "Uint8x16",
+ "Uint16x8",
+ "Uint32x4",
+ "Float32x4"
+];
+
+// Generate a load bit-cast store test function that performs:
+//
+// function f(a, b) {
+// vec = src.load(H, a);
+// cast = dst.from«src»Bits(vec);
+// store(H, b, cast);
+// }
+//
+// Here, `H` is the heap provided by `heap`.
+function test_func(src, dst) {
+ text = `
+ "use asm";
+ var src = glob.SIMD.${src};
+ var dst = glob.SIMD.${dst};
+ var ld = src.load;
+ var st = dst.store;
+ var bc = dst.from${src}Bits;
+
+ var H = new glob.Uint8Array(heap);
+
+ function f(a, b) {
+ a = a|0;
+ b = b|0;
+
+ st(H, b, bc(ld(H, a)));
+ }
+
+ return f;
+ `;
+ return asmLink(asmCompile('glob', 'ffi', 'heap', text), this, null, heap);
+}
+
+function assertBuf16(a, b) {
+ for (let i=0; i < 16; i++) {
+ assertEq(asU8[a+i], asU8[b+i]);
+ }
+}
+
+for (let src of allTypes) {
+ for (let dst of allTypes) {
+ // Skip identity conversions.
+ if (src == dst) continue;
+
+ print(src, dst);
+ let f = test_func(src, dst);
+ // Initialize with pseudo-random data.
+ for (let i = 0; i < 64; i++) {
+ asU8[i] = (i + 17) * 97;
+ }
+
+ // Aligned load/store.
+ f(0, 16);
+ assertBuf16(0, 16);
+
+ // Unaligned access.
+ f(1, 27);
+ assertBuf16(1, 27);
+ }
+}
diff --git a/js/src/jit-test/tests/asm.js/testSIMD-load-store.js b/js/src/jit-test/tests/asm.js/testSIMD-load-store.js
new file mode 100644
index 000000000..d826c106b
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testSIMD-load-store.js
@@ -0,0 +1,457 @@
+// |jit-test|
+load(libdir + "asm.js");
+load(libdir + "simd.js");
+load(libdir + "asserts.js");
+
+// Avoid pathological --ion-eager compile times due to bails in loops
+setJitCompilerOption('ion.warmup.trigger', 1000000);
+
+// Set to true to see more JS debugging spew
+const DEBUG = false;
+
+if (!isSimdAvailable() || typeof SIMD === 'undefined' || !isAsmJSCompilationAvailable()) {
+ DEBUG && print("won't run tests as simd extensions aren't activated yet");
+ quit(0);
+}
+
+const RuntimeError = WebAssembly.RuntimeError;
+
+const INT32_MAX = Math.pow(2, 31) - 1;
+const INT32_MIN = INT32_MAX + 1 | 0;
+
+try {
+
+// Load / Store
+var IMPORTS = USE_ASM + 'var H=new glob.Uint8Array(heap); var i4=glob.SIMD.Int32x4; var ci4=i4.check; var load=i4.load; var store=i4.store;';
+
+// Bad number of args
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load();} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(3);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(3, 4, 5);} return f");
+
+// Bad type of args
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(3, 5);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, 5.0);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){var i=0.;load(H, i);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "var H2=new glob.Int32Array(heap); function f(){var i=0;load(H2, i)} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "var H2=42; function f(){var i=0;load(H2, i)} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){var i=0;load(H2, i)} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "var f4=glob.SIMD.Float32x4; function f(){var i=0;var vec=f4(1,2,3,4); store(H, i, vec)} return f");
+
+// Bad coercions of returned values
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){var i=0;return load(H, i)|0;} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){var i=0;return +load(H, i);} return f");
+
+// Literal index constants
+var buf = new ArrayBuffer(BUF_MIN);
+var SIZE_TA = BUF_MIN >> 2
+var asI32 = new Int32Array(buf);
+asI32[SIZE_TA - 4] = 4;
+asI32[SIZE_TA - 3] = 3;
+asI32[SIZE_TA - 2] = 2;
+asI32[SIZE_TA - 1] = 1;
+
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, -1);} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, " + (INT32_MAX + 1) + ");} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, " + (INT32_MAX + 1 - 15) + ");} return f");
+asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, " + (INT32_MAX + 1 - 16) + ");} return f");
+
+assertAsmLinkFail(asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f() {return ci4(load(H, " + (BUF_MIN - 15) + "));} return f"), this, {}, buf);
+assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f() {return ci4(load(H, " + (BUF_MIN - 16) + "));} return f"), this, {}, buf)(), [4, 3, 2, 1]);
+assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f() {return ci4(load(H, " + BUF_MIN + " - 16 | 0));} return f"), this, {}, buf)(), [4, 3, 2, 1]);
+
+var CONSTANT_INDEX = 42;
+var CONSTANT_BYTE_INDEX = CONSTANT_INDEX << 2;
+
+var loadStoreCode = `
+ "use asm";
+
+ var H = new glob.Uint8Array(heap);
+
+ var i4 = glob.SIMD.Int32x4;
+ var i4load = i4.load;
+ var i4store = i4.store;
+ var ci4 = i4.check;
+
+ var f4 = glob.SIMD.Float32x4;
+ var f4load = f4.load;
+ var f4store = f4.store;
+ var cf4 = f4.check;
+
+ function f32l(i) { i=i|0; return cf4(f4load(H, i|0)); }
+ function f32lcst() { return cf4(f4load(H, ${CONSTANT_BYTE_INDEX})); }
+ function f32s(i, vec) { i=i|0; vec=cf4(vec); f4store(H, i|0, vec); }
+ function f32scst(vec) { vec=cf4(vec); f4store(H, ${CONSTANT_BYTE_INDEX}, vec); }
+
+ function i32l(i) { i=i|0; return ci4(i4load(H, i|0)); }
+ function i32lcst() { return ci4(i4load(H, ${CONSTANT_BYTE_INDEX})); }
+ function i32s(i, vec) { i=i|0; vec=ci4(vec); i4store(H, i|0, vec); }
+ function i32scst(vec) { vec=ci4(vec); i4store(H, ${CONSTANT_BYTE_INDEX}, vec); }
+
+ function f32lbndcheck(i) {
+ i=i|0;
+ if ((i|0) > ${CONSTANT_BYTE_INDEX}) i=${CONSTANT_BYTE_INDEX};
+ if ((i|0) < 0) i = 0;
+ return cf4(f4load(H, i|0));
+ }
+ function f32sbndcheck(i, vec) {
+ i=i|0;
+ vec=cf4(vec);
+ if ((i|0) > ${CONSTANT_BYTE_INDEX}) i=${CONSTANT_BYTE_INDEX};
+ if ((i|0) < 0) i = 0;
+ return cf4(f4store(H, i|0, vec));
+ }
+
+ return {
+ f32l: f32l,
+ f32lcst: f32lcst,
+ f32s: f32s,
+ f32scst: f32scst,
+ f32lbndcheck: f32lbndcheck,
+ f32sbndcheck: f32sbndcheck,
+ i32l: i32l,
+ i32lcst: i32lcst,
+ i32s: i32s,
+ i32scst: i32scst
+ }
+`;
+
+const SIZE = 0x8000;
+
+var F32 = new Float32Array(SIZE);
+var reset = function() {
+ for (var i = 0; i < SIZE; i++)
+ F32[i] = i + 1;
+};
+reset();
+
+var buf = F32.buffer;
+var m = asmLink(asmCompile('glob', 'ffi', 'heap', loadStoreCode), this, null, buf);
+
+function slice(TA, i, n) { return Array.prototype.slice.call(TA, i, i + n); }
+
+// Float32x4.load
+function f32l(n) { return m.f32l((n|0) << 2 | 0); };
+
+// Correct accesses
+assertEqX4(f32l(0), slice(F32, 0, 4));
+assertEqX4(f32l(1), slice(F32, 1, 4));
+assertEqX4(f32l(SIZE - 4), slice(F32, SIZE - 4, 4));
+
+assertEqX4(m.f32lcst(), slice(F32, CONSTANT_INDEX, 4));
+assertEqX4(m.f32lbndcheck(CONSTANT_BYTE_INDEX), slice(F32, CONSTANT_INDEX, 4));
+
+// OOB
+assertThrowsInstanceOf(() => f32l(-1), RuntimeError);
+assertThrowsInstanceOf(() => f32l(SIZE), RuntimeError);
+assertThrowsInstanceOf(() => f32l(SIZE - 1), RuntimeError);
+assertThrowsInstanceOf(() => f32l(SIZE - 2), RuntimeError);
+assertThrowsInstanceOf(() => f32l(SIZE - 3), RuntimeError);
+
+var code = `
+ "use asm";
+ var f4 = glob.SIMD.Float32x4;
+ var f4l = f4.load;
+ var u8 = new glob.Uint8Array(heap);
+
+ function g(x) {
+ x = x|0;
+ // set a constraint on the size of the heap
+ var ptr = 0;
+ ptr = u8[0xFFFF] | 0;
+ // give a precise range to x
+ x = (x>>0) > 5 ? 5 : x;
+ x = (x>>0) < 0 ? 0 : x;
+ // ptr value gets a precise range but the bounds check shouldn't get
+ // eliminated.
+ return f4l(u8, 0xFFFA + x | 0);
+ }
+
+ return g;
+`;
+assertThrowsInstanceOf(() => asmLink(asmCompile('glob', 'ffi', 'heap', code), this, {}, new ArrayBuffer(0x10000))(0), RuntimeError);
+
+// Float32x4.store
+function f32s(n, v) { return m.f32s((n|0) << 2 | 0, v); };
+
+var vec = SIMD.Float32x4(5,6,7,8);
+var vec2 = SIMD.Float32x4(0,1,2,3);
+var vecWithNaN = SIMD.Float32x4(NaN, 2, NaN, 4);
+
+reset();
+f32s(0, vec);
+assertEqX4(vec, slice(F32, 0, 4));
+
+reset();
+f32s(0, vec2);
+assertEqX4(vec2, slice(F32, 0, 4));
+
+reset();
+f32s(4, vec);
+assertEqX4(vec, slice(F32, 4, 4));
+
+reset();
+f32s(4, vecWithNaN);
+assertEqX4(vecWithNaN, slice(F32, 4, 4));
+
+reset();
+m.f32scst(vec2);
+assertEqX4(vec2, slice(F32, CONSTANT_INDEX, 4));
+
+reset();
+m.f32sbndcheck(CONSTANT_BYTE_INDEX, vec);
+assertEqX4(vec, slice(F32, CONSTANT_INDEX, 4));
+
+// OOB
+reset();
+assertThrowsInstanceOf(() => f32s(SIZE - 3, vec), RuntimeError);
+assertThrowsInstanceOf(() => f32s(SIZE - 2, vec), RuntimeError);
+assertThrowsInstanceOf(() => f32s(SIZE - 1, vec), RuntimeError);
+assertThrowsInstanceOf(() => f32s(SIZE, vec), RuntimeError);
+for (var i = 0; i < SIZE; i++)
+ assertEq(F32[i], i + 1);
+
+// Int32x4.load
+var I32 = new Int32Array(buf);
+reset = function () {
+ for (var i = 0; i < SIZE; i++)
+ I32[i] = i + 1;
+};
+reset();
+
+function i32(n) { return m.i32l((n|0) << 2 | 0); };
+
+// Correct accesses
+assertEqX4(i32(0), slice(I32, 0, 4));
+assertEqX4(i32(1), slice(I32, 1, 4));
+assertEqX4(i32(SIZE - 4), slice(I32, SIZE - 4, 4));
+
+assertEqX4(m.i32lcst(), slice(I32, CONSTANT_INDEX, 4));
+
+// OOB
+assertThrowsInstanceOf(() => i32(-1), RuntimeError);
+assertThrowsInstanceOf(() => i32(SIZE), RuntimeError);
+assertThrowsInstanceOf(() => i32(SIZE - 1), RuntimeError);
+assertThrowsInstanceOf(() => i32(SIZE - 2), RuntimeError);
+assertThrowsInstanceOf(() => i32(SIZE - 3), RuntimeError);
+
+// Int32x4.store
+function i32s(n, v) { return m.i32s((n|0) << 2 | 0, v); };
+
+var vec = SIMD.Int32x4(5,6,7,8);
+var vec2 = SIMD.Int32x4(0,1,2,3);
+
+reset();
+i32s(0, vec);
+assertEqX4(vec, slice(I32, 0, 4));
+
+reset();
+i32s(0, vec2);
+assertEqX4(vec2, slice(I32, 0, 4));
+
+reset();
+i32s(4, vec);
+assertEqX4(vec, slice(I32, 4, 4));
+
+reset();
+m.i32scst(vec2);
+assertEqX4(vec2, slice(I32, CONSTANT_INDEX, 4));
+
+// OOB
+reset();
+assertThrowsInstanceOf(() => i32s(SIZE - 3, vec), RuntimeError);
+assertThrowsInstanceOf(() => i32s(SIZE - 2, vec), RuntimeError);
+assertThrowsInstanceOf(() => i32s(SIZE - 1, vec), RuntimeError);
+assertThrowsInstanceOf(() => i32s(SIZE - 0, vec), RuntimeError);
+for (var i = 0; i < SIZE; i++)
+ assertEq(I32[i], i + 1);
+
+// Partial loads and stores
+(function() {
+
+// Variable indexes
+function MakeCodeFor(typeName) {
+ return `
+ "use asm";
+ var type = glob.SIMD.${typeName};
+ var c = type.check;
+
+ var l1 = type.load1;
+ var l2 = type.load2;
+
+ var s1 = type.store1;
+ var s2 = type.store2;
+
+ var u8 = new glob.Uint8Array(heap);
+
+ function load1(i) { i=i|0; return l1(u8, i); }
+ function load2(i) { i=i|0; return l2(u8, i); }
+
+ function loadCst1() { return l1(u8, 41 << 2); }
+ function loadCst2() { return l2(u8, 41 << 2); }
+
+ function store1(i, x) { i=i|0; x=c(x); return s1(u8, i, x); }
+ function store2(i, x) { i=i|0; x=c(x); return s2(u8, i, x); }
+
+ function storeCst1(x) { x=c(x); return s1(u8, 41 << 2, x); }
+ function storeCst2(x) { x=c(x); return s2(u8, 41 << 2, x); }
+
+ return {
+ load1: load1,
+ load2: load2,
+ loadCst1: loadCst1,
+ loadCst2: loadCst2,
+ store1: store1,
+ store2: store2,
+ storeCst1: storeCst1,
+ storeCst2: storeCst2,
+ }
+`;
+}
+
+var SIZE = 0x10000;
+
+function TestPartialLoads(m, typedArray, x, y, z, w) {
+ // Fill array with predictable values
+ for (var i = 0; i < SIZE; i += 4) {
+ typedArray[i] = x(i);
+ typedArray[i + 1] = y(i);
+ typedArray[i + 2] = z(i);
+ typedArray[i + 3] = w(i);
+ }
+
+ // Test correct loads
+ var i = 0, j = 0; // i in elems, j in bytes
+ assertEqX4(m.load1(j), [x(i), 0, 0, 0]);
+ assertEqX4(m.load2(j), [x(i), y(i), 0, 0]);
+
+ j += 4;
+ assertEqX4(m.load1(j), [y(i), 0, 0, 0]);
+ assertEqX4(m.load2(j), [y(i), z(i), 0, 0]);
+
+ j += 4;
+ assertEqX4(m.load1(j), [z(i), 0, 0, 0]);
+ assertEqX4(m.load2(j), [z(i), w(i), 0, 0]);
+
+ j += 4;
+ assertEqX4(m.load1(j), [w(i), 0, 0, 0]);
+ assertEqX4(m.load2(j), [w(i), x(i+4), 0, 0]);
+
+ j += 4;
+ i += 4;
+ assertEqX4(m.load1(j), [x(i), 0, 0, 0]);
+ assertEqX4(m.load2(j), [x(i), y(i), 0, 0]);
+
+ // Test loads with constant indexes (41)
+ assertEqX4(m.loadCst1(), [y(40), 0, 0, 0]);
+ assertEqX4(m.loadCst2(), [y(40), z(40), 0, 0]);
+
+ // Test limit and OOB accesses
+ assertEqX4(m.load1((SIZE - 1) << 2), [w(SIZE - 4), 0, 0, 0]);
+ assertThrowsInstanceOf(() => m.load1(((SIZE - 1) << 2) + 1), RuntimeError);
+
+ assertEqX4(m.load2((SIZE - 2) << 2), [z(SIZE - 4), w(SIZE - 4), 0, 0]);
+ assertThrowsInstanceOf(() => m.load2(((SIZE - 2) << 2) + 1), RuntimeError);
+}
+
+// Partial stores
+function TestPartialStores(m, typedArray, typeName, x, y, z, w) {
+ var val = SIMD[typeName](x, y, z, w);
+
+ function Reset() {
+ for (var i = 0; i < SIZE; i++)
+ typedArray[i] = i + 1;
+ }
+ function CheckNotModified(low, high) {
+ for (var i = low; i < high; i++)
+ assertEq(typedArray[i], i + 1);
+ }
+
+ function TestStore1(i) {
+ m.store1(i, val);
+ CheckNotModified(0, i >> 2);
+ assertEq(typedArray[i >> 2], x);
+ CheckNotModified((i >> 2) + 1, SIZE);
+ typedArray[i >> 2] = (i >> 2) + 1;
+ }
+
+ function TestStore2(i) {
+ m.store2(i, val);
+ CheckNotModified(0, i >> 2);
+ assertEq(typedArray[i >> 2], x);
+ assertEq(typedArray[(i >> 2) + 1], y);
+ CheckNotModified((i >> 2) + 2, SIZE);
+ typedArray[i >> 2] = (i >> 2) + 1;
+ typedArray[(i >> 2) + 1] = (i >> 2) + 2;
+ }
+
+ function TestOOBStore(f) {
+ assertThrowsInstanceOf(f, RuntimeError);
+ CheckNotModified(0, SIZE);
+ }
+
+ Reset();
+
+ TestStore1(0);
+ TestStore1(1 << 2);
+ TestStore1(2 << 2);
+ TestStore1(3 << 2);
+ TestStore1(1337 << 2);
+
+ var i = (SIZE - 1) << 2;
+ TestStore1(i);
+ TestOOBStore(() => m.store1(i + 1, val));
+ TestOOBStore(() => m.store1(-1, val));
+
+ TestStore2(0);
+ TestStore2(1 << 2);
+ TestStore2(2 << 2);
+ TestStore2(3 << 2);
+ TestStore2(1337 << 2);
+
+ var i = (SIZE - 2) << 2;
+ TestStore2(i);
+ TestOOBStore(() => m.store2(i + 1, val));
+ TestOOBStore(() => m.store2(-1, val));
+
+ // Constant indexes (41)
+ m.storeCst1(val);
+ CheckNotModified(0, 41);
+ assertEq(typedArray[41], x);
+ CheckNotModified(42, SIZE);
+ typedArray[41] = 42;
+
+ m.storeCst2(val);
+ CheckNotModified(0, 41);
+ assertEq(typedArray[41], x);
+ assertEq(typedArray[42], y);
+ CheckNotModified(43, SIZE);
+ typedArray[41] = 42;
+ typedArray[42] = 43;
+}
+
+var f32 = new Float32Array(SIZE);
+var mFloat32x4 = asmLink(asmCompile('glob', 'ffi', 'heap', MakeCodeFor('Float32x4')), this, null, f32.buffer);
+
+TestPartialLoads(mFloat32x4, f32,
+ (i) => i + 1,
+ (i) => Math.fround(13.37),
+ (i) => Math.fround(1/i),
+ (i) => Math.fround(Math.sqrt(0x2000 - i)));
+
+TestPartialStores(mFloat32x4, f32, 'Float32x4', 42, -0, NaN, 0.1337);
+
+var i32 = new Int32Array(f32.buffer);
+var mInt32x4 = asmLink(asmCompile('glob', 'ffi', 'heap', MakeCodeFor('Int32x4')), this, null, i32.buffer);
+
+TestPartialLoads(mInt32x4, i32,
+ (i) => i + 1 | 0,
+ (i) => -i | 0,
+ (i) => i * 2 | 0,
+ (i) => 42);
+
+TestPartialStores(mInt32x4, i32, 'Int32x4', 42, -3, 13, 37);
+
+})();
+
+} catch (e) { print('stack: ', e.stack); throw e }
diff --git a/js/src/jit-test/tests/asm.js/testSIMD.js b/js/src/jit-test/tests/asm.js/testSIMD.js
new file mode 100644
index 000000000..29786bc52
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testSIMD.js
@@ -0,0 +1,1575 @@
+load(libdir + "asm.js");
+load(libdir + "simd.js");
+load(libdir + "asserts.js");
+var heap = new ArrayBuffer(0x10000);
+
+// Avoid pathological --ion-eager compile times due to bails in loops
+setJitCompilerOption('ion.warmup.trigger', 1000000);
+
+// Set to true to see more JS debugging spew
+const DEBUG = false;
+
+if (!isSimdAvailable() || typeof SIMD === 'undefined' || !isAsmJSCompilationAvailable()) {
+ DEBUG && print("won't run tests as simd extensions aren't activated yet");
+ quit(0);
+}
+
+const I32 = 'var i4 = glob.SIMD.Int32x4;'
+const CI32 = 'var ci4 = i4.check;'
+const I32A = 'var i4a = i4.add;'
+const I32S = 'var i4s = i4.sub;'
+const I32M = 'var i4m = i4.mul;'
+const I32U32 = 'var i4u4 = i4.fromUint32x4Bits;'
+
+const U32 = 'var u4 = glob.SIMD.Uint32x4;'
+const CU32 = 'var cu4 = u4.check;'
+const U32A = 'var u4a = u4.add;'
+const U32S = 'var u4s = u4.sub;'
+const U32M = 'var u4m = u4.mul;'
+const U32I32 = 'var u4i4 = u4.fromInt32x4Bits;'
+
+const F32 = 'var f4 = glob.SIMD.Float32x4;'
+const CF32 = 'var cf4 = f4.check;'
+const F32A = 'var f4a = f4.add;'
+const F32S = 'var f4s = f4.sub;'
+const F32M = 'var f4m = f4.mul;'
+const F32D = 'var f4d = f4.div;'
+const FROUND = 'var f32=glob.Math.fround;'
+const B32 = 'var b4 = glob.SIMD.Bool32x4;'
+const CB32 = 'var cb4 = b4.check;'
+
+const EXTI4 = 'var e = i4.extractLane;'
+const EXTU4 = 'var e = u4.extractLane;'
+const EXTF4 = 'var e = f4.extractLane;'
+const EXTB4 = 'var e = b4.extractLane;'
+
+// anyTrue / allTrue on boolean vectors.
+const ANYB4 = 'var anyt=b4.anyTrue;'
+const ALLB4 = 'var allt=b4.allTrue;'
+
+const INT32_MAX = Math.pow(2, 31) - 1;
+const INT32_MIN = INT32_MAX + 1 | 0;
+const UINT32_MAX = Math.pow(2, 32) - 1;
+
+const assertEqFFI = {assertEq:assertEq};
+
+function CheckI4(header, code, expected) {
+ // code needs to contain a local called x
+ header = USE_ASM + I32 + CI32 + EXTI4 + F32 + header;
+ var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return ci4(x)} return f'), this)();
+ assertEqX4(observed, expected);
+}
+
+function CheckU4(header, code, expected) {
+ // code needs to contain a local called x.
+ header = USE_ASM + U32 + CU32 + EXTU4 + I32 + CI32 + I32U32 + header;
+ var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return ci4(i4u4(x))} return f'), this)();
+ // We can't return an unsigned SIMD type. Return Int32x4, convert to unsigned here.
+ observed = SIMD.Uint32x4.fromInt32x4Bits(observed)
+ assertEqX4(observed, expected);
+}
+
+function CheckF4(header, code, expected) {
+ // code needs to contain a local called x
+ header = USE_ASM + F32 + CF32 + EXTF4 + header;
+ var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return cf4(x)} return f'), this)();
+ assertEqX4(observed, expected.map(Math.fround));
+}
+
+function CheckB4(header, code, expected) {
+ // code needs to contain a local called x
+ header = USE_ASM + B32 + CB32 + header;
+ var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return cb4(x)} return f'), this)();
+ assertEqX4(observed, expected);
+}
+
+try {
+
+// 1. Constructors
+
+// 1.1 Compilation
+assertAsmTypeFail('glob', USE_ASM + "var i4 = Int32x4 ; return {}") ;
+assertAsmTypeFail('glob', USE_ASM + "var i4 = glob.Int32x4 ; return {}") ;
+assertAsmTypeFail('glob', USE_ASM + "var i4 = glob.globglob.Int32x4 ; return {}") ;
+assertAsmTypeFail('glob', USE_ASM + "var i4 = glob.Math.Int32x4 ; return {}") ;
+assertAsmTypeFail('glob', USE_ASM + "var herd = glob.SIMD.ponyX4 ; return {}") ;
+
+// 1.2 Linking
+assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: 42});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: Math.fround});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: 42}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: Math.fround}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: new Array}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: SIMD.Float32x4}});
+
+var [Type, int32] = [TypedObject.StructType, TypedObject.int32];
+var MyStruct = new Type({'x': int32, 'y': int32, 'z': int32, 'w': int32});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: MyStruct}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + I32 + "return {}"), {SIMD: {Int32x4: new MyStruct}});
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {} return f"), {SIMD:{Int32x4: SIMD.Int32x4}})(), undefined);
+
+assertAsmLinkFail(asmCompile('glob', USE_ASM + F32 + "return {}"), {SIMD: {Float32x4: 42}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + F32 + "return {}"), {SIMD: {Float32x4: Math.fround}});
+assertAsmLinkFail(asmCompile('glob', USE_ASM + F32 + "return {}"), {SIMD: {Float32x4: new Array}});
+assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {} return f"), {SIMD:{Float32x4: SIMD.Float32x4}})(), undefined);
+
+// 1.3 Correctness
+// 1.3.1 Local variables declarations
+assertAsmTypeFail('glob', USE_ASM + "function f() {var x=Int32x4(1,2,3,4);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4();} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1, 2);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1, 2, 3);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1, 2, 3, 4.0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1, 2.0, 3, 4);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4a(1,2,3,4);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,2+2|0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3," + (INT32_MIN - 1) + ");} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(i4(1,2,3,4));} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4);} return f"), this)(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3," + (INT32_MAX + 1) + ");} return f"), this)(), undefined);
+
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4;} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4();} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3);} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1.,2.,3.);} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1.,2.,f32(3.),4.);} return f");
+assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {var x=f4(1.,2.,3.,4.);} return f"), this)(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4);} return f"), this)(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3," + (INT32_MIN - 1) + ");} return f"), this)(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3," + (INT32_MAX + 1) + ");} return f"), this)(), undefined);
+
+// Places where NumLit can creep in
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f(i) {i=i|0; var z=0; switch(i|0) {case i4(1,2,3,4): z=1; break; default: z=2; break;}} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f(i) {i=i|0; var z=0; return i * i4(1,2,3,4) | 0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f(i) {var x=i4(1,2,3,i4(4,5,6,7))} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f(i) {var x=i4(1,2,3,f4(4,5,6,7))} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f(i) {var x=f4(1,2,3,i4(4,5,6,7))} return f");
+
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {return +i4(1,2,3,4)} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {return i4(1,2,3,4)|0} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f() {return f32(i4(1,2,3,4))} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + "function f() {return cf4(i4(1,2,3,4))} return f");
+
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {return +f4(1,2,3,4)} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {return f4(1,2,3,4)|0} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + FROUND + "function f() {return f32(f4(1,2,3,4))} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + "function f() {return ci4(f4(1,2,3,4))} return f");
+
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {return i4(1,2,3,4);} return f"), this)(), [1, 2, 3, 4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f() {return ci4(i4(1,2,3,4));} return f"), this)(), [1, 2, 3, 4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {return f4(1,2,3,4);} return f"), this)(), [1, 2, 3, 4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f() {return cf4(f4(1,2,3,4));} return f"), this)(), [1, 2, 3, 4]);
+
+assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {i4(1,2,3,4);} return f"), this)(), undefined);
+assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {f4(1,2,3,4);} return f"), this)(), undefined);
+
+// Int32x4 ctor should accept int?
+assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + I32 + CI32 + "var i32=new glob.Int32Array(heap); function f(i) {i=i|0; return ci4(i4(i32[i>>2], 2, 3, 4))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [0, 2, 3, 4]);
+// Float32x4 ctor should accept floatish (i.e. float || float? || floatish) and doublit
+assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + CF32 + FROUND + "var h=new glob.Float32Array(heap); function f(i) {i=i|0; return cf4(f4(h[i>>2], f32(2), f32(3), f32(4)))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [NaN, 2, 3, 4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + FROUND + "function f(i) {i=i|0; return cf4(f4(f32(1) + f32(2), f32(2), f32(3), f32(4)))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [3, 2, 3, 4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + FROUND + "function f(i) {i=i|0; return cf4(f4(f32(1) + f32(2), 2.0, 3.0, 4.0))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [3, 2, 3, 4]);
+// Bool32x4 ctor should accept int?
+assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + B32 + CB32 + "var i32=new glob.Int32Array(heap); function f(i) {i=i|0; return cb4(b4(i32[i>>2], 2, 0, 4))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [false, true, false, true]);
+
+// 1.3.2 Getters - Reading values out of lanes
+assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=1; return e(x,1) | 0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=1; return e(x + x, 1) | 0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=1.; return e(x, 1) | 0;} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + EXTF4 + "var f32=glob.Math.fround;" + I32 + "function f() {var x=f32(1); return e(x, 1) | 0;} return f");
+
+assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); return x.length|0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=e(i4(1,2,3,4),1); return x|0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); return (e(x,0) > (1>>>0)) | 0;} return f");
+
+assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); return e(x,-1) | 0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); return e(x,4) | 0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); return e(x,.5) | 0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); return e(x,x) | 0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + EXTF4 + "function f() {var x=i4(1,2,3,4); return e(x,0) | 0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + EXTI4 + "function f() {var x=i4(1,2,3,4); var i=0; return e(x,i) | 0;} return f");
+
+// The signMask property is no longer supported. Replaced by allTrue / anyTrue.
+assertAsmTypeFail('glob', USE_ASM + "function f() {var x=42; return x.signMask;} return f");
+assertAsmTypeFail('glob', USE_ASM + "function f() {var x=42.; return x.signMask;} return f");
+assertAsmTypeFail('glob', USE_ASM + FROUND + "function f() {var x=f32(42.); return x.signMask;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + 'function f() { var x=i4(1,2,3,4); return x.signMask | 0 } return f');
+assertAsmTypeFail('glob', USE_ASM + U32 + 'function f() { var x=u4(1,2,3,4); return x.signMask | 0 } return f');
+assertAsmTypeFail('glob', USE_ASM + F32 + FROUND + 'var Infinity = glob.Infinity; function f() { var x=f4(0,0,0,0); x=f4(f32(1), f32(-13.37), f32(42), f32(-Infinity)); return x.signMask | 0 } return f');
+
+// Check lane extraction.
+function CheckLanes(innerBody, type, expected) {
+ var coerceBefore, coerceAfter, extractLane;
+
+ if (type === SIMD.Int32x4) {
+ coerceBefore = '';
+ coerceAfter = '|0';
+ extractLane = 'ei';
+ } else if (type === SIMD.Uint32x4) {
+ // Coerce Uint32 lanes to double so they can be legally returned.
+ coerceBefore = '+';
+ coerceAfter = '';
+ extractLane = 'eu';
+ } else if (type === SIMD.Float32x4) {
+ coerceBefore = '+';
+ coerceAfter = '';
+ extractLane = 'ef';
+ expected = expected.map(Math.fround);
+ } else if (type === SIMD.Bool32x4) {
+ coerceBefore = '';
+ coerceAfter = '|0';
+ extractLane = 'eb';
+ } else throw "unexpected type in CheckLanes";
+
+ for (var i = 0; i < 4; i++) {
+ var lane = i;
+ var laneCheckCode = `"use asm";
+ var i4=glob.SIMD.Int32x4;
+ var u4=glob.SIMD.Uint32x4;
+ var f4=glob.SIMD.Float32x4;
+ var b4=glob.SIMD.Bool32x4;
+ var ei=i4.extractLane;
+ var eu=u4.extractLane;
+ var ef=f4.extractLane;
+ var eb=b4.extractLane;
+ function f() {${innerBody}; return ${coerceBefore}${extractLane}(x, ${lane})${coerceAfter} }
+ return f;`;
+ assertEq(asmLink(asmCompile('glob', laneCheckCode), this)(), expected[i]);
+ }
+}
+function CheckLanesI4(innerBody, expected) { return CheckLanes(innerBody, SIMD.Int32x4, expected); }
+function CheckLanesU4(innerBody, expected) { return CheckLanes(innerBody, SIMD.Uint32x4, expected); }
+function CheckLanesF4(innerBody, expected) { return CheckLanes(innerBody, SIMD.Float32x4, expected); }
+function CheckLanesB4(innerBody, expected) { return CheckLanes(innerBody, SIMD.Bool32x4, expected); }
+
+CheckLanesI4('var x=i4(0,0,0,0);', [0,0,0,0]);
+CheckLanesI4('var x=i4(1,2,3,4);', [1,2,3,4]);
+CheckLanesI4('var x=i4(' + INT32_MIN + ',2,3,' + INT32_MAX + ')', [INT32_MIN,2,3,INT32_MAX]);
+CheckLanesI4('var x=i4(1,2,3,4); var y=i4(5,6,7,8)', [1,2,3,4]);
+CheckLanesI4('var a=1; var b=i4(9,8,7,6); var c=13.37; var x=i4(1,2,3,4); var y=i4(5,6,7,8)', [1,2,3,4]);
+CheckLanesI4('var y=i4(5,6,7,8); var x=i4(1,2,3,4)', [1,2,3,4]);
+
+CheckLanesU4('var x=u4(0,0,0,0);', [0,0,0,0]);
+CheckLanesU4('var x=u4(1,2,3,4000000000);', [1,2,3,4000000000]);
+CheckLanesU4('var x=u4(' + INT32_MIN + ',2,3,' + UINT32_MAX + ')', [INT32_MIN>>>0,2,3,UINT32_MAX]);
+CheckLanesU4('var x=u4(1,2,3,4); var y=u4(5,6,7,8)', [1,2,3,4]);
+CheckLanesU4('var a=1; var b=u4(9,8,7,6); var c=13.37; var x=u4(1,2,3,4); var y=u4(5,6,7,8)', [1,2,3,4]);
+CheckLanesU4('var y=u4(5,6,7,8); var x=u4(1,2,3,4)', [1,2,3,4]);
+
+CheckLanesF4('var x=f4(' + INT32_MAX + ', 2, 3, ' + INT32_MIN + ')', [INT32_MAX, 2, 3, INT32_MIN]);
+CheckLanesF4('var x=f4(' + (INT32_MAX + 1) + ', 2, 3, 4)', [INT32_MAX + 1, 2, 3, 4]);
+CheckLanesF4('var x=f4(1.3, 2.4, 3.5, 98.76)', [1.3, 2.4, 3.5, 98.76]);
+CheckLanesF4('var x=f4(13.37, 2., 3., -0)', [13.37, 2, 3, -0]);
+
+CheckLanesB4('var x=b4(0,0,0,0);', [0,0,0,0]);
+CheckLanesB4('var x=b4(0,1,0,0);', [0,1,0,0]);
+CheckLanesB4('var x=b4(0,2,0,0);', [0,1,0,0]);
+CheckLanesB4('var x=b4(-1,0,1,-1);', [1,0,1,1]);
+
+// 1.3.3. Variable assignments
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4();} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1, 2);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1, 2, 3);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1.0, 2, 3, 4);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1, 2.0, 3, 4);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1, 2, 3.0, 4);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1, 2, 3, 4.0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4(1, 2, 3, x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); var c=4.0; x=i4(1, 2, 3, +c);} return f");
+
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + I32 + "var i32=new glob.Int32Array(heap); function f() {var x=i4(1,2,3,4); i32[0] = x;} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + I32 + "var i32=new glob.Int32Array(heap); function f() {var x=i4(1,2,3,4); x = i32[0];} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + F32 + "var f32=new glob.Float32Array(heap); function f() {var x=f4(1,2,3,4); f32[0] = x;} return f");
+assertAsmTypeFail('glob', 'ffi', 'heap', USE_ASM + F32 + "var f32=new glob.Int32Array(heap); function f() {var x=f4(1,2,3,4); x = f32[0];} return f");
+
+CheckI4('', 'var x=i4(1,2,3,4); x=i4(5,6,7,8)', [5, 6, 7, 8]);
+CheckI4('', 'var x=i4(1,2,3,4); var c=6; x=i4(5,c|0,7,8)', [5, 6, 7, 8]);
+CheckI4('', 'var x=i4(8,7,6,5); x=i4(e(x,3)|0,e(x,2)|0,e(x,1)|0,e(x,0)|0)', [5, 6, 7, 8]);
+
+CheckU4('', 'var x=u4(1,2,3,4); x=u4(5,6,7,4000000000)', [5, 6, 7, 4000000000]);
+CheckU4('', 'var x=u4(1,2,3,4); var c=6; x=u4(5,c|0,7,8)', [5, 6, 7, 8]);
+CheckU4('', 'var x=u4(8,7,6,5); x=u4(e(x,3)|0,e(x,2)|0,e(x,1)|0,e(x,0)|0)', [5, 6, 7, 8]);
+
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=f4(1,2,3,c);} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=f4(1.,2.,3.,c);} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4.; x=f4(1,2,3,c);} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4.; x=f4(1.,2.,3.,c);} return f");
+
+CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(7.); x=f4(f32(5),f32(6),y,f32(8))', [5, 6, 7, 8]);
+CheckF4(FROUND, 'var x=f4(1,2,3,4); x=f4(f32(5),f32(6),f32(7),f32(8))', [5, 6, 7, 8]);
+CheckF4(FROUND, 'var x=f4(1,2,3,4); x=f4(f32(5.),f32(6.),f32(7.),f32(8.))', [5, 6, 7, 8]);
+CheckF4('', 'var x=f4(1.,2.,3.,4.); x=f4(5.,6.,7.,8.)', [5, 6, 7, 8]);
+CheckF4('', 'var x=f4(1.,2.,3.,4.); x=f4(1,2,3,4)', [1, 2, 3, 4]);
+CheckF4(FROUND, 'var x=f4(1.,2.,3.,4.); var y=f32(7.); x=f4(9, 4, 2, 1)', [9, 4, 2, 1]);
+CheckF4('', 'var x=f4(8.,7.,6.,5.); x=f4(e(x,3),e(x,2),e(x,1),e(x,0))', [5, 6, 7, 8]);
+
+// Optimization for all lanes from the same definition.
+CheckI4('', 'var x=i4(1,2,3,4); var c=6; x=i4(c|0,c|0,c|0,c|0)', [6, 6, 6, 6]);
+CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(7.); x=f4(y,y,y,y)', [7, 7, 7, 7]);
+CheckI4('', 'var x=i4(1,2,3,4); var c=0; c=e(x,3)|0; x=i4(c,c,c,c)', [4, 4, 4, 4]);
+CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(0); y=e(x,2); x=f4(y,y,y,y)', [3, 3, 3, 3]);
+CheckI4('', 'var x=i4(1,2,3,4); var c=0; var d=0; c=e(x,3)|0; d=e(x,3)|0; x=i4(c,d,d,c)', [4, 4, 4, 4]);
+CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(0); var z=f32(0); y=e(x,2); z=e(x,2); x=f4(y,z,y,z)', [3, 3, 3, 3]);
+
+// Uses in ternary conditionals
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; c=x?c:c;} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=1?x:c;} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=1?c:x;} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "function f() {var x=f4(1,2,3,4); var y=i4(1,2,3,4); x=1?x:y;} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "function f() {var x=f4(1,2,3,4); var y=i4(1,2,3,4); x=1?y:y;} return f");
+assertAsmTypeFail('glob', USE_ASM + B32 + I32 + "function f() {var x=b4(1,2,3,4); var y=i4(1,2,3,4); x=1?y:y;} return f");
+assertAsmTypeFail('glob', USE_ASM + U32 + I32 + "function f() {var x=u4(1,2,3,4); var y=i4(1,2,3,4); x=1?y:y;} return f");
+assertAsmTypeFail('glob', USE_ASM + U32 + I32 + "function f() {var x=i4(1,2,3,4); var y=u4(1,2,3,4); x=1?y:y;} return f");
+
+CheckF4('', 'var x=f4(1,2,3,4); var y=f4(4,3,2,1); x=3?y:x', [4, 3, 2, 1]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=x|0; var v=f4(1,2,3,4); var w=f4(5,6,7,8); return cf4(x?w:v);} return f"), this)(1), [5,6,7,8]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(v) {v=cf4(v); var w=f4(5,6,7,8); return cf4(4?w:v);} return f"), this)(SIMD.Float32x4(1,2,3,4)), [5,6,7,8]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(v, x) {v=cf4(v); x=x|0; var w=f4(5,6,7,8); return cf4(x?w:v);} return f"), this)(SIMD.Float32x4(1,2,3,4), 0), [1,2,3,4]);
+
+CheckI4('', 'var x=i4(1,2,3,4); var y=i4(4,3,2,1); x=e(x,0)?y:x', [4, 3, 2, 1]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=x|0; var v=i4(1,2,3,4); var w=i4(5,6,7,8); return ci4(x?w:v);} return f"), this)(1), [5,6,7,8]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(v) {v=ci4(v); var w=i4(5,6,7,8); return ci4(4?w:v);} return f"), this)(SIMD.Int32x4(1,2,3,4)), [5,6,7,8]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(v, x) {v=ci4(v); x=x|0; var w=i4(5,6,7,8); return ci4(x?w:v);} return f"), this)(SIMD.Int32x4(1,2,3,4), 0), [1,2,3,4]);
+
+// Unsigned SIMD types can't be function arguments or return values.
+assertAsmTypeFail('glob', USE_ASM + U32 + CU32 + "function f(x) {x=cu4(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + U32 + CU32 + "function f() {x=u4(0,0,0,0); return cu4(x);} return f");
+
+// 1.3.4 Return values
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {var x=1; return ci4(x)} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {var x=1; return ci4(x + x)} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {var x=1.; return ci4(x)} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + "function f() {var x=f32(1.); return ci4(x)} return f");
+
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f() {var x=i4(1,2,3,4); return ci4(x)} return f"), this)(), [1,2,3,4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f() {var x=f4(1,2,3,4); return cf4(x)} return f"), this)(), [1,2,3,4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + "function f() {var x=b4(1,2,0,4); return cb4(x)} return f"), this)(), [true,true,false,true]);
+
+// 1.3.5 Coerce and pass arguments
+// Via check
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {ci4();} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); ci4(x, x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {ci4(1);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {ci4(1.);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + "function f() {ci4(f32(1.));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + CF32 + "function f(x) {x=cf4(x); ci4(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return 1 + ci4(x) | 0;} return f");
+
+var i32x4 = SIMD.Int32x4(1, 3, 3, 7);
+assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x)} return f"), this)(i32x4), undefined);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return ci4(x);} return f"), this)(i32x4), [1,3,3,7]);
+
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f() {cf4();} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); cf4(x, x);} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f() {cf4(1);} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f() {cf4(1.);} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + FROUND + "function f() {cf4(f32(1.));} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + F32 + CF32 + "function f(x) {x=cf4(x); cf4(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return 1 + cf4(x) | 0;} return f");
+
+var f32x4 = SIMD.Float32x4(13.37, 42.42, -0, NaN);
+assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x)} return f"), this)(f32x4), undefined);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return cf4(x);} return f"), this)(f32x4), [13.37, 42.42, -0, NaN].map(Math.fround));
+
+var b32x4 = SIMD.Bool32x4(true, false, false, true);
+assertEq(asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + "function f(x) {x=cb4(x)} return f"), this)(b32x4), undefined);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + "function f(x) {x=cb4(x); return cb4(x);} return f"), this)(b32x4), [true, false, false, true]);
+
+// Legacy coercions
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4();} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4(1,2,3,4);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x,y) {x=i4(y);y=+y} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return i4(x);} return f");
+
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {return +i4(1,2,3,4)} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {return 0|i4(1,2,3,4)} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f(x) {return f32(i4(1,2,3,4))} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f(x) {return f4(i4(1,2,3,4))} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return f4(x);} return f");
+
+
+function assertCaught(f) {
+ var caught = false;
+ try {
+ f.apply(null, Array.prototype.slice.call(arguments, 1));
+ } catch (e) {
+ DEBUG && print('Assert caught: ', e, '\n', e.stack);
+ assertEq(e instanceof TypeError, true);
+ caught = true;
+ }
+ assertEq(caught, true);
+}
+
+var f = asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return cf4(x);} return f"), this);
+assertCaught(f);
+assertCaught(f, 1);
+assertCaught(f, {});
+assertCaught(f, "I sincerely am a SIMD typed object.");
+assertCaught(f, SIMD.Int32x4(1,2,3,4));
+assertCaught(f, SIMD.Bool32x4(true, true, false, true));
+
+var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return ci4(x);} return f"), this);
+assertCaught(f);
+assertCaught(f, 1);
+assertCaught(f, {});
+assertCaught(f, "I sincerely am a SIMD typed object.");
+assertCaught(f, SIMD.Float32x4(4,3,2,1));
+assertCaught(f, SIMD.Bool32x4(true, true, false, true));
+
+var f = asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + "function f(x) {x=cb4(x); return cb4(x);} return f"), this);
+assertCaught(f);
+assertCaught(f, 1);
+assertCaught(f, {});
+assertCaught(f, "I sincerely am a SIMD typed object.");
+assertCaught(f, SIMD.Int32x4(1,2,3,4));
+assertCaught(f, SIMD.Float32x4(4,3,2,1));
+
+// 1.3.6 Globals
+// 1.3.6.1 Local globals
+// Read
+assertAsmTypeFail('glob', USE_ASM + I32 + "var g=i4(1,2,3,4); function f() {var x=4; x=g|0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var g=i4(1,2,3,4); function f() {var x=4.; x=+g;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var g=i4(1,2,3,4); var f32=glob.Math.fround; function f() {var x=f32(4.); x=f32(g);} return f");
+
+assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f() {var x=4; x=g|0;} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f() {var x=4.; x=+g;} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); var f32=glob.Math.fround; function f() {var x=f32(4.); x=f32(g);} return f");
+
+assertAsmTypeFail('glob', USE_ASM + F32 + I32 + CI32 + "var g=f4(1., 2., 3., 4.); function f() {var x=i4(1,2,3,4); x=ci4(g);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + "var g=i4(1,2,3,4); function f() {var x=f4(1.,2.,3.,4.); x=cf4(g);} return f");
+assertAsmTypeFail('glob', USE_ASM + U32 + I32 + CI32 + "var g=u4(1,2,3,4); function f() {var x=i4(1,2,3,4); x=ci4(g);} return f");
+
+assertAsmTypeFail('glob', USE_ASM + I32 + "var g=0; function f() {var x=i4(1,2,3,4); x=g|0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var g=0.; function f() {var x=i4(1,2,3,4); x=+g;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var f32=glob.Math.fround; var g=f32(0.); function f() {var x=i4(1,2,3,4); x=f32(g);} return f");
+
+// Unsigned SIMD globals are not allowed.
+assertAsmTypeFail('glob', USE_ASM + U32 + "var g=u4(0,0,0,0); function f() {var x=u4(1,2,3,4); x=g;} return f");
+
+assertAsmTypeFail('glob', USE_ASM + F32 + "var g=0; function f() {var x=f4(0.,0.,0.,0.); x=g|0;} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "var g=0.; function f() {var x=f4(0.,0.,0.,0.); x=+g;} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "var f32=glob.Math.fround; var g=f32(0.); function f() {var x=f4(0.,0.,0.,0.); x=f32(g);} return f");
+
+CheckI4('var x=i4(1,2,3,4)', '', [1, 2, 3, 4]);
+CheckI4('var _=42; var h=i4(5,5,5,5); var __=13.37; var x=i4(4,7,9,2);', '', [4,7,9,2]);
+
+CheckF4('var x=f4(1.,2.,3.,4.)', '', [1, 2, 3, 4]);
+CheckF4('var _=42; var h=f4(5.,5.,5.,5.); var __=13.37; var x=f4(4.,13.37,9.,-0.);', '', [4, 13.37, 9, -0]);
+CheckF4('var x=f4(1,2,3,4)', '', [1, 2, 3, 4]);
+
+CheckB4('var x=b4(1,0,3,0)', '', [true, false, true, false]);
+CheckB4('var _=42; var h=b4(5,0,5,5); var __=13.37; var x=b4(0,0,9,2);', '', [false, false, true, true]);
+
+// Write
+assertAsmTypeFail('glob', USE_ASM + I32 + "var g=i4(1,2,3,4); function f() {var x=4; g=x|0;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var g=i4(1,2,3,4); function f() {var x=4.; g=+x;} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var g=i4(1,2,3,4); var f32=glob.Math.fround; function f() {var x=f32(4.); g=f32(x);} return f");
+
+assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f() {var x=4; g=x|0;} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f() {var x=4.; g=+x;} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); var f32=glob.Math.fround; function f() {var x=f32(4.); g=f32(x);} return f");
+
+assertAsmTypeFail('glob', USE_ASM + F32 + I32 + CI32 + "var g=f4(1., 2., 3., 4.); function f() {var x=i4(1,2,3,4); g=ci4(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + I32 + CF32 + "var g=f4(1., 2., 3., 4.); function f() {var x=i4(1,2,3,4); g=cf4(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + "var g=i4(1,2,3,4); function f() {var x=f4(1.,2.,3.,4.); g=cf4(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CI32 + "var g=i4(1,2,3,4); function f() {var x=f4(1.,2.,3.,4.); g=ci4(x);} return f");
+
+CheckI4('var x=i4(0,0,0,0);', 'x=i4(1,2,3,4)', [1,2,3,4]);
+CheckF4('var x=f4(0.,0.,0.,0.);', 'x=f4(5.,3.,4.,2.)', [5,3,4,2]);
+CheckB4('var x=b4(0,0,0,0);', 'x=b4(0,0,1,1)', [false, false, true, true]);
+
+CheckI4('var x=i4(0,0,0,0); var y=42; var z=3.9; var w=13.37', 'x=i4(1,2,3,4); y=24; z=4.9; w=23.10;', [1,2,3,4]);
+CheckF4('var x=f4(0,0,0,0); var y=42; var z=3.9; var w=13.37', 'x=f4(1,2,3,4); y=24; z=4.9; w=23.10;', [1,2,3,4]);
+CheckB4('var x=b4(0,0,0,0); var y=42; var z=3.9; var w=13.37', 'x=b4(1,0,0,0); y=24; z=4.9; w=23.10;', [true, false, false, false]);
+
+// 1.3.6.2 Imported globals
+// Read
+var Int32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {return ci4(g)} return f"), this, {g: SIMD.Int32x4(1,2,3,4)})();
+assertEq(SIMD.Int32x4.extractLane(Int32x4, 0), 1);
+assertEq(SIMD.Int32x4.extractLane(Int32x4, 1), 2);
+assertEq(SIMD.Int32x4.extractLane(Int32x4, 2), 3);
+assertEq(SIMD.Int32x4.extractLane(Int32x4, 3), 4);
+
+for (var v of [1, {}, "totally legit SIMD variable", SIMD.Float32x4(1,2,3,4)])
+ assertCaught(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {return ci4(g)} return f"), this, {g: v});
+
+// Unsigned SIMD globals are not allowed.
+assertAsmTypeFail('glob', 'ffi', USE_ASM + U32 + CU32 + "var g=cu4(ffi.g); function f() {} return f");
+
+var Float32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {return cf4(g)} return f"), this, {g: SIMD.Float32x4(1,2,3,4)})();
+assertEq(SIMD.Float32x4.extractLane(Float32x4, 0), 1);
+assertEq(SIMD.Float32x4.extractLane(Float32x4, 1), 2);
+assertEq(SIMD.Float32x4.extractLane(Float32x4, 2), 3);
+assertEq(SIMD.Float32x4.extractLane(Float32x4, 3), 4);
+
+for (var v of [1, {}, "totally legit SIMD variable", SIMD.Int32x4(1,2,3,4)])
+ assertCaught(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {return cf4(g)} return f"), this, {g: v});
+
+var Bool32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + B32 + CB32 + "var g=cb4(ffi.g); function f() {return cb4(g)} return f"), this, {g: SIMD.Bool32x4(false, false, false, true)})();
+assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 0), false);
+assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 1), false);
+assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 2), false);
+assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 3), true);
+
+for (var v of [1, {}, "totally legit SIMD variable", SIMD.Int32x4(1,2,3,4)])
+ assertCaught(asmCompile('glob', 'ffi', USE_ASM + B32 + CB32 + "var g=cb4(ffi.g); function f() {return cb4(g)} return f"), this, {g: v});
+
+// Write
+var Int32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {g=i4(4,5,6,7); return ci4(g)} return f"), this, {g: SIMD.Int32x4(1,2,3,4)})();
+assertEq(SIMD.Int32x4.extractLane(Int32x4, 0), 4);
+assertEq(SIMD.Int32x4.extractLane(Int32x4, 1), 5);
+assertEq(SIMD.Int32x4.extractLane(Int32x4, 2), 6);
+assertEq(SIMD.Int32x4.extractLane(Int32x4, 3), 7);
+
+var Float32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {g=f4(4.,5.,6.,7.); return cf4(g)} return f"), this, {g: SIMD.Float32x4(1,2,3,4)})();
+assertEq(SIMD.Float32x4.extractLane(Float32x4, 0), 4);
+assertEq(SIMD.Float32x4.extractLane(Float32x4, 1), 5);
+assertEq(SIMD.Float32x4.extractLane(Float32x4, 2), 6);
+assertEq(SIMD.Float32x4.extractLane(Float32x4, 3), 7);
+
+var Bool32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + B32 + CB32 + "var g=cb4(ffi.g); function f() {g=b4(1,1,0,0); return cb4(g)} return f"), this, {g: SIMD.Bool32x4(1,1,1,0)})();
+assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 0), true);
+assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 1), true);
+assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 2), false);
+assertEq(SIMD.Bool32x4.extractLane(Bool32x4, 3), false);
+
+// 2. SIMD operations
+// 2.1 Compilation
+assertAsmTypeFail('glob', USE_ASM + "var add = Int32x4.add; return {}");
+assertAsmTypeFail('glob', USE_ASM + I32A + I32 + "return {}");
+assertAsmTypeFail('glob', USE_ASM + "var g = 3; var add = g.add; return {}");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var func = i4.doTheHarlemShake; return {}");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var div = i4.div; return {}");
+assertAsmTypeFail('glob', USE_ASM + "var f32 = glob.Math.fround; var i4a = f32.add; return {}");
+// Operation exists, but in a different type.
+assertAsmTypeFail('glob', USE_ASM + I32 + "var func = i4.fromUint32x4; return {}");
+
+// 2.2 Linking
+assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + I32 + I32A + "function f() {} return f"), {});
+assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + I32 + I32A + "function f() {} return f"), {SIMD: Math.fround});
+
+var oldInt32x4Add = SIMD.Int32x4.add;
+var code = asmCompile('glob', USE_ASM + I32 + I32A + "return {}");
+for (var v of [42, Math.fround, SIMD.Float32x4.add, function(){}, SIMD.Int32x4.mul]) {
+ SIMD.Int32x4.add = v;
+ assertAsmLinkFail(code, {SIMD: {Int32x4: SIMD.Int32x4}});
+}
+SIMD.Int32x4.add = oldInt32x4Add; // finally replace the add function with the original one
+assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + I32A + "function f() {} return f"), {SIMD: {Int32x4: SIMD.Int32x4}})(), undefined);
+
+// 2.3. Binary arithmetic operations
+// 2.3.1 Additions
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a();} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a(x, x, x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a(13, 37);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a(23.10, 19.89);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a(x, 42);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4a(x, 13.37);} return f");
+
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); var y=4; x=i4a(x, y);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(0,0,0,0); var y=4; x=i4a(y, y);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(0,0,0,0); var y=4; y=i4a(x, x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + U32 + "function f() {var x=i4(0,0,0,0); var y=u4(1,2,3,4); y=i4a(x, y);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); x=i4a(x, y);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); y=i4a(x, y);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); y=i4a(x, x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); y=f4a(x, x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); y=f4a(x, y);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); x=f4a(y, y);} return f");
+
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + 'function f() {var x=i4(1,2,3,4); var y=0; y=i4a(x,x)|0} return f');
+assertAsmTypeFail('glob', USE_ASM + I32 + I32A + 'function f() {var x=i4(1,2,3,4); var y=0.; y=+i4a(x,x)} return f');
+
+CheckI4(I32A, 'var z=i4(1,2,3,4); var y=i4(0,1,0,3); var x=i4(0,0,0,0); x=i4a(z,y)', [1,3,3,7]);
+CheckI4(I32A, 'var x=i4(2,3,4,5); var y=i4(0,1,0,3); x=i4a(x,y)', [2,4,4,8]);
+CheckI4(I32A, 'var x=i4(1,2,3,4); x=i4a(x,x)', [2,4,6,8]);
+CheckI4(I32A, 'var x=i4(' + INT32_MAX + ',2,3,4); var y=i4(1,1,0,3); x=i4a(x,y)', [INT32_MIN,3,3,7]);
+CheckI4(I32A, 'var x=i4(' + INT32_MAX + ',2,3,4); var y=i4(1,1,0,3); x=ci4(i4a(x,y))', [INT32_MIN,3,3,7]);
+
+CheckU4(U32A, 'var z=u4(1,2,3,4); var y=u4(0,1,0,3); var x=u4(0,0,0,0); x=u4a(z,y)', [1,3,3,7]);
+CheckU4(U32A, 'var x=u4(2,3,4,5); var y=u4(0,1,0,3); x=u4a(x,y)', [2,4,4,8]);
+CheckU4(U32A, 'var x=u4(1,2,3,4); x=u4a(x,x)', [2,4,6,8]);
+
+CheckF4(F32A, 'var x=f4(1,2,3,4); x=f4a(x,x)', [2,4,6,8]);
+CheckF4(F32A, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4a(x,y)', [5,5,8,6]);
+CheckF4(F32A, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4a(x,y)', [Math.fround(13.37) + 4,5,8,6]);
+CheckF4(F32A, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=cf4(f4a(x,y))', [Math.fround(13.37) + 4,5,8,6]);
+
+// 2.3.2. Subtracts
+CheckI4(I32S, 'var x=i4(1,2,3,4); var y=i4(-1,1,0,2); x=i4s(x,y)', [2,1,3,2]);
+CheckI4(I32S, 'var x=i4(5,4,3,2); var y=i4(1,2,3,4); x=i4s(x,y)', [4,2,0,-2]);
+CheckI4(I32S, 'var x=i4(1,2,3,4); x=i4s(x,x)', [0,0,0,0]);
+CheckI4(I32S, 'var x=i4(' + INT32_MIN + ',2,3,4); var y=i4(1,1,0,3); x=i4s(x,y)', [INT32_MAX,1,3,1]);
+CheckI4(I32S, 'var x=i4(' + INT32_MIN + ',2,3,4); var y=i4(1,1,0,3); x=ci4(i4s(x,y))', [INT32_MAX,1,3,1]);
+
+CheckU4(U32S, 'var x=u4(1,2,3,4); var y=u4(-1,1,0,2); x=u4s(x,y)', [2,1,3,2]);
+CheckU4(U32S, 'var x=u4(5,4,3,2); var y=u4(1,2,3,4); x=u4s(x,y)', [4,2,0,-2>>>0]);
+CheckU4(U32S, 'var x=u4(1,2,3,4); x=u4s(x,x)', [0,0,0,0]);
+CheckU4(U32S, 'var x=u4(' + INT32_MIN + ',2,3,4); var y=u4(1,1,0,3); x=u4s(x,y)', [INT32_MAX,1,3,1]);
+CheckU4(U32S, 'var x=u4(' + INT32_MIN + ',2,3,4); var y=u4(1,1,0,3); x=cu4(u4s(x,y))', [INT32_MAX,1,3,1]);
+
+CheckF4(F32S, 'var x=f4(1,2,3,4); x=f4s(x,x)', [0,0,0,0]);
+CheckF4(F32S, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4s(x,y)', [-3,-1,-2,2]);
+CheckF4(F32S, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4s(x,y)', [Math.fround(13.37) - 4,-1,-2,2]);
+CheckF4(F32S, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=cf4(f4s(x,y))', [Math.fround(13.37) - 4,-1,-2,2]);
+
+{
+ // Bug 1216099
+ let code = `
+ "use asm";
+ var f4 = global.SIMD.Float32x4;
+ var f4sub = f4.sub;
+ const zerox4 = f4(0.0, 0.0, 0.0, 0.0);
+ function f() {
+ var newVelx4 = f4(0.0, 0.0, 0.0, 0.0);
+ var newVelTruex4 = f4(0.0,0.0,0.0,0.0);
+ newVelTruex4 = f4sub(zerox4, newVelx4);
+ }
+ // return statement voluntarily missing
+ `;
+ assertAsmTypeFail('global', code);
+}
+
+// 2.3.3. Multiplications / Divisions
+assertAsmTypeFail('glob', USE_ASM + I32 + "var f4d=i4.div; function f() {} return f");
+
+CheckI4(I32M, 'var x=i4(1,2,3,4); var y=i4(-1,1,0,2); x=i4m(x,y)', [-1,2,0,8]);
+CheckI4(I32M, 'var x=i4(5,4,3,2); var y=i4(1,2,3,4); x=i4m(x,y)', [5,8,9,8]);
+CheckI4(I32M, 'var x=i4(1,2,3,4); x=i4m(x,x)', [1,4,9,16]);
+(function() {
+ var m = INT32_MIN, M = INT32_MAX, imul = Math.imul;
+ CheckI4(I32M, `var x=i4(${m},${m}, ${M}, ${M}); var y=i4(2,-3,4,-5); x=i4m(x,y)`,
+ [imul(m, 2), imul(m, -3), imul(M, 4), imul(M, -5)]);
+ CheckI4(I32M, `var x=i4(${m},${m}, ${M}, ${M}); var y=i4(${m}, ${M}, ${m}, ${M}); x=i4m(x,y)`,
+ [imul(m, m), imul(m, M), imul(M, m), imul(M, M)]);
+})();
+
+CheckF4(F32M, 'var x=f4(1,2,3,4); x=f4m(x,x)', [1,4,9,16]);
+CheckF4(F32M, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4m(x,y)', [4,6,15,8]);
+CheckF4(F32M, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4m(x,y)', [Math.fround(13.37) * 4,6,15,8]);
+CheckF4(F32M, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=cf4(f4m(x,y))', [Math.fround(13.37) * 4,6,15,8]);
+
+var f32x4 = SIMD.Float32x4(0, NaN, -0, NaN);
+var another = SIMD.Float32x4(NaN, -1, -0, NaN);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32M + CF32 + "function f(x, y) {x=cf4(x); y=cf4(y); x=f4m(x,y); return cf4(x);} return f"), this)(f32x4, another), [NaN, NaN, 0, NaN]);
+
+CheckF4(F32D, 'var x=f4(1,2,3,4); x=f4d(x,x)', [1,1,1,1]);
+CheckF4(F32D, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4d(x,y)', [1/4,2/3,3/5,2]);
+CheckF4(F32D, 'var x=f4(13.37,1,1,4); var y=f4(4,0,-0.,2); x=f4d(x,y)', [Math.fround(13.37) / 4,+Infinity,-Infinity,2]);
+
+var f32x4 = SIMD.Float32x4(0, 0, -0, NaN);
+var another = SIMD.Float32x4(0, -0, 0, 0);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32D + CF32 + "function f(x,y) {x=cf4(x); y=cf4(y); x=f4d(x,y); return cf4(x);} return f"), this)(f32x4, another), [NaN, NaN, NaN, NaN]);
+
+// Unary arithmetic operators
+function CheckUnaryF4(op, checkFunc, assertFunc) {
+ var _ = asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + 'var op=f4.' + op + '; function f(x){x=cf4(x); return cf4(op(x)); } return f'), this);
+ return function(input) {
+ var simd = SIMD.Float32x4(input[0], input[1], input[2], input[3]);
+
+ var exp = input.map(Math.fround).map(checkFunc).map(Math.fround);
+ var obs = _(simd);
+ assertEqX4(obs, exp, assertFunc);
+ }
+}
+
+function CheckUnaryI4(op, checkFunc) {
+ var _ = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + 'var op=i4.' + op + '; function f(x){x=ci4(x); return ci4(op(x)); } return f'), this);
+ return function(input) {
+ var simd = SIMD.Int32x4(input[0], input[1], input[2], input[3]);
+ assertEqX4(_(simd), input.map(checkFunc).map(function(x) { return x | 0}));
+ }
+}
+
+function CheckUnaryU4(op, checkFunc) {
+ var _ = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32U32 + U32 + U32I32 +
+ 'var op=u4.' + op + '; function f(x){x=ci4(x); return ci4(i4u4(op(u4i4(x)))); } return f'), this);
+ return function(input) {
+ var simd = SIMD.Int32x4(input[0], input[1], input[2], input[3]);
+ var res = SIMD.Uint32x4.fromInt32x4Bits(_(simd));
+ assertEqX4(res, input.map(checkFunc).map(function(x) { return x >>> 0 }));
+ }
+}
+
+function CheckUnaryB4(op, checkFunc) {
+ var _ = asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + 'var op=b4.' + op + '; function f(x){x=cb4(x); return cb4(op(x)); } return f'), this);
+ return function(input) {
+ var simd = SIMD.Bool32x4(input[0], input[1], input[2], input[3]);
+ assertEqX4(_(simd), input.map(checkFunc).map(function(x) { return !!x}));
+ }
+}
+
+CheckUnaryI4('neg', function(x) { return -x })([1, -2, INT32_MIN, INT32_MAX]);
+CheckUnaryI4('not', function(x) { return ~x })([1, -2, INT32_MIN, INT32_MAX]);
+
+CheckUnaryU4('neg', function(x) { return -x })([1, -2, INT32_MIN, INT32_MAX]);
+CheckUnaryU4('not', function(x) { return ~x })([1, -2, INT32_MIN, INT32_MAX]);
+
+var CheckNotB = CheckUnaryB4('not', function(x) { return !x });
+CheckNotB([true, false, true, true]);
+CheckNotB([true, true, true, true]);
+CheckNotB([false, false, false, false]);
+
+var CheckAbs = CheckUnaryF4('abs', Math.abs);
+CheckAbs([1, 42.42, 0.63, 13.37]);
+CheckAbs([NaN, -Infinity, Infinity, 0]);
+
+var CheckNegF = CheckUnaryF4('neg', function(x) { return -x });
+CheckNegF([1, 42.42, 0.63, 13.37]);
+CheckNegF([NaN, -Infinity, Infinity, 0]);
+
+var CheckSqrt = CheckUnaryF4('sqrt', function(x) { return Math.sqrt(x); });
+CheckSqrt([1, 42.42, 0.63, 13.37]);
+CheckSqrt([NaN, -Infinity, Infinity, 0]);
+
+// ReciprocalApproximation and reciprocalSqrtApproximation give approximate results
+function assertNear(a, b) {
+ if (a !== a && b === b)
+ throw 'Observed NaN, expected ' + b;
+ if (Math.abs(a - b) > 1e-3)
+ throw 'More than 1e-3 between ' + a + ' and ' + b;
+}
+var CheckRecp = CheckUnaryF4('reciprocalApproximation', function(x) { return 1 / x; }, assertNear);
+CheckRecp([1, 42.42, 0.63, 13.37]);
+CheckRecp([NaN, -Infinity, Infinity, 0]);
+
+var CheckRecp = CheckUnaryF4('reciprocalSqrtApproximation', function(x) { return 1 / Math.sqrt(x); }, assertNear);
+CheckRecp([1, 42.42, 0.63, 13.37]);
+CheckRecp([NaN, -Infinity, Infinity, 0]);
+
+// Min/Max
+assertAsmTypeFail('glob', USE_ASM + I32 + "var f4m=i4.min; function f() {} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var f4d=i4.max; function f() {} return f");
+
+const F32MIN = 'var min = f4.min;'
+const F32MAX = 'var max = f4.max;'
+
+CheckF4(F32MIN, 'var x=f4(1,2,3,4); x=min(x,x)', [1,2,3,4]);
+CheckF4(F32MIN, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=min(x,y)', [4,2,3,2]);
+CheckF4(F32MIN + FROUND + 'var Infinity = glob.Infinity;', 'var x=f4(0,0,0,0); var y=f4(2310,3,5,0); x=f4(f32(+Infinity),f32(-Infinity),f32(3),f32(-0.)); x=min(x,y)', [2310,-Infinity,3,-0]);
+
+CheckF4(F32MIN, 'var x=f4(0,0,-0,-0); var y=f4(0,-0,0,-0); x=min(x,y)', [0,-0,-0,-0]);
+CheckF4(F32MIN + FROUND + 'var NaN = glob.NaN;', 'var x=f4(0,0,0,0); var y=f4(0,0,0,0); var n=f32(0); n=f32(NaN); x=f4(n,0.,n,0.); y=f4(n,n,0.,0.); x=min(x,y)', [NaN, NaN, NaN, 0]);
+
+CheckF4(F32MAX, 'var x=f4(1,2,3,4); x=max(x,x)', [1,2,3,4]);
+CheckF4(F32MAX, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=max(x,y)', [13.37, 3, 5, 4]);
+CheckF4(F32MAX + FROUND + 'var Infinity = glob.Infinity;', 'var x=f4(0,0,0,0); var y=f4(2310,3,5,0); x=f4(f32(+Infinity),f32(-Infinity),f32(3),f32(-0.)); x=max(x,y)', [+Infinity,3,5,0]);
+
+CheckF4(F32MAX, 'var x=f4(0,0,-0,-0); var y=f4(0,-0,0,-0); x=max(x,y)', [0,0,0,-0]);
+CheckF4(F32MAX + FROUND + 'var NaN = glob.NaN;', 'var x=f4(0,0,0,0); var y=f4(0,0,0,0); var n=f32(0); n=f32(NaN); x=f4(n,0.,n,0.); y=f4(n,n,0.,0.); x=max(x,y)', [NaN, NaN, NaN, 0]);
+
+const F32MINNUM = 'var min = f4.minNum;'
+const F32MAXNUM = 'var max = f4.maxNum;'
+
+CheckF4(F32MINNUM, 'var x=f4(1,2,3,4); x=min(x,x)', [1,2,3,4]);
+CheckF4(F32MINNUM, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=min(x,y)', [4,2,3,2]);
+CheckF4(F32MINNUM + FROUND + 'var Infinity = glob.Infinity;', 'var x=f4(0,0,0,0); var y=f4(2310,3,5,0); x=f4(f32(+Infinity),f32(-Infinity),f32(3),f32(-0.)); x=min(x,y)', [2310,-Infinity,3,-0]);
+
+CheckF4(F32MINNUM, 'var x=f4(0,0,-0,-0); var y=f4(0,-0,0,-0); x=min(x,y)', [0,-0,-0,-0]);
+CheckF4(F32MINNUM + FROUND + 'var NaN = glob.NaN;', 'var x=f4(0,0,0,0); var y=f4(0,0,0,0); var n=f32(0); n=f32(NaN); x=f4(n,0.,n,0.); y=f4(n,n,0.,0.); x=min(x,y)', [NaN, 0, 0, 0]);
+
+CheckF4(F32MAXNUM, 'var x=f4(1,2,3,4); x=max(x,x)', [1,2,3,4]);
+CheckF4(F32MAXNUM, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=max(x,y)', [13.37, 3, 5, 4]);
+CheckF4(F32MAXNUM + FROUND + 'var Infinity = glob.Infinity;', 'var x=f4(0,0,0,0); var y=f4(2310,3,5,0); x=f4(f32(+Infinity),f32(-Infinity),f32(3),f32(-0.)); x=max(x,y)', [+Infinity,3,5,0]);
+
+CheckF4(F32MAXNUM, 'var x=f4(0,0,-0,-0); var y=f4(0,-0,0,-0); x=max(x,y)', [0,0,0,-0]);
+CheckF4(F32MAXNUM + FROUND + 'var NaN = glob.NaN;', 'var x=f4(0,0,0,0); var y=f4(0,0,0,0); var n=f32(0); n=f32(NaN); x=f4(n,0.,n,0.); y=f4(n,n,0.,0.); x=max(x,y)', [NaN, 0, 0, 0]);
+
+// ReplaceLane
+const RLF = 'var r = f4.replaceLane;';
+
+assertAsmTypeFail('glob', USE_ASM + F32 + RLF + "function f() {var x = f4(1,2,3,4); x = r(x, 0, 1);} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + RLF + "function f() {var x = f4(1,2,3,4); x = r(x, 0, x);} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(x, 4, f32(1));} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(x, f32(0), f32(1));} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(1, 0, f32(1));} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(1, 0., f32(1));} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(f32(1), 0, f32(1));} return f");
+assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); var l = 0; x = r(x, l, f32(1));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); var y = i4(1,2,3,4); x = r(y, 0, f32(1));} return f");
+
+CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 0, f32(13.37));', [Math.fround(13.37), 2, 3, 4]);
+CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 1, f32(13.37));', [1, Math.fround(13.37), 3, 4]);
+CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 2, f32(13.37));', [1, 2, Math.fround(13.37), 4]);
+CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 3, f32(13.37));', [1, 2, 3, Math.fround(13.37)]);
+CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 3, f32(13.37) + f32(6.63));', [1, 2, 3, Math.fround(Math.fround(13.37) + Math.fround(6.63))]);
+
+CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 0, 13.37);', [Math.fround(13.37), 2, 3, 4]);
+CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 1, 13.37);', [1, Math.fround(13.37), 3, 4]);
+CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 2, 13.37);', [1, 2, Math.fround(13.37), 4]);
+CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 3, 13.37);', [1, 2, 3, Math.fround(13.37)]);
+
+const RLI = 'var r = i4.replaceLane;';
+CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 0, 42);', [42, 2, 3, 4]);
+CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 1, 42);', [1, 42, 3, 4]);
+CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 2, 42);', [1, 2, 42, 4]);
+CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 3, 42);', [1, 2, 3, 42]);
+
+const RLU = 'var r = u4.replaceLane;';
+CheckU4(RLU, 'var x = u4(1,2,3,4); x = r(x, 0, 42);', [42, 2, 3, 4]);
+CheckU4(RLU, 'var x = u4(1,2,3,4); x = r(x, 1, 42);', [1, 42, 3, 4]);
+CheckU4(RLU, 'var x = u4(1,2,3,4); x = r(x, 2, 42);', [1, 2, 42, 4]);
+CheckU4(RLU, 'var x = u4(1,2,3,4); x = r(x, 3, 42);', [1, 2, 3, 42]);
+
+const RLB = 'var r = b4.replaceLane;';
+CheckB4(RLB, 'var x = b4(1,1,0,0); x = r(x, 0, 0);', [false, true, false, false]);
+CheckB4(RLB, 'var x = b4(1,1,0,0); x = r(x, 1, 0);', [true, false, false, false]);
+CheckB4(RLB, 'var x = b4(1,1,0,0); x = r(x, 2, 2);', [true, true, true, false]);
+CheckB4(RLB, 'var x = b4(1,1,0,0); x = r(x, 3, 1);', [true, true, false, true]);
+
+// Comparisons
+// Comparison operators produce Bool32x4 vectors.
+const T = true;
+const F = false;
+
+const EQI32 = 'var eq = i4.equal';
+const NEI32 = 'var ne = i4.notEqual';
+const LTI32 = 'var lt = i4.lessThan;';
+const LEI32 = 'var le = i4.lessThanOrEqual';
+const GTI32 = 'var gt = i4.greaterThan;';
+const GEI32 = 'var ge = i4.greaterThanOrEqual';
+
+CheckB4(I32+EQI32, 'var x=b4(0,0,0,0); var a=i4(1,2,3,4); var b=i4(-1,1,0,2); x=eq(a,b)', [F, F, F, F]);
+CheckB4(I32+EQI32, 'var x=b4(0,0,0,0); var a=i4(-1,1,0,2); var b=i4(1,2,3,4); x=eq(a,b)', [F, F, F, F]);
+CheckB4(I32+EQI32, 'var x=b4(0,0,0,0); var a=i4(1,0,3,4); var b=i4(1,1,7,0); x=eq(a,b)', [T, F, F, F]);
+
+CheckB4(I32+NEI32, 'var x=b4(0,0,0,0); var a=i4(1,2,3,4); var b=i4(-1,1,0,2); x=ne(a,b)', [T, T, T, T]);
+CheckB4(I32+NEI32, 'var x=b4(0,0,0,0); var a=i4(-1,1,0,2); var b=i4(1,2,3,4); x=ne(a,b)', [T, T, T, T]);
+CheckB4(I32+NEI32, 'var x=b4(0,0,0,0); var a=i4(1,0,3,4); var b=i4(1,1,7,0); x=ne(a,b)', [F, T, T, T]);
+
+CheckB4(I32+LTI32, 'var x=b4(0,0,0,0); var a=i4(1,2,3,4); var b=i4(-1,1,0,2); x=lt(a,b)', [F, F, F, F]);
+CheckB4(I32+LTI32, 'var x=b4(0,0,0,0); var a=i4(-1,1,0,2); var b=i4(1,2,3,4); x=lt(a,b)', [T, T, T, T]);
+CheckB4(I32+LTI32, 'var x=b4(0,0,0,0); var a=i4(1,0,3,4); var b=i4(1,1,7,0); x=lt(a,b)', [F, T, T, F]);
+
+CheckB4(I32+LEI32, 'var x=b4(0,0,0,0); var a=i4(1,2,3,4); var b=i4(-1,1,0,2); x=le(a,b)', [F, F, F, F]);
+CheckB4(I32+LEI32, 'var x=b4(0,0,0,0); var a=i4(-1,1,0,2); var b=i4(1,2,3,4); x=le(a,b)', [T, T, T, T]);
+CheckB4(I32+LEI32, 'var x=b4(0,0,0,0); var a=i4(1,0,3,4); var b=i4(1,1,7,0); x=le(a,b)', [T, T, T, F]);
+
+CheckB4(I32+GTI32, 'var x=b4(0,0,0,0); var a=i4(1,2,3,4); var b=i4(-1,1,0,2); x=gt(a,b)', [T, T, T, T]);
+CheckB4(I32+GTI32, 'var x=b4(0,0,0,0); var a=i4(-1,1,0,2); var b=i4(1,2,3,4); x=gt(a,b)', [F, F, F, F]);
+CheckB4(I32+GTI32, 'var x=b4(0,0,0,0); var a=i4(1,0,3,4); var b=i4(1,1,7,0); x=gt(a,b)', [F, F, F, T]);
+
+CheckB4(I32+GEI32, 'var x=b4(0,0,0,0); var a=i4(1,2,3,4); var b=i4(-1,1,0,2); x=ge(a,b)', [T, T, T, T]);
+CheckB4(I32+GEI32, 'var x=b4(0,0,0,0); var a=i4(-1,1,0,2); var b=i4(1,2,3,4); x=ge(a,b)', [F, F, F, F]);
+CheckB4(I32+GEI32, 'var x=b4(0,0,0,0); var a=i4(1,0,3,4); var b=i4(1,1,7,0); x=ge(a,b)', [T, F, F, T]);
+
+const EQU32 = 'var eq = u4.equal';
+const NEU32 = 'var ne = u4.notEqual';
+const LTU32 = 'var lt = u4.lessThan;';
+const LEU32 = 'var le = u4.lessThanOrEqual';
+const GTU32 = 'var gt = u4.greaterThan;';
+const GEU32 = 'var ge = u4.greaterThanOrEqual';
+
+CheckB4(U32+EQU32, 'var x=b4(0,0,0,0); var a=u4(1,2,3,4); var b=u4(-1,1,0,2); x=eq(a,b)', [F, F, F, F]);
+CheckB4(U32+EQU32, 'var x=b4(0,0,0,0); var a=u4(-1,1,0,2); var b=u4(1,2,3,4); x=eq(a,b)', [F, F, F, F]);
+CheckB4(U32+EQU32, 'var x=b4(0,0,0,0); var a=u4(1,0,3,4); var b=u4(1,1,7,0); x=eq(a,b)', [T, F, F, F]);
+
+CheckB4(U32+NEU32, 'var x=b4(0,0,0,0); var a=u4(1,2,3,4); var b=u4(-1,1,0,2); x=ne(a,b)', [T, T, T, T]);
+CheckB4(U32+NEU32, 'var x=b4(0,0,0,0); var a=u4(-1,1,0,2); var b=u4(1,2,3,4); x=ne(a,b)', [T, T, T, T]);
+CheckB4(U32+NEU32, 'var x=b4(0,0,0,0); var a=u4(1,0,3,4); var b=u4(1,1,7,0); x=ne(a,b)', [F, T, T, T]);
+
+CheckB4(U32+LTU32, 'var x=b4(0,0,0,0); var a=u4(1,2,3,4); var b=u4(-1,1,0,2); x=lt(a,b)', [T, F, F, F]);
+CheckB4(U32+LTU32, 'var x=b4(0,0,0,0); var a=u4(-1,1,0,2); var b=u4(1,2,3,4); x=lt(a,b)', [F, T, T, T]);
+CheckB4(U32+LTU32, 'var x=b4(0,0,0,0); var a=u4(1,0,3,4); var b=u4(1,1,7,0); x=lt(a,b)', [F, T, T, F]);
+
+CheckB4(U32+LEU32, 'var x=b4(0,0,0,0); var a=u4(1,2,3,4); var b=u4(-1,1,0,2); x=le(a,b)', [T, F, F, F]);
+CheckB4(U32+LEU32, 'var x=b4(0,0,0,0); var a=u4(-1,1,0,2); var b=u4(1,2,3,4); x=le(a,b)', [F, T, T, T]);
+CheckB4(U32+LEU32, 'var x=b4(0,0,0,0); var a=u4(1,0,3,4); var b=u4(1,1,7,0); x=le(a,b)', [T, T, T, F]);
+
+CheckB4(U32+GTU32, 'var x=b4(0,0,0,0); var a=u4(1,2,3,4); var b=u4(-1,1,0,2); x=gt(a,b)', [F, T, T, T]);
+CheckB4(U32+GTU32, 'var x=b4(0,0,0,0); var a=u4(-1,1,0,2); var b=u4(1,2,3,4); x=gt(a,b)', [T, F, F, F]);
+CheckB4(U32+GTU32, 'var x=b4(0,0,0,0); var a=u4(1,0,3,4); var b=u4(1,1,7,0); x=gt(a,b)', [F, F, F, T]);
+
+CheckB4(U32+GEU32, 'var x=b4(0,0,0,0); var a=u4(1,2,3,4); var b=u4(-1,1,0,2); x=ge(a,b)', [F, T, T, T]);
+CheckB4(U32+GEU32, 'var x=b4(0,0,0,0); var a=u4(-1,1,0,2); var b=u4(1,2,3,4); x=ge(a,b)', [T, F, F, F]);
+CheckB4(U32+GEU32, 'var x=b4(0,0,0,0); var a=u4(1,0,3,4); var b=u4(1,1,7,0); x=ge(a,b)', [T, F, F, T]);
+
+const LTF32 = 'var lt=f4.lessThan;';
+const LEF32 = 'var le=f4.lessThanOrEqual;';
+const GTF32 = 'var gt=f4.greaterThan;';
+const GEF32 = 'var ge=f4.greaterThanOrEqual;';
+const EQF32 = 'var eq=f4.equal;';
+const NEF32 = 'var ne=f4.notEqual;';
+
+assertAsmTypeFail('glob', USE_ASM + F32 + "var lt=f4.lessThan; function f() {var x=f4(1,2,3,4); var y=f4(5,6,7,8); x=lt(x,y);} return f");
+
+CheckB4(F32+LTF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=b4(0,0,0,0); x=lt(y,z)', [F, F, F, F]);
+CheckB4(F32+LTF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=b4(0,0,0,0); x=lt(y,z)', [T, T, T, T]);
+CheckB4(F32+LTF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=b4(0,0,0,0); x=lt(y,z)', [F, T, T, F]);
+CheckB4(F32+LTF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=b4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=lt(y,z);', [F, F, F, F]);
+
+CheckB4(F32+LEF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=b4(0,0,0,0); x=le(y,z)', [F, F, F, F]);
+CheckB4(F32+LEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=b4(0,0,0,0); x=le(y,z)', [T, T, T, T]);
+CheckB4(F32+LEF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=b4(0,0,0,0); x=le(y,z)', [T, T, T, F]);
+CheckB4(F32+LEF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=b4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=le(y,z);', [T, T, F, F]);
+
+CheckB4(F32+EQF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=b4(0,0,0,0); x=eq(y,z)', [F, F, F, F]);
+CheckB4(F32+EQF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=b4(0,0,0,0); x=eq(y,z)', [F, F, F, F]);
+CheckB4(F32+EQF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=b4(0,0,0,0); x=eq(y,z)', [T, F, F, F]);
+CheckB4(F32+EQF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=b4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=eq(y,z);', [T, T, F, F]);
+
+CheckB4(F32+NEF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=b4(0,0,0,0); x=ne(y,z)', [T, T, T, T]);
+CheckB4(F32+NEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=b4(0,0,0,0); x=ne(y,z)', [T, T, T, T]);
+CheckB4(F32+NEF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=b4(0,0,0,0); x=ne(y,z)', [F, T, T, T]);
+CheckB4(F32+NEF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=b4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=ne(y,z);', [F, F, T, T]);
+
+CheckB4(F32+GTF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=b4(0,0,0,0); x=gt(y,z)', [T, T, T, T]);
+CheckB4(F32+GTF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=b4(0,0,0,0); x=gt(y,z)', [F, F, F, F]);
+CheckB4(F32+GTF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=b4(0,0,0,0); x=gt(y,z)', [F, F, F, T]);
+CheckB4(F32+GTF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=b4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=gt(y,z);', [F, F, F, F]);
+
+CheckB4(F32+GEF32, 'var y=f4(1,2,3,4); var z=f4(-1,1,0,2); var x=b4(0,0,0,0); x=ge(y,z)', [T, T, T, T]);
+CheckB4(F32+GEF32, 'var y=f4(-1,1,0,2); var z=f4(1,2,3,4); var x=b4(0,0,0,0); x=ge(y,z)', [F, F, F, F]);
+CheckB4(F32+GEF32, 'var y=f4(1,0,3,4); var z=f4(1,1,7,0); var x=b4(0,0,0,0); x=ge(y,z)', [T, F, F, T]);
+CheckB4(F32+GEF32 + 'const nan = glob.NaN; const fround=glob.Math.fround', 'var y=f4(0,0,0,0); var z=f4(0,0,0,0); var x=b4(0,0,0,0); y=f4(fround(0.0),fround(-0.0),fround(0.0),fround(nan)); z=f4(fround(-0.0),fround(0.0),fround(nan),fround(0.0)); x=ge(y,z);', [T, T, F, F]);
+
+var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + LTI32 + B32 + ANYB4 + 'function f(x){x=ci4(x); var y=i4(-1,0,4,5); var b=b4(0,0,0,0); b=lt(x,y); return anyt(b)|0;} return f'), this);
+assertEq(f(SIMD.Int32x4(1,2,3,4)), 1);
+assertEq(f(SIMD.Int32x4(1,2,4,5)), 0);
+assertEq(f(SIMD.Int32x4(1,2,3,5)), 1);
+
+var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + LTI32 + B32 + ALLB4 + 'function f(x){x=ci4(x); var y=i4(-1,0,4,5); var b=b4(0,0,0,0); b=lt(x,y); return allt(b)|0;} return f'), this);
+assertEq(f(SIMD.Int32x4(-2,-2,3,4)), 1);
+assertEq(f(SIMD.Int32x4(1,2,4,5)), 0);
+assertEq(f(SIMD.Int32x4(1,2,3,5)), 0);
+
+// Conversions operators
+const CVTIF = 'var cvt=f4.fromInt32x4;';
+const CVTFI = 'var cvt=i4.fromFloat32x4;';
+const CVTUF = 'var cvt=f4.fromUint32x4;';
+const CVTFU = 'var cvt=u4.fromFloat32x4;';
+
+assertAsmTypeFail('glob', USE_ASM + I32 + "var cvt=i4.fromInt32x4; return {}");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var cvt=i4.fromUint32x4; return {}");
+assertAsmTypeFail('glob', USE_ASM + U32 + "var cvt=u4.fromInt32x4; return {}");
+assertAsmTypeFail('glob', USE_ASM + U32 + "var cvt=u4.fromUint32x4; return {}");
+assertAsmTypeFail('glob', USE_ASM + F32 + "var cvt=f4.fromFloat32x4; return {}");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIF + "function f() {var x=i4(1,2,3,4); x=cvt(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIF + "function f() {var x=f4(1,2,3,4); x=cvt(x);} return f");
+
+var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + CI32 + CVTIF + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); y=cvt(x); return cf4(y);} return f'), this);
+assertEqX4(f(SIMD.Int32x4(1,2,3,4)), [1, 2, 3, 4]);
+assertEqX4(f(SIMD.Int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, Math.fround(INT32_MIN), Math.fround(INT32_MAX), -1]);
+
+var f = asmLink(asmCompile('glob', USE_ASM + I32 + U32 + U32I32 + F32 + CF32 + CI32 + CVTUF +
+ 'function f(x){x=ci4(x); var y=f4(0,0,0,0); y=cvt(u4i4(x)); return cf4(y);} return f'), this);
+assertEqX4(f(SIMD.Int32x4(1,2,3,4)), [1, 2, 3, 4]);
+assertEqX4(f(SIMD.Int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, Math.fround(INT32_MAX+1), Math.fround(INT32_MAX), Math.fround(UINT32_MAX)]);
+
+var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + F32 + CF32 + CVTFI + 'function f(x){x=cf4(x); var y=i4(0,0,0,0); y=cvt(x); return ci4(y);} return f'), this);
+assertEqX4(f(SIMD.Float32x4(1,2,3,4)), [1, 2, 3, 4]);
+// Test that INT32_MIN (exactly representable as an float32) and the first
+// integer representable as an float32 can be converted.
+assertEqX4(f(SIMD.Float32x4(INT32_MIN, INT32_MAX - 64, -0, 0)), [INT32_MIN, INT32_MAX - 64, 0, 0].map(Math.fround));
+// Test boundaries: first integer less than INT32_MIN and representable as a float32
+assertThrowsInstanceOf(() => f(SIMD.Float32x4(INT32_MIN - 129, 0, 0, 0)), RangeError);
+// INT_MAX + 1
+assertThrowsInstanceOf(() => f(SIMD.Float32x4(Math.pow(2, 31), 0, 0, 0)), RangeError);
+// Special values
+assertThrowsInstanceOf(() => f(SIMD.Float32x4(NaN, 0, 0, 0)), RangeError);
+assertThrowsInstanceOf(() => f(SIMD.Float32x4(Infinity, 0, 0, 0)), RangeError);
+assertThrowsInstanceOf(() => f(SIMD.Float32x4(-Infinity, 0, 0, 0)), RangeError);
+
+var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + U32 + I32U32 + F32 + CF32 + CVTFU +
+ 'function f(x){x=cf4(x); var y=u4(0,0,0,0); y=cvt(x); return ci4(i4u4(y));} return f'), this);
+assertEqX4(f(SIMD.Float32x4(1,2,3,4)), [1, 2, 3, 4]);
+// TODO: Test negative numbers > -1. They should truncate to 0. See https://github.com/tc39/ecmascript_simd/issues/315
+assertEqX4(SIMD.Uint32x4.fromInt32x4Bits(f(SIMD.Float32x4(0xffffff00, INT32_MAX+1, -0, 0))),
+ [0xffffff00, INT32_MAX+1, 0, 0].map(Math.fround));
+// Test boundaries: -1 or less.
+assertThrowsInstanceOf(() => f(SIMD.Float32x4(-1, 0, 0, 0)), RangeError);
+assertThrowsInstanceOf(() => f(SIMD.Float32x4(Math.pow(2, 32), 0, 0, 0)), RangeError);
+// Special values
+assertThrowsInstanceOf(() => f(SIMD.Float32x4(NaN, 0, 0, 0)), RangeError);
+assertThrowsInstanceOf(() => f(SIMD.Float32x4(Infinity, 0, 0, 0)), RangeError);
+assertThrowsInstanceOf(() => f(SIMD.Float32x4(-Infinity, 0, 0, 0)), RangeError);
+
+// Cast operators
+const CVTIFB = 'var cvt=f4.fromInt32x4Bits;';
+const CVTFIB = 'var cvt=i4.fromFloat32x4Bits;';
+
+var cast = (function() {
+ var i32 = new Int32Array(1);
+ var f32 = new Float32Array(i32.buffer);
+
+ function fromInt32Bits(x) {
+ i32[0] = x;
+ return f32[0];
+ }
+
+ function fromFloat32Bits(x) {
+ f32[0] = x;
+ return i32[0];
+ }
+
+ return {
+ fromInt32Bits,
+ fromFloat32Bits
+ }
+})();
+
+assertAsmTypeFail('glob', USE_ASM + I32 + "var cvt=i4.fromInt32x4; return {}");
+assertAsmTypeFail('glob', USE_ASM + F32 + "var cvt=f4.fromFloat32x4; return {}");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIFB + "function f() {var x=i4(1,2,3,4); x=cvt(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIFB + "function f() {var x=f4(1,2,3,4); x=cvt(x);} return f");
+
+var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CVTIFB + CF32 + CI32 + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); y=cvt(x); return cf4(y);} return f'), this);
+assertEqX4(f(SIMD.Int32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromInt32Bits));
+assertEqX4(f(SIMD.Int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, INT32_MIN, INT32_MAX, -1].map(cast.fromInt32Bits));
+
+var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32A + CVTIFB + CF32 + CI32 + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); var z=f4(1,1,1,1); y=cvt(x); y=f4a(y, z); return cf4(y)} return f'), this);
+assertEqX4(f(SIMD.Int32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromInt32Bits).map((x) => x+1));
+assertEqX4(f(SIMD.Int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, INT32_MIN, INT32_MAX, -1].map(cast.fromInt32Bits).map((x) => x+1));
+
+var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + F32 + CF32 + CVTFIB + 'function f(x){x=cf4(x); var y=i4(0,0,0,0); y=cvt(x); return ci4(y);} return f'), this);
+assertEqX4(f(SIMD.Float32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromFloat32Bits));
+assertEqX4(f(SIMD.Float32x4(-0,NaN,+Infinity,-Infinity)), [-0, NaN, +Infinity, -Infinity].map(cast.fromFloat32Bits));
+
+var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + F32 + CF32 + I32A + CVTFIB + 'function f(x){x=cf4(x); var y=i4(0,0,0,0); var z=i4(1,1,1,1); y=cvt(x); y=i4a(y,z); return ci4(y);} return f'), this);
+assertEqX4(f(SIMD.Float32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromFloat32Bits).map((x) => x+1));
+assertEqX4(f(SIMD.Float32x4(-0,NaN,+Infinity,-Infinity)), [-0, NaN, +Infinity, -Infinity].map(cast.fromFloat32Bits).map((x) => x+1));
+
+// Bitwise ops
+const ANDI32 = 'var andd=i4.and;';
+const ORI32 = 'var orr=i4.or;';
+const XORI32 = 'var xorr=i4.xor;';
+
+CheckI4(ANDI32, 'var x=i4(42,1337,-1,13); var y=i4(2, 4, 7, 15); x=andd(x,y)', [42 & 2, 1337 & 4, -1 & 7, 13 & 15]);
+CheckI4(ORI32, ' var x=i4(42,1337,-1,13); var y=i4(2, 4, 7, 15); x=orr(x,y)', [42 | 2, 1337 | 4, -1 | 7, 13 | 15]);
+CheckI4(XORI32, 'var x=i4(42,1337,-1,13); var y=i4(2, 4, 7, 15); x=xorr(x,y)', [42 ^ 2, 1337 ^ 4, -1 ^ 7, 13 ^ 15]);
+
+const ANDU32 = 'var andd=u4.and;';
+const ORU32 = 'var orr=u4.or;';
+const XORU32 = 'var xorr=u4.xor;';
+
+CheckU4(ANDU32, 'var x=u4(42,1337,-1,13); var y=u4(2, 4, 7, 15); x=andd(x,y)', [42 & 2, 1337 & 4, (-1 & 7) >>> 0, 13 & 15]);
+CheckU4(ORU32, ' var x=u4(42,1337,-1,13); var y=u4(2, 4, 7, 15); x=orr(x,y)', [42 | 2, 1337 | 4, (-1 | 7) >>> 0, 13 | 15]);
+CheckU4(XORU32, 'var x=u4(42,1337,-1,13); var y=u4(2, 4, 7, 15); x=xorr(x,y)', [42 ^ 2, 1337 ^ 4, (-1 ^ 7) >>> 0, 13 ^ 15]);
+
+const ANDB32 = 'var andd=b4.and;';
+const ORB32 = 'var orr=b4.or;';
+const XORB32 = 'var xorr=b4.xor;';
+
+CheckB4(ANDB32, 'var x=b4(1,0,1,0); var y=b4(1,1,0,0); x=andd(x,y)', [true, false, false, false]);
+CheckB4(ORB32, ' var x=b4(1,0,1,0); var y=b4(1,1,0,0); x=orr(x,y)', [true, true, true, false]);
+CheckB4(XORB32, 'var x=b4(1,0,1,0); var y=b4(1,1,0,0); x=xorr(x,y)', [false, true, true, false]);
+
+// No bitwise ops on Float32x4.
+const ANDF32 = 'var andd=f4.and;';
+const ORF32 = 'var orr=f4.or;';
+const XORF32 = 'var xorr=f4.xor;';
+const NOTF32 = 'var nott=f4.not;';
+
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + ANDF32 + 'function f() {var x=f4(42, 13.37,-1.42, 23.10); var y=f4(19.89, 2.4, 8.15, 16.36); x=andd(x,y);} return f');
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + ORF32 + 'function f() {var x=f4(42, 13.37,-1.42, 23.10); var y=f4(19.89, 2.4, 8.15, 16.36); x=orr(x,y);} return f');
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + XORF32 + 'function f() {var x=f4(42, 13.37,-1.42, 23.10); var y=f4(19.89, 2.4, 8.15, 16.36); x=xorr(x,y);} return f');
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + NOTF32 + 'function f() {var x=f4(42, 13.37,-1.42, 23.10); x=nott(x);} return f');
+
+// Logical ops
+const LSHI = 'var lsh=i4.shiftLeftByScalar;'
+const RSHI = 'var rsh=i4.shiftRightByScalar;'
+
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + FROUND + LSHI + "function f() {var x=f4(1,2,3,4); return ci4(lsh(x,f32(42)));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + FROUND + LSHI + "function f() {var x=f4(1,2,3,4); return ci4(lsh(x,42));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + LSHI + "function f() {var x=i4(1,2,3,4); return ci4(lsh(x,42.0));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + LSHI + "function f() {var x=i4(1,2,3,4); return ci4(lsh(x,f32(42)));} return f");
+
+var input = 'i4(0, 1, ' + INT32_MIN + ', ' + INT32_MAX + ')';
+var vinput = [0, 1, INT32_MIN, INT32_MAX];
+
+function Lsh(i) { return function(x) { return (x << (i & 31)) | 0 } }
+function Rsh(i) { return function(x) { return (x >> (i & 31)) | 0 } }
+
+var asmLsh = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + LSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(lsh(v, x+y))} return f;'), this)
+var asmRsh = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + RSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(rsh(v, x+y))} return f;'), this)
+
+for (var i = 1; i < 64; i++) {
+ CheckI4(LSHI, 'var x=' + input + '; x=lsh(x, ' + i + ')', vinput.map(Lsh(i)));
+ CheckI4(RSHI, 'var x=' + input + '; x=rsh(x, ' + i + ')', vinput.map(Rsh(i)));
+
+ assertEqX4(asmLsh(i, 3), vinput.map(Lsh(i + 3)));
+ assertEqX4(asmRsh(i, 3), vinput.map(Rsh(i + 3)));
+}
+
+// Same thing for Uint32x4.
+const LSHU = 'var lsh=u4.shiftLeftByScalar;'
+const RSHU = 'var rsh=u4.shiftRightByScalar;'
+
+input = 'u4(0, 1, 0x80008000, ' + INT32_MAX + ')';
+vinput = [0, 1, 0x80008000, INT32_MAX];
+
+function uLsh(i) { return function(x) { return (x << (i & 31)) >>> 0 } }
+function uRsh(i) { return function(x) { return (x >>> (i & 31)) } }
+
+// Need to bitcast to Int32x4 before returning result.
+asmLsh = asmLink(asmCompile('glob', USE_ASM + U32 + CU32 + LSHU + I32 + CI32 + I32U32 +
+ 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(i4u4(lsh(v, x+y)));} return f;'), this)
+asmRsh = asmLink(asmCompile('glob', USE_ASM + U32 + CU32 + RSHU + I32 + CI32 + I32U32 +
+ 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(i4u4(rsh(v, x+y)));} return f;'), this)
+
+for (var i = 1; i < 64; i++) {
+ // Constant shifts.
+ CheckU4(LSHU, 'var x=' + input + '; x=lsh(x, ' + i + ')', vinput.map(uLsh(i)));
+ CheckU4(RSHU, 'var x=' + input + '; x=rsh(x, ' + i + ')', vinput.map(uRsh(i)));
+
+ // Dynamically computed shifts. The asm function returns a Int32x4.
+ assertEqX4(SIMD.Uint32x4.fromInt32x4Bits(asmLsh(i, 3)), vinput.map(uLsh(i + 3)));
+ assertEqX4(SIMD.Uint32x4.fromInt32x4Bits(asmRsh(i, 3)), vinput.map(uRsh(i + 3)));
+}
+
+// Select
+const I32SEL = 'var i4sel = i4.select;'
+const U32SEL = 'var u4sel = u4.select;'
+const F32SEL = 'var f4sel = f4.select;'
+
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var x=f4(1,2,3,4); return ci4(i4sel(x,x,x));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=f4(1,2,3,4); var x=i4(1,2,3,4); return ci4(i4sel(m,x,x));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=f4(1,2,3,4); var x=f4(1,2,3,4); return ci4(i4sel(m,x,x));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=i4(1,2,3,4); var x=f4(1,2,3,4); return ci4(i4sel(m,x,x));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=i4(1,2,3,4); var x=i4(1,2,3,4); return ci4(i4sel(m,x,x));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=b4(1,2,3,4); var x=f4(1,2,3,4); return ci4(i4sel(m,x,x));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=b4(1,2,3,4); var x=f4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=b4(1,2,3,4); var x=i4(1,2,3,4); var y=f4(5,6,7,8); return ci4(i4sel(m,x,y));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=b4(1,2,3,4); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return ci4(i4sel(m,x,y));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + B32 + CI32 + I32SEL + "function f() {var m=b4(1,2,3,4); var x=i4(1,2,3,4); var y=b4(5,6,7,8); return ci4(i4sel(m,x,y));} return f");
+
+assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + F32SEL + "function f() {var m=f4(1,2,3,4); return cf4(f4sel(x,x,x));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=f4(1,2,3,4); var x=i4(1,2,3,4); return cf4(f4sel(m,x,x));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=f4(1,2,3,4); var x=f4(1,2,3,4); return cf4(f4sel(m,x,x));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(1,2,3,4); var x=f4(1,2,3,4); var y=i4(5,6,7,8); return cf4(f4sel(m,x,y));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(1,2,3,4); var x=i4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y));} return f");
+
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + CI32 + I32SEL + "function f() {var m=b4(0,0,0,0); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + CI32 + I32SEL + "function f() {var m=b4(1,1,1,1); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + CI32 + I32SEL + "function f() {var m=b4(0,1,0,1); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + CI32 + I32SEL + "function f() {var m=b4(0,0,1,1); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
+
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + F32 + CF32 + F32SEL + "function f() {var m=b4(0,0,0,0); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + F32 + CF32 + F32SEL + "function f() {var m=b4(1,1,1,1); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + F32 + CF32 + F32SEL + "function f() {var m=b4(0,1,0,1); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + B32 + F32 + CF32 + F32SEL + "function f() {var m=b4(0,0,1,1); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
+
+CheckU4(B32 + U32SEL, "var m=b4(0,0,0,0); var x=u4(1,2,3,4); var y=u4(5,6,7,8); x=u4sel(m,x,y);", [5, 6, 7, 8]);
+CheckU4(B32 + U32SEL, "var m=b4(1,1,1,1); var x=u4(1,2,3,4); var y=u4(5,6,7,8); x=u4sel(m,x,y);", [1, 2, 3, 4]);
+CheckU4(B32 + U32SEL, "var m=b4(0,1,0,1); var x=u4(1,2,3,4); var y=u4(5,6,7,8); x=u4sel(m,x,y);", [5, 2, 7, 4]);
+CheckU4(B32 + U32SEL, "var m=b4(0,0,1,1); var x=u4(1,2,3,4); var y=u4(5,6,7,8); x=u4sel(m,x,y);", [5, 6, 3, 4]);
+
+// Splat
+const I32SPLAT = 'var splat=i4.splat;'
+const U32SPLAT = 'var splat=u4.splat;'
+const F32SPLAT = 'var splat=f4.splat;'
+const B32SPLAT = 'var splat=b4.splat;'
+
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); var p=f4(1.,2.,3.,4.); p=splat(f32(1));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(1, 2)} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat()} return f");
+
+assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(m);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(1.0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + FROUND + "function f() {var m=i4(1,2,3,4); m=splat(f32(1.0));} return f");
+
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32SPLAT + 'function f(){return ci4(splat(42));} return f'), this)(), [42, 42, 42, 42]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + B32SPLAT + 'function f(){return cb4(splat(42));} return f'), this)(), [true, true, true, true]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + B32 + CB32 + B32SPLAT + 'function f(){return cb4(splat(0));} return f'), this)(), [false, false, false, false]);
+CheckU4(B32 + U32SPLAT, "var x=u4(1,2,3,4); x=splat(0);", [0, 0, 0, 0]);
+CheckU4(B32 + U32SPLAT, "var x=u4(1,2,3,4); x=splat(0xaabbccdd);", [0xaabbccdd, 0xaabbccdd, 0xaabbccdd, 0xaabbccdd]);
+
+const l33t = Math.fround(13.37);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(f32(1)));} return f'), this)(), [1, 1, 1, 1]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(1.0));} return f'), this)(), [1, 1, 1, 1]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(f32(1 >>> 0)));} return f'), this)(), [1, 1, 1, 1]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(f32(13.37)));} return f'), this)(), [l33t, l33t, l33t, l33t]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(13.37));} return f'), this)(), [l33t, l33t, l33t, l33t]);
+
+var i32view = new Int32Array(heap);
+var f32view = new Float32Array(heap);
+i32view[0] = 42;
+assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + I32 + CI32 + I32SPLAT + 'var i32=new glob.Int32Array(heap); function f(){return ci4(splat(i32[0]));} return f'), this, {}, heap)(), [42, 42, 42, 42]);
+f32view[0] = 42;
+assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + CF32 + F32SPLAT + 'var f32=new glob.Float32Array(heap); function f(){return cf4(splat(f32[0]));} return f'), this, {}, heap)(), [42, 42, 42, 42]);
+assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(f32(1) + f32(2)));} return f'), this, {}, heap)(), [3, 3, 3, 3]);
+
+// Dead code
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + 'function f(){var x=i4(1,2,3,4); return ci4(x); x=i4(5,6,7,8); return ci4(x);} return f'), this)(), [1, 2, 3, 4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + EXTI4 + 'function f(){var x=i4(1,2,3,4); var c=0; return ci4(x); c=e(x,0)|0; return ci4(x);} return f'), this)(), [1, 2, 3, 4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32A + 'function f(){var x=i4(1,2,3,4); var c=0; return ci4(x); x=i4a(x,x); return ci4(x);} return f'), this)(), [1, 2, 3, 4]);
+assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32S + 'function f(){var x=i4(1,2,3,4); var c=0; return ci4(x); x=i4s(x,x); return ci4(x);} return f'), this)(), [1, 2, 3, 4]);
+
+// Swizzle
+assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); x=swizzle(x, -1, 0, 0, 0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); x=swizzle(x, 4, 0, 0, 0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); x=swizzle(x, 0.0, 0, 0, 0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); x=swizzle(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); x=swizzle(x, 0, 0, 0, x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); var y=42; x=swizzle(x, 0, 0, 0, y);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "var swizzle=i4.swizzle; function f() {var x=f4(1,2,3,4); x=swizzle(x, 0, 0, 0, 0);} return f");
+
+function swizzle(arr, lanes) {
+ return [arr[lanes[0]], arr[lanes[1]], arr[lanes[2]], arr[lanes[3]]];
+}
+
+var before = Date.now();
+for (var i = 0; i < Math.pow(4, 4); i++) {
+ var lanes = [i & 3, (i >> 2) & 3, (i >> 4) & 3, (i >> 6) & 3];
+ CheckI4('var swizzle=i4.swizzle;', 'var x=i4(1,2,3,4); x=swizzle(x, ' + lanes.join(',') + ')', swizzle([1,2,3,4], lanes));
+ CheckU4('var swizzle=u4.swizzle;', 'var x=u4(1,2,3,4); x=swizzle(x, ' + lanes.join(',') + ')', swizzle([1,2,3,4], lanes));
+ CheckF4('var swizzle=f4.swizzle;', 'var x=f4(1,2,3,4); x=swizzle(x, ' + lanes.join(',') + ')', swizzle([1,2,3,4], lanes));
+}
+DEBUG && print('time for checking all swizzles:', Date.now() - before);
+
+// Shuffle
+assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); x=shuffle(x, y, -1, 0, 0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); x=shuffle(x, y, 8, 0, 0, 0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); x=shuffle(x, y, 0.0, 0, 0, 0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); x=shuffle(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); x=shuffle(x, 0, 0, 0, 0, 0);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); x=shuffle(x, y, 0, 0, 0, x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var shuffle=i4.shuffle; function f() {var x=i4(1,2,3,4); var y=i4(1,2,3,4); var z=42; x=shuffle(x, y, 0, 0, 0, z);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "var shuffle=i4.shuffle; function f() {var x=f4(1,2,3,4); x=shuffle(x, x, 0, 0, 0, 0);} return f");
+
+function shuffle(lhs, rhs, lanes) {
+ return [(lanes[0] < 4 ? lhs : rhs)[lanes[0] % 4],
+ (lanes[1] < 4 ? lhs : rhs)[lanes[1] % 4],
+ (lanes[2] < 4 ? lhs : rhs)[lanes[2] % 4],
+ (lanes[3] < 4 ? lhs : rhs)[lanes[3] % 4]];
+}
+
+before = Date.now();
+
+const LANE_SELECTORS = [
+ // Four of lhs or four of rhs, equivalent to swizzle
+ [0, 1, 2, 3],
+ [4, 5, 6, 7],
+ [0, 2, 3, 1],
+ [4, 7, 4, 6],
+ // One of lhs, three of rhs
+ [0, 4, 5, 6],
+ [4, 0, 5, 6],
+ [4, 5, 0, 6],
+ [4, 5, 6, 0],
+ // Two of lhs, two of rhs
+ // in one shufps
+ [1, 2, 4, 5],
+ [4, 5, 1, 2],
+ // in two shufps
+ [7, 0, 5, 2],
+ [0, 7, 5, 2],
+ [0, 7, 2, 5],
+ [7, 0, 2, 5],
+ // Three of lhs, one of rhs
+ [7, 0, 1, 2],
+ [0, 7, 1, 2],
+ [0, 1, 7, 2],
+ [0, 1, 2, 7],
+ // Impl-specific special cases for swizzle
+ [2, 3, 2, 3],
+ [0, 1, 0, 1],
+ [0, 0, 1, 1],
+ [2, 2, 3, 3],
+ // Impl-specific special cases for shuffle (case and swapped case)
+ [2, 3, 6, 7], [6, 7, 2, 3],
+ [0, 1, 4, 5], [4, 5, 0, 1],
+ [0, 4, 1, 5], [4, 0, 5, 1],
+ [2, 6, 3, 7], [6, 2, 7, 3],
+ [4, 1, 2, 3], [0, 5, 6, 7],
+ // Insert one element from rhs into lhs keeping other elements unchanged
+ [7, 1, 2, 3],
+ [0, 7, 2, 3],
+ [0, 1, 7, 2],
+ // These are effectively vector selects
+ [0, 5, 2, 3],
+ [0, 1, 6, 3],
+ [4, 5, 2, 3],
+ [4, 1, 6, 3]
+];
+
+for (var lanes of LANE_SELECTORS) {
+ CheckI4('var shuffle=i4.shuffle;', 'var x=i4(1,2,3,4); var y=i4(5,6,7,8); x=shuffle(x, y, ' + lanes.join(',') + ')', shuffle([1,2,3,4], [5,6,7,8], lanes));
+ CheckU4('var shuffle=u4.shuffle;', 'var x=u4(1,2,3,4); var y=u4(5,6,7,8); x=shuffle(x, y, ' + lanes.join(',') + ')', shuffle([1,2,3,4], [5,6,7,8], lanes));
+ CheckF4('var shuffle=f4.shuffle;', 'var x=f4(1,2,3,4); var y=f4(5,6,7,8); x=shuffle(x, y, ' + lanes.join(',') + ')', shuffle([1,2,3,4], [5,6,7,8], lanes));
+}
+DEBUG && print('time for checking all shuffles:', Date.now() - before);
+
+// 3. Function calls
+// 3.1. No math builtins
+assertAsmTypeFail('glob', USE_ASM + I32 + "var fround=glob.Math.fround; function f() {var x=i4(1,2,3,4); return +fround(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var sin=glob.Math.sin; function f() {var x=i4(1,2,3,4); return +sin(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var ceil=glob.Math.ceil; function f() {var x=i4(1,2,3,4); return +ceil(x);} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var pow=glob.Math.pow; function f() {var x=i4(1,2,3,4); return +pow(1.0, x);} return f");
+
+assertAsmTypeFail('glob', USE_ASM + I32 + "var fround=glob.Math.fround; function f() {var x=i4(1,2,3,4); x=i4(fround(3));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var sin=glob.Math.sin; function f() {var x=i4(1,2,3,4); x=i4(sin(3.0));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var ceil=glob.Math.sin; function f() {var x=i4(1,2,3,4); x=i4(ceil(3.0));} return f");
+assertAsmTypeFail('glob', USE_ASM + I32 + "var pow=glob.Math.pow; function f() {var x=i4(1,2,3,4); x=i4(pow(1.0, 2.0));} return f");
+
+// 3.2. FFI calls
+// Can't pass SIMD arguments to FFI
+assertAsmTypeFail('glob', 'ffi', USE_ASM + I32 + "var func=ffi.func; function f() {var x=i4(1,2,3,4); func(x);} return f");
+assertAsmTypeFail('glob', 'ffi', USE_ASM + U32 + "var func=ffi.func; function f() {var x=u4(1,2,3,4); func(x);} return f");
+assertAsmTypeFail('glob', 'ffi', USE_ASM + F32 + "var func=ffi.func; function f() {var x=f4(1,2,3,4); func(x);} return f");
+assertAsmTypeFail('glob', 'ffi', USE_ASM + B32 + "var func=ffi.func; function f() {var x=b4(1,2,3,4); func(x);} return f");
+
+// Can't have FFI return SIMD values
+assertAsmTypeFail('glob', 'ffi', USE_ASM + I32 + "var func=ffi.func; function f() {var x=i4(1,2,3,4); x=i4(func());} return f");
+assertAsmTypeFail('glob', 'ffi', USE_ASM + U32 + "var func=ffi.func; function f() {var x=u4(1,2,3,4); x=i4(func());} return f");
+assertAsmTypeFail('glob', 'ffi', USE_ASM + F32 + "var func=ffi.func; function f() {var x=f4(1,2,3,4); x=f4(func());} return f");
+assertAsmTypeFail('glob', 'ffi', USE_ASM + B32 + "var func=ffi.func; function f() {var x=b4(1,2,3,4); x=b4(func());} return f");
+
+// 3.3 Internal calls
+// asm.js -> asm.js
+// Retrieving values from asm.js
+var code = USE_ASM + I32 + CI32 + I32A + EXTI4 + `
+ var check = ffi.check;
+
+ function g() {
+ var i = 0;
+ var y = i4(0,0,0,0);
+ var tmp = i4(0,0,0,0); var z = i4(1,1,1,1);
+ var w = i4(5,5,5,5);
+ for (; (i|0) < 30; i = i + 1 |0)
+ y = i4a(z, y);
+ y = i4a(w, y);
+ check(e(y,0) | 0, e(y,1) | 0, e(y,2) | 0, e(y,3) | 0);
+ return ci4(y);
+ }
+
+ function f(x) {
+ x = ci4(x);
+ var y = i4(0,0,0,0);
+ y = ci4(g());
+ check(e(y,0) | 0, e(y,1) | 0, e(y,2) | 0, e(y,3) | 0);
+ return ci4(x);
+ }
+ return f;
+`;
+
+var v4 = SIMD.Int32x4(1,2,3,4);
+function check(x, y, z, w) {
+ assertEq(x, 35);
+ assertEq(y, 35);
+ assertEq(z, 35);
+ assertEq(w, 35);
+}
+var ffi = {check};
+assertEqX4(asmLink(asmCompile('glob', 'ffi', code), this, ffi)(v4), [1,2,3,4]);
+
+// Passing arguments from asm.js to asm.js
+var code = USE_ASM + I32 + CI32 + I32A + EXTI4 + `
+ var assertEq = ffi.assertEq;
+
+ function internal([args]) {
+ [coerc]
+ assertEq(e([last],0) | 0, [i] | 0);
+ assertEq(e([last],1) | 0, [i] + 1 |0);
+ assertEq(e([last],2) | 0, [i] + 2 |0);
+ assertEq(e([last],3) | 0, [i] + 3 |0);
+ }
+
+ function external() {
+ [decls]
+ internal([args]);
+ }
+ return external;
+`;
+
+var ffi = {assertEq};
+var args = '';
+var decls = '';
+var coerc = '';
+for (var i = 1; i < 10; ++i) {
+ var j = i;
+ args += ((i > 1) ? ', ':'') + 'x' + i;
+ decls += 'var x' + i + ' = i4(' + j++ + ', ' + j++ + ', ' + j++ + ', ' + j++ + ');\n';
+ coerc += 'x' + i + ' = ci4(x' + i + ');\n';
+ last = 'x' + i;
+ var c = code.replace(/\[args\]/g, args)
+ .replace(/\[last\]/g, last)
+ .replace(/\[decls\]/i, decls)
+ .replace(/\[coerc\]/i, coerc)
+ .replace(/\[i\]/g, i);
+ asmLink(asmCompile('glob', 'ffi', c), this, ffi)();
+}
+
+// Bug 1240524
+assertAsmTypeFail(USE_ASM + B32 + 'var x = b4(0, 0, 0, 0); frd(x);');
+
+// Passing boolean results to extern functions.
+// Verify that these functions are typed correctly.
+function isone(x) { return (x===1)|0 }
+var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + B32 + CB32 + ANYB4 + 'var isone=ffi.isone; function f(i) { i=cb4(i); return isone(anyt(i)|0)|0; } return f'), this, {isone:isone});
+assertEq(f(SIMD.Bool32x4(0,0,1,0)), 1)
+assertEq(f(SIMD.Bool32x4(0,0,0,0)), 0)
+assertAsmTypeFail('glob', 'ffi', USE_ASM + B32 + CB32 + ANYB4 + 'var isone=ffi.isone; function f(i) { i=cb4(i); return isone(anyt(i))|0; } return f');
+
+var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + B32 + CB32 + ALLB4 + 'var isone=ffi.isone; function f(i) { i=cb4(i); return isone(allt(i)|0)|0; } return f'), this, {isone:isone});
+assertEq(f(SIMD.Bool32x4(1,1,1,1)), 1)
+assertEq(f(SIMD.Bool32x4(0,1,0,0)), 0)
+assertAsmTypeFail('glob', 'ffi', USE_ASM + B32 + CB32 + ALLB4 + 'var isone=ffi.isone; function f(i) { i=cb4(i); return isone(allt(i))|0; } return f');
+
+var f = asmLink(asmCompile('glob', 'ffi', USE_ASM + B32 + CB32 + EXTB4 + 'var isone=ffi.isone; function f(i) { i=cb4(i); return isone(e(i,2)|0)|0; } return f'), this, {isone:isone});
+assertEq(f(SIMD.Bool32x4(1,1,1,1)), 1)
+assertEq(f(SIMD.Bool32x4(0,1,0,0)), 0)
+assertAsmTypeFail('glob', 'ffi', USE_ASM + B32 + CB32 + EXTB4 + 'var isone=ffi.isone; function f(i) { i=cb4(i); return isone(e(i,2))|0; } return f');
+
+// Stress-test for register spilling code and stack depth checks
+var code = `
+ "use asm";
+ var i4 = glob.SIMD.Int32x4;
+ var i4a = i4.add;
+ var e = i4.extractLane;
+ var assertEq = ffi.assertEq;
+ function g() {
+ var x = i4(1,2,3,4);
+ var y = i4(2,3,4,5);
+ var z = i4(0,0,0,0);
+ z = i4a(x, y);
+ assertEq(e(z,0) | 0, 3);
+ assertEq(e(z,1) | 0, 5);
+ assertEq(e(z,2) | 0, 7);
+ assertEq(e(z,3) | 0, 9);
+ }
+ return g
+`
+asmLink(asmCompile('glob', 'ffi', code), this, assertEqFFI)();
+
+(function() {
+ var code = `
+ "use asm";
+ var i4 = glob.SIMD.Int32x4;
+ var i4a = i4.add;
+ var e = i4.extractLane;
+ var assertEq = ffi.assertEq;
+ var one = ffi.one;
+
+ // Function call with arguments on the stack (1 on x64, 3 on x86)
+ function h(x1, x2, x3, x4, x5, x6, x7) {
+ x1=x1|0
+ x2=x2|0
+ x3=x3|0
+ x4=x4|0
+ x5=x5|0
+ x6=x6|0
+ x7=x7|0
+ return x1 + x2 |0
+ }
+
+ function g() {
+ var x = i4(1,2,3,4);
+ var y = i4(2,3,4,5);
+ var z = i4(0,0,0,0);
+ var w = 1;
+ z = i4a(x, y);
+ w = w + (one() | 0) | 0;
+ assertEq(e(z,0) | 0, 3);
+ assertEq(e(z,1) | 0, 5);
+ assertEq(e(z,2) | 0, 7);
+ assertEq(e(z,3) | 0, 9);
+ h(1, 2, 3, 4, 42, 42, 42)|0
+ return w | 0;
+ }
+ return g
+ `;
+
+ asmLink(asmCompile('glob', 'ffi', code), this, {assertEq: assertEq, one: () => 1})();
+})();
+
+// Function calls with mixed arguments on the stack (SIMD and scalar). In the
+// worst case (x64), we have 6 int arg registers and 8 float registers.
+(function() {
+ var code = `
+ "use asm";
+ var i4 = glob.SIMD.Int32x4;
+ var e = i4.extractLane;
+ var ci4 = i4.check;
+ function h(
+ // In registers:
+ gpr1, gpr2, gpr3, gpr4, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8,
+ // On the stack:
+ sint1, ssimd1, sdouble1, ssimd2, sint2, sint3, sint4, ssimd3, sdouble2
+ )
+ {
+ gpr1=gpr1|0;
+ gpr2=gpr2|0;
+ gpr3=gpr3|0;
+ gpr4=gpr4|0;
+
+ xmm1=+xmm1;
+ xmm2=+xmm2;
+ xmm3=+xmm3;
+ xmm4=+xmm4;
+ xmm5=+xmm5;
+ xmm6=+xmm6;
+ xmm7=+xmm7;
+ xmm8=+xmm8;
+
+ sint1=sint1|0;
+ ssimd1=ci4(ssimd1);
+ sdouble1=+sdouble1;
+ ssimd2=ci4(ssimd2);
+ sint2=sint2|0;
+ sint3=sint3|0;
+ sint4=sint4|0;
+ ssimd3=ci4(ssimd3);
+ sdouble2=+sdouble2;
+
+ return (e(ssimd1,0)|0) + (e(ssimd2,1)|0) + (e(ssimd3,2)|0) + sint2 + gpr3 | 0;
+ }
+
+ function g() {
+ var simd1 = i4(1,2,3,4);
+ var simd2 = i4(5,6,7,8);
+ var simd3 = i4(9,10,11,12);
+ return h(1, 2, 3, 4,
+ 1., 2., 3., 4., 5., 6., 7., 8.,
+ 5, simd1, 9., simd2, 6, 7, 8, simd3, 10.) | 0;
+ }
+ return g
+ `;
+
+ assertEq(asmLink(asmCompile('glob', 'ffi', code), this)(), 1 + 6 + 11 + 6 + 3);
+})();
+
+// Check that the interrupt callback doesn't erase high components of simd
+// registers:
+
+// WARNING: must be the last test in this file
+(function() {
+ var iters = 2000000;
+ var code = `
+ "use asm";
+ var i4 = glob.SIMD.Int32x4;
+ var i4a = i4.add;
+ var ci4 = i4.check;
+ function _() {
+ var i = 0;
+ var n = i4(0,0,0,0);
+ var one = i4(1,1,1,1);
+ for (; (i>>>0) < ` + iters + `; i=(i+1)>>>0) {
+ n = i4a(n, one);
+ }
+ return ci4(n);
+ }
+ return _;`;
+ // This test relies on the fact that setting the timeout will call the
+ // interrupt callback at fixed intervals, even before the timeout.
+ timeout(1000);
+ var x4 = asmLink(asmCompile('glob', code), this)();
+ assertEq(SIMD.Int32x4.extractLane(x4,0), iters);
+ assertEq(SIMD.Int32x4.extractLane(x4,1), iters);
+ assertEq(SIMD.Int32x4.extractLane(x4,2), iters);
+ assertEq(SIMD.Int32x4.extractLane(x4,3), iters);
+})();
+
+} catch(e) {
+ print('Stack:', e.stack)
+ print('Error:', e)
+ throw e;
+}
diff --git a/js/src/jit-test/tests/asm.js/testSource.js b/js/src/jit-test/tests/asm.js/testSource.js
new file mode 100644
index 000000000..b44c52a6b
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testSource.js
@@ -0,0 +1,398 @@
+setCachingEnabled(true);
+
+(function() {
+/*
+ * NO ARGUMENT
+ */
+
+function f0() {
+ "use asm";
+ function g() {}
+ return g;
+
+}
+
+var bodyOnly = '"use asm";\n\
+ function g() {}\n\
+ return g;\n';
+
+var funcBody = 'function f0() {\n\
+ "use asm";\n\
+ function g() {}\n\
+ return g;\n\n\
+}';
+
+assertEq(f0.toString(), funcBody);
+assertEq(f0.toSource(), funcBody);
+
+var f0 = function() {
+ "use asm";
+ function g() {}
+ return g;
+
+}
+
+funcBody1 = funcBody.replace('function f0','function ');
+assertEq(f0.toString(), funcBody1);
+assertEq(f0.toSource(), '(' + funcBody1 + ')');
+
+var g = function g0() {
+ "use asm";
+ function g() {}
+ return g;
+
+}
+
+funcBody2 = funcBody.replace('function f0', 'function g0');
+assertEq(g.toString(), funcBody2);
+assertEq(g.toSource(), '(' + funcBody2 + ')');
+
+f0 = new Function(bodyOnly);
+assertEq(f0.toString(), "function anonymous() {\n" + bodyOnly + "\n}");
+assertEq(f0.toSource(), "(function anonymous() {\n" + bodyOnly + "\n})");
+
+if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
+ var m = new Function(bodyOnly);
+ assertEq(isAsmJSModuleLoadedFromCache(m), true);
+ assertEq(m.toString(), "function anonymous() {\n" + bodyOnly + "\n}");
+ assertEq(m.toSource(), "(function anonymous() {\n" + bodyOnly + "\n})");
+}
+
+})();
+
+(function() {
+/*
+ * ONE ARGUMENT
+ */
+function f1(glob) {
+ "use asm";
+ function g() {}
+ return g;
+
+}
+
+var bodyOnly = '"use asm";\n\
+ function g() {}\n\
+ return g;\n';
+
+var funcBody = 'function f1(glob) {\n\
+ "use asm";\n\
+ function g() {}\n\
+ return g;\n\n\
+}';
+
+assertEq(f1.toString(), funcBody);
+assertEq(f1.toSource(), funcBody);
+
+f1 = function(glob) {
+ "use asm";
+ function g() {}
+ return g;
+
+}
+
+funcBody1 = funcBody.replace('function f1', 'function ');
+assertEq(f1.toString(), funcBody1);
+assertEq(f1.toSource(), '(' + funcBody1 + ')');
+
+var g = function g0(glob) {
+ "use asm";
+ function g() {}
+ return g;
+
+}
+
+funcBody2 = funcBody.replace('function f1', 'function g0');
+assertEq(g.toString(), funcBody2);
+assertEq(g.toSource(), '(' + funcBody2 + ')');
+
+f1 = new Function('glob', bodyOnly);
+assertEq(f1.toString(), "function anonymous(glob) {\n" + bodyOnly + "\n}");
+assertEq(f1.toSource(), "(function anonymous(glob) {\n" + bodyOnly + "\n})");
+
+if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
+ var m = new Function('glob', bodyOnly);
+ assertEq(isAsmJSModuleLoadedFromCache(m), true);
+ assertEq(m.toString(), "function anonymous(glob) {\n" + bodyOnly + "\n}");
+ assertEq(m.toSource(), "(function anonymous(glob) {\n" + bodyOnly + "\n})");
+}
+
+})();
+
+
+(function() {
+/*
+ * TWO ARGUMENTS
+ */
+function f2(glob, ffi) {
+ "use asm";
+ function g() {}
+ return g;
+
+}
+
+var bodyOnly = '"use asm";\n\
+ function g() {}\n\
+ return g;\n';
+
+var funcBody = 'function f2(glob, ffi) {\n\
+ "use asm";\n\
+ function g() {}\n\
+ return g;\n\n\
+}';
+
+assertEq(f2.toString(), funcBody);
+assertEq(f2.toSource(), funcBody);
+
+f2 = function (glob, ffi) {
+ "use asm";
+ function g() {}
+ return g;
+
+}
+
+funcBody1 = funcBody.replace('function f2', 'function ');
+assertEq(f2.toString(), funcBody1);
+assertEq(f2.toSource(), '(' + funcBody1 + ')');
+
+var g = function g0(glob, ffi) {
+ "use asm";
+ function g() {}
+ return g;
+
+}
+
+var funcBody2 = funcBody.replace('function f2', 'function g0');
+assertEq(g.toString(), funcBody2);
+assertEq(g.toSource(), '(' + funcBody2 + ')');
+
+f2 = new Function('glob', 'ffi', bodyOnly);
+assertEq(f2.toString(), "function anonymous(glob, ffi) {\n" + bodyOnly + "\n}");
+assertEq(f2.toSource(), "(function anonymous(glob, ffi) {\n" + bodyOnly + "\n})");
+
+if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
+ var m = new Function('glob', 'ffi', bodyOnly);
+ assertEq(isAsmJSModuleLoadedFromCache(m), true);
+ assertEq(m.toString(), "function anonymous(glob, ffi) {\n" + bodyOnly + "\n}");
+ assertEq(m.toSource(), "(function anonymous(glob, ffi) {\n" + bodyOnly + "\n})");
+}
+
+})();
+
+
+(function() {
+/*
+ * THREE ARGUMENTS
+ */
+function f3(glob, ffi, heap) {
+ "use asm";
+ function g() {}
+ return g;
+
+}
+
+var bodyOnly = '"use asm";\n\
+ function g() {}\n\
+ return g;\n';
+
+var funcBody = 'function f3(glob, ffi, heap) {\n\
+ "use asm";\n\
+ function g() {}\n\
+ return g;\n\n\
+}';
+
+assertEq(f3.toString(), funcBody);
+assertEq(f3.toSource(), funcBody);
+
+f3 = function (glob, ffi, heap) {
+ "use asm";
+ function g() {}
+ return g;
+
+}
+
+funcBody1 = funcBody.replace('function f3', 'function ');
+assertEq(f3.toString(), funcBody1);
+assertEq(f3.toSource(), '(' + funcBody1 + ')');
+
+var g = function g0(glob, ffi, heap) {
+ "use asm";
+ function g() {}
+ return g;
+
+}
+
+funcBody2 = funcBody.replace('function f3', 'function g0');
+assertEq(g.toString(), funcBody2);
+assertEq(g.toSource(), '(' + funcBody2 + ')');
+
+f3 = new Function('glob', 'ffi', 'heap', bodyOnly);
+assertEq(f3.toString(), "function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n}");
+assertEq(f3.toSource(), "(function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n})");
+
+if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
+ var m = new Function('glob', 'ffi', 'heap', bodyOnly);
+ assertEq(isAsmJSModuleLoadedFromCache(m), true);
+ assertEq(m.toString(), "function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n}");
+ assertEq(m.toSource(), "(function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n})");
+}
+
+})();
+
+/* Modules in "use strict" context */
+(function() {
+
+var funcSource =
+ `function (glob, ffi, heap) {
+ "use asm";
+ function g() {}
+ return g;
+ }`;
+
+var f4 = eval("\"use strict\";\n(" + funcSource + ")");
+
+var expectedToString = funcSource;
+var expectedToSource = '(' + expectedToString + ')'
+
+assertEq(f4.toString(), expectedToString);
+assertEq(f4.toSource(), expectedToSource);
+
+if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
+ var f5 = eval("\"use strict\";\n(" + funcSource + ")");
+ assertEq(isAsmJSModuleLoadedFromCache(f5), true);
+ assertEq(f5.toString(), expectedToString);
+ assertEq(f5.toSource(), expectedToSource);
+}
+})();
+
+/* Functions */
+(function() {
+
+var noSrc = "function noArgument() {\n\
+ return 42;\n\
+}"
+var oneSrc = "function oneArgument(x) {\n\
+ x = x | 0;\n\
+ return x + 1 | 0;\n\
+}";
+var twoSrc = "function twoArguments(x, y) {\n\
+ x = x | 0;\n\
+ y = y | 0;\n\
+ return x + y | 0;\n\
+}";
+var threeSrc = "function threeArguments(a, b, c) {\n\
+ a = +a;\n\
+ b = +b;\n\
+ c = +c;\n\
+ return +(+(a * b) + c);\n\
+}";
+
+var funcBody = '\n\
+ "use asm";\n'
+ + noSrc + '\n'
+ + oneSrc + '\n'
+ + twoSrc + '\n'
+ + threeSrc + '\n'
+ + 'return {\n\
+ no: noArgument,\n\
+ one: oneArgument,\n\
+ two: twoArguments,\n\
+ three: threeArguments\n\
+ }';
+
+var g = new Function(funcBody);
+var moduleG = g();
+
+function checkFuncSrc(m) {
+ assertEq(m.no.toString(), noSrc);
+ assertEq(m.no.toSource(), noSrc);
+
+ assertEq(m.one.toString(), oneSrc);
+ assertEq(m.one.toSource(), oneSrc);
+
+ assertEq(m.two.toString(), twoSrc);
+ assertEq(m.two.toSource(), twoSrc);
+
+ assertEq(m.three.toString(), threeSrc);
+ assertEq(m.three.toSource(), threeSrc);
+}
+checkFuncSrc(moduleG);
+
+if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
+ var g2 = new Function(funcBody);
+ assertEq(isAsmJSModuleLoadedFromCache(g2), true);
+ m = g2();
+ checkFuncSrc(m);
+
+ var moduleDecl = 'function g3() {' + funcBody + '}';
+ eval(moduleDecl);
+ m = g3();
+ assertEq(isAsmJSModuleLoadedFromCache(g3), false);
+ checkFuncSrc(m);
+
+ eval('var x = 42;' + moduleDecl);
+ m = g3();
+ assertEq(isAsmJSModuleLoadedFromCache(g3), true);
+ checkFuncSrc(m);
+}
+
+})();
+
+/* Functions in "use strict" context */
+(function () {
+
+var funcCode = 'function g(x) {\n\
+ x=x|0;\n\
+ return x + 1 | 0;}';
+var moduleCode = 'function () {\n\
+ "use asm";\n' + funcCode + '\n\
+ return g;\n\
+ }',
+ useStrict = '"use strict";';
+
+var f5 = eval(useStrict + ";\n(" + moduleCode + "())");
+
+var expectedToString = funcCode;
+var expectedToSource = expectedToString
+
+assertEq(f5.toString(), expectedToString);
+assertEq(f5.toSource(), expectedToSource);
+
+if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
+ var mf5 = eval("\"use strict\";\n(" + moduleCode + ")");
+ assertEq(isAsmJSModuleLoadedFromCache(mf5), true);
+ var f5 = mf5();
+ assertEq(f5.toString(), expectedToString);
+ assertEq(f5.toSource(), expectedToSource);
+}
+
+})();
+
+/* Functions in "use strict" context with dynamic linking failure */
+(function () {
+
+var funcCode = 'function g(x) {\n\
+ x=x|0;\n\
+ return x + 1 | 0;}';
+var moduleCode = 'function (glob) {\n\
+ "use asm";\n\
+ var fround = glob.Math.fround;\n\
+ ' + funcCode + '\n\
+ return g;\n\
+ }',
+ useStrict = '"use strict";';
+
+var f6 = eval(useStrict + ";\n(" + moduleCode + "({Math:{}}))");
+
+assertEq(f6.toString(), funcCode);
+assertEq(f6.toSource(), funcCode);
+
+if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
+ var mf6 = eval("\"use strict\";\n(" + moduleCode + ")");
+ assertEq(isAsmJSModuleLoadedFromCache(mf6), true);
+ var f6 = mf6({Math:{}});
+ assertEq(f6.toString(), funcCode);
+ assertEq(f6.toSource(), funcCode);
+}
+
+})();
diff --git a/js/src/jit-test/tests/asm.js/testStackWalking.js b/js/src/jit-test/tests/asm.js/testStackWalking.js
new file mode 100644
index 000000000..dfda4d8c9
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testStackWalking.js
@@ -0,0 +1,98 @@
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+function matchStack(stackString, stackArray)
+{
+ var match = 0;
+ for (name of stackArray) {
+ match = stackString.indexOf(name, match);
+ if (match === -1)
+ throw name + " not found in the stack " + stack;
+ }
+}
+
+var stack;
+function dumpStack()
+{
+ stack = new Error().stack
+}
+
+setJitCompilerOption("ion.warmup.trigger", 10);
+setJitCompilerOption("baseline.warmup.trigger", 0);
+setJitCompilerOption("offthread-compilation.enable", 0);
+setCachingEnabled(true);
+
+var callFFI = asmCompile('global', 'ffis', USE_ASM + "var ffi=ffis.ffi; function f() { return ffi()|0 } return f");
+
+var f = asmLink(callFFI, null, {ffi:dumpStack});
+for (var i = 0; i < 15; i++) {
+ stack = null;
+ f();
+ matchStack(stack, ['dumpStack', 'f']);
+}
+
+if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
+ var callFFI = asmCompile('global', 'ffis', USE_ASM + "var ffi=ffis.ffi; function f() { return ffi()|0 } return f");
+ assertEq(isAsmJSModuleLoadedFromCache(callFFI), true);
+ stack = null;
+ f();
+ matchStack(stack, ['dumpStack', 'f']);
+}
+
+var f1 = asmLink(callFFI, null, {ffi:dumpStack});
+var f2 = asmLink(callFFI, null, {ffi:function middle() { f1() }});
+stack = null;
+(function outer() { f2() })();
+matchStack(stack, ["dumpStack", "f", "middle", "f"]);
+
+function returnStackDumper() { return { valueOf:function() { stack = new Error().stack } } }
+var f = asmLink(callFFI, null, {ffi:returnStackDumper});
+for (var i = 0; i < 15; i++) {
+ stack = null;
+ f();
+ matchStack(stack, ['valueOf', 'f']);
+}
+
+var caught = false;
+try {
+ stack = null;
+ asmLink(asmCompile(USE_ASM + "function asmRec() { asmRec() } return asmRec"))();
+} catch (e) {
+ caught = true;
+ matchStack(e.stack, ['asmRec', 'asmRec', 'asmRec', 'asmRec']);
+}
+assertEq(caught, true);
+
+var caught = false;
+try {
+ callFFI(null, {ffi:Object.defineProperty})();
+} catch (e) {
+ caught = true;
+}
+assertEq(caught, true);
+
+asmLink(callFFI, null, {ffi:eval})();
+asmLink(callFFI, null, {ffi:Function})();
+asmLink(callFFI, null, {ffi:Error})();
+
+var manyCalls = asmCompile('global', 'ffis',
+ USE_ASM +
+ "var ffi=ffis.ffi;\
+ function f1(a,b,c,d,e,f,g,h,i,j,k) { \
+ a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0; \
+ ffi(); \
+ return (a+b+c+d+e+f+g+h+i+j+k)|0; \
+ } \
+ function f2() { \
+ return f1(1,2,3,4,5,6,7,8,f1(1,2,3,4,5,6,7,8,9,10,11)|0,10,11)|0; \
+ } \
+ function f3() { return 13 } \
+ function f4(i) { \
+ i=i|0; \
+ return TBL[i&3]()|0; \
+ } \
+ var TBL=[f3, f3, f2, f3]; \
+ return f4;");
+stack = null;
+assertEq(asmLink(manyCalls, null, {ffi:dumpStack})(2), 123);
+matchStack(stack, ['dumpStack', 'f1', 'f2', 'f4']);
diff --git a/js/src/jit-test/tests/asm.js/testStealing.js b/js/src/jit-test/tests/asm.js/testStealing.js
new file mode 100644
index 000000000..f05c81b17
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testStealing.js
@@ -0,0 +1,19 @@
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+if (!isAsmJSCompilationAvailable())
+ quit();
+
+var code = USE_ASM + "var i32 = new stdlib.Int32Array(buf); function f() { return i32[0]|0 } return f";
+
+var ab = new ArrayBuffer(BUF_MIN);
+new Int32Array(ab)[0] = 42;
+
+var f = asmLink(asmCompile('stdlib', 'ffi', 'buf', code), this, null, ab);
+assertEq(f(), 42);
+
+assertThrowsInstanceOf(() => detachArrayBuffer(ab), Error);
+assertEq(f(), 42);
+
+assertThrowsInstanceOf(() => serialize(ab, [ab]), Error);
+assertEq(f(), 42);
diff --git a/js/src/jit-test/tests/asm.js/testTimeout1.js b/js/src/jit-test/tests/asm.js/testTimeout1.js
new file mode 100644
index 000000000..9f3013c63
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testTimeout1.js
@@ -0,0 +1,8 @@
+// |jit-test| exitstatus: 6;
+
+load(libdir + "asm.js");
+
+var g = asmLink(asmCompile(USE_ASM + "function f() {} function g() { while(1) { f() } } return g"));
+timeout(1);
+g();
+assertEq(true, false);
diff --git a/js/src/jit-test/tests/asm.js/testTimeout2.js b/js/src/jit-test/tests/asm.js/testTimeout2.js
new file mode 100644
index 000000000..4ba2d2624
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testTimeout2.js
@@ -0,0 +1,8 @@
+// |jit-test| exitstatus: 6;
+
+load(libdir + "asm.js");
+
+var g = asmLink(asmCompile(USE_ASM + "function g() { while(1) {} } return g"));
+timeout(1);
+g();
+assertEq(true, false);
diff --git a/js/src/jit-test/tests/asm.js/testTimeout3.js b/js/src/jit-test/tests/asm.js/testTimeout3.js
new file mode 100644
index 000000000..4f7df0a5e
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testTimeout3.js
@@ -0,0 +1,8 @@
+// |jit-test| exitstatus: 6;
+
+load(libdir + "asm.js");
+
+var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; if (!i) return; f((i-1)|0); f((i-1)|0); f((i-1)|0); f((i-1)|0); f((i-1)|0); } return f"));
+timeout(1);
+f(100);
+assertEq(true, false);
diff --git a/js/src/jit-test/tests/asm.js/testTimeout4.js b/js/src/jit-test/tests/asm.js/testTimeout4.js
new file mode 100644
index 000000000..4cbe53179
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testTimeout4.js
@@ -0,0 +1,8 @@
+// |jit-test| exitstatus: 6;
+
+load(libdir + "asm.js");
+
+var g = asmLink(asmCompile(USE_ASM + "function f(d) { d=+d; d=d*.1; d=d/.4; return +d } function g() { while(1) { +f(1.1) } } return g"));
+timeout(1);
+g();
+assertEq(true, false);
diff --git a/js/src/jit-test/tests/asm.js/testTimeout5.js b/js/src/jit-test/tests/asm.js/testTimeout5.js
new file mode 100644
index 000000000..02524e4ec
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testTimeout5.js
@@ -0,0 +1,12 @@
+// |jit-test| exitstatus: 6;
+
+load(libdir + "asm.js");
+
+enableSPSProfiling();
+
+var f = asmLink(asmCompile('glob', 'ffis', 'buf', USE_ASM + "function f() { var i=0; while (1) { i=(i+1)|0 } } return f"));
+timeout(1);
+if (getBuildConfiguration()["arm-simulator"])
+ enableSingleStepProfiling();
+f();
+assertEq(true, false);
diff --git a/js/src/jit-test/tests/asm.js/testTimeout6.js b/js/src/jit-test/tests/asm.js/testTimeout6.js
new file mode 100644
index 000000000..4ae0a037e
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testTimeout6.js
@@ -0,0 +1,12 @@
+// |jit-test| exitstatus: 6;
+
+load(libdir + "asm.js");
+
+enableSPSProfiling();
+
+var f = asmLink(asmCompile('glob', 'ffis', 'buf', USE_ASM + "function g() { var i=0; while (1) { i=(i+1)|0 } } function f() { g() } return f"));
+timeout(1);
+if (getBuildConfiguration()["arm-simulator"])
+ enableSingleStepProfiling();
+f();
+assertEq(true, false);
diff --git a/js/src/jit-test/tests/asm.js/testUseAsmWarnings.js b/js/src/jit-test/tests/asm.js/testUseAsmWarnings.js
new file mode 100644
index 000000000..46a15d752
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testUseAsmWarnings.js
@@ -0,0 +1,14 @@
+load(libdir + "asm.js");
+
+assertAsmDirectiveFail("'use asm'");
+assertAsmDirectiveFail("eval('\"use asm\";');");
+assertAsmDirectiveFail("{ eval('\"use asm\";'); }");
+assertAsmDirectiveFail("if (Math) { 'use asm'; }");
+assertAsmDirectiveFail("function f(){ { 'use asm'; } }");
+assertAsmDirectiveFail("function f(){ ; 'use asm'; } }");
+assertAsmDirectiveFail("function f(){ 1; 'use asm'; } }");
+assertAsmDirectiveFail("function f(){ var x; 'use asm'; } }");
+assertAsmDirectiveFail("function f(){ if (Math) { 'use asm'; } }");
+assertAsmDirectiveFail("(function(){ eval('\"use asm\";') })()");
+assertAsmDirectiveFail("new Function('{\"use asm\";}')");
+assertAsmDirectiveFail("new Function('if (Math){\"use asm\";}')");
diff --git a/js/src/jit-test/tests/asm.js/testX86ByteStore.js b/js/src/jit-test/tests/asm.js/testX86ByteStore.js
new file mode 100644
index 000000000..05556a5d9
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testX86ByteStore.js
@@ -0,0 +1,77 @@
+load(libdir + "asm.js");
+
+var body =
+' "use asm";\
+ var i8=new global.Int8Array(buffer);\
+ function g(i,j,k) {\
+ i=i|0;\
+ j=j|0;\
+ k=k|0;\
+ var a=0,b=0,c=0,d=0,e=0,f=0;\
+ a=(i+j)|0;\
+ b=(k+j)|0;\
+ c=(i+k)|0;\
+ b=(a+b)|0;\
+ d=(b+c+i+j)|0;\
+ e=(a+j+c)|0;\
+ f=(a+i+k)|0;\
+ i8[i] = f;\
+ return (a+b+c+d+e+f)|0;\
+ }\
+ return g;';
+
+var buf=new ArrayBuffer(BUF_MIN);
+var g = asmLink(asmCompile('global','foreign','buffer',body), this, null, buf);
+assertEq(g(1,2,3), 46);
+assertEq(new Int8Array(buf)[1], 7);
+
+var body =
+' "use asm";\
+ var i8=new global.Int8Array(buffer);\
+ function g(i,j,k) {\
+ i=i|0;\
+ j=j|0;\
+ k=k|0;\
+ var a=0,b=0,c=0,d=0,e=0,f=0;\
+ a=(i+j)|0;\
+ b=(k+j)|0;\
+ c=(i+k)|0;\
+ b=(a+b)|0;\
+ d=(b+c+i+j)|0;\
+ e=(a+j+c)|0;\
+ f=(a+i+k)|0;\
+ i8[i] = e;\
+ return (a+b+c+d+e+f)|0;\
+ }\
+ return g;';
+
+var buf=new ArrayBuffer(BUF_MIN);
+var g = asmLink(asmCompile('global','foreign','buffer',body), this, null, buf);
+assertEq(g(1,2,3), 46);
+assertEq(new Int8Array(buf)[1], 9);
+
+var body =
+' "use asm";\
+ var i8=new global.Int8Array(buffer);\
+ function g(i,j,k) {\
+ i=i|0;\
+ j=j|0;\
+ k=k|0;\
+ var a=0,b=0,c=0,d=0,e=0,f=0,g=0;\
+ a=(i+j)|0;\
+ b=(k+j)|0;\
+ c=(i+k)|0;\
+ b=(a+b)|0;\
+ d=(b+c+i+j)|0;\
+ e=(a+j+c)|0;\
+ f=(a+i+k)|0;\
+ g=(f+j+b)|0;\
+ i8[i] = g;\
+ return (a+b+c+d+e+f+g)|0;\
+ }\
+ return g;';
+
+var buf=new ArrayBuffer(BUF_MIN);
+var g = asmLink(asmCompile('global','foreign','buffer',body), this, null, buf);
+assertEq(g(1,2,3), 63);
+assertEq(new Int8Array(buf)[1], 17);
diff --git a/js/src/jit-test/tests/asm.js/testZOOB.js b/js/src/jit-test/tests/asm.js/testZOOB.js
new file mode 100644
index 000000000..ae59611d6
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testZOOB.js
@@ -0,0 +1,232 @@
+// |jit-test|
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+if (!isAsmJSCompilationAvailable())
+ quit();
+
+var ab = new ArrayBuffer(BUF_MIN);
+
+// Compute a set of interesting indices.
+indices = [0]
+for (var i of [4,1024,BUF_MIN,Math.pow(2,30),Math.pow(2,31),Math.pow(2,32),Math.pow(2,33)]) {
+ for (var j of [-2,-1,0,1,2]) {
+ for (var k of [1,-1])
+ indices.push((i+j)*k);
+ }
+}
+
+function testInt(ctor, shift, scale, disp) {
+ var arr = new ctor(ab);
+
+ var c = asmCompile('glob', 'imp', 'b',
+ USE_ASM +
+ 'var arr=new glob.' + ctor.name + '(b); ' +
+ 'function load(i) {i=i|0; return arr[((i<<' + scale + ')+' + disp + ')>>' + shift + ']|0 } ' +
+ 'function store(i,j) {i=i|0;j=j|0; arr[((i<<' + scale + ')+' + disp + ')>>' + shift + '] = j } ' +
+ 'function storeZero(i) {i=i|0; arr[((i<<' + scale + ')+' + disp + ')>>' + shift + '] = 0 } ' +
+ 'function storeNegOne(i) {i=i|0; arr[((i<<' + scale + ')+' + disp + ')>>' + shift + '] = -1 } ' +
+ 'return { load: load, store: store, storeZero: storeZero, storeNegOne: storeNegOne }');
+ var f = asmLink(c, this, null, ab);
+
+ var v = arr[0];
+ arr[0] = -1;
+ var negOne = arr[0]|0;
+ arr[0] = v;
+
+ for (var i of indices) {
+ var index = ((i<<scale)+disp)>>shift;
+ v = arr[index]|0;
+
+ // Loads
+ assertEq(f.load(i), v);
+
+ // Stores of immediates
+ arr[index] = 1;
+ f.storeZero(i);
+ assertEq(arr[index]|0, 0);
+ f.storeNegOne(i);
+ assertEq(arr[index]|0, index>>>0 < arr.length ? negOne : 0);
+
+ // Stores
+ arr[index] = ~v;
+ f.store(i, v);
+ assertEq(arr[index]|0, v);
+ }
+}
+
+function testFloat(ctor, shift, scale, disp, coercion) {
+ var arr = new ctor(ab);
+
+ var c = asmCompile('glob', 'imp', 'b',
+ USE_ASM +
+ 'var arr=new glob.' + ctor.name + '(b); ' +
+ 'var toF = glob.Math.fround; ' +
+ 'function load(i) {i=i|0; return ' + coercion + '(arr[((i<<' + scale + ')+' + disp + ')>>' + shift + ']) } ' +
+ 'function store(i,j) {i=i|0;j=+j; arr[((i<<' + scale + ')+' + disp + ')>>' + shift + '] = j } ' +
+ 'return { load: load, store: store }');
+ var f = asmLink(c, this, null, ab);
+
+ for (var i of indices) {
+ var index = ((i<<scale)+disp)>>shift;
+ var v = +arr[index];
+
+ // Loads
+ assertEq(f.load(i), v);
+
+ // Stores
+ arr[index] = ~v;
+ f.store(i, v);
+ assertEq(+arr[index], v);
+ }
+}
+
+function testFloat32(ctor, shift, scale, disp) {
+ testFloat(ctor, shift, scale, disp, "toF");
+}
+function testFloat64(ctor, shift, scale, disp) {
+ testFloat(ctor, shift, scale, disp, "+");
+}
+
+function assertEqX4(observed, expected) {
+ assertEq(observed.x, expected.x);
+ assertEq(observed.y, expected.y);
+ assertEq(observed.z, expected.z);
+ assertEq(observed.w, expected.w);
+}
+
+function testSimdX4(ctor, shift, scale, disp, simdName, simdCtor) {
+ var arr = new ctor(ab);
+
+ var c = asmCompile('glob', 'imp', 'b',
+ USE_ASM +
+ 'var arr=new glob.' + ctor.name + '(b); ' +
+ 'var SIMD_' + simdName + ' = glob.SIMD.' + simdName + '; ' +
+ 'var SIMD_' + simdName + '_check = SIMD_' + simdName + '.check; ' +
+ 'var SIMD_' + simdName + '_load = SIMD_' + simdName + '.load; ' +
+ 'var SIMD_' + simdName + '_load2 = SIMD_' + simdName + '.load2; ' +
+ 'var SIMD_' + simdName + '_load1 = SIMD_' + simdName + '.load1; ' +
+ 'var SIMD_' + simdName + '_store = SIMD_' + simdName + '.store; ' +
+ 'var SIMD_' + simdName + '_store2 = SIMD_' + simdName + '.store2; ' +
+ 'var SIMD_' + simdName + '_store1 = SIMD_' + simdName + '.store1; ' +
+ 'function load(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_load(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' +
+ 'function load2(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_load2(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' +
+ 'function load1(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_load1(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' +
+ 'function store(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_store(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' +
+ 'function store2(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_store2(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' +
+ 'function store1(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_store1(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' +
+ 'return { load: load, load2: load2, load1: load1, store: store, store2 : store2, store1 : store1 }');
+ var f = asmLink(c, this, null, ab);
+
+ const RuntimeError = WebAssembly.RuntimeError;
+
+ for (var i of indices) {
+ var index = ((i<<scale)+disp)>>shift;
+
+ var v, v2, v1;
+ var t = false, t2 = false, t1 = false;
+ try { v = simdCtor.load(arr, index); }
+ catch (e) {
+ assertEq(e instanceof RangeError, true);
+ t = true;
+ }
+ try { v2 = simdCtor.load2(arr, index); }
+ catch (e) {
+ assertEq(e instanceof RangeError, true);
+ t2 = true;
+ }
+ try { v1 = simdCtor.load1(arr, index); }
+ catch (e) {
+ assertEq(e instanceof RangeError, true);
+ t1 = true;
+ }
+
+ // Loads
+ var l, l2, l1;
+ var r = false, r2 = false, r1 = false;
+ try { l = f.load(i); }
+ catch (e) {
+ assertEq(e instanceof RuntimeError, true);
+ r = true;
+ }
+ try { l2 = f.load2(i); }
+ catch (e) {
+ assertEq(e instanceof RuntimeError, true);
+ r2 = true;
+ }
+ try { l1 = f.load1(i); }
+ catch (e) {
+ assertEq(e instanceof RuntimeError, true);
+ r1 = true;
+ }
+ assertEq(t, r);
+ assertEq(t2, r2);
+ assertEq(t1, r1);
+ if (!t) assertEqX4(v, l);
+ if (!t2) assertEqX4(v2, l2);
+ if (!t1) assertEqX4(v1, l1);
+
+ // Stores
+ if (!t) {
+ simdCtor.store(arr, index, simdCtor.neg(v));
+ f.store(i, v);
+ assertEqX4(simdCtor.load(arr, index), v);
+ } else
+ assertThrowsInstanceOf(() => f.store(i, simdCtor()), RuntimeError);
+ if (!t2) {
+ simdCtor.store2(arr, index, simdCtor.neg(v2));
+ f.store2(i, v2);
+ assertEqX4(simdCtor.load2(arr, index), v2);
+ } else
+ assertThrowsInstanceOf(() => f.store2(i, simdCtor()), RuntimeError);
+ if (!t1) {
+ simdCtor.store1(arr, index, simdCtor.neg(v1));
+ f.store1(i, v1);
+ assertEqX4(simdCtor.load1(arr, index), v1);
+ } else
+ assertThrowsInstanceOf(() => f.store1(i, simdCtor()), RuntimeError);
+ }
+}
+
+function testFloat32x4(ctor, shift, scale, disp) {
+ testSimdX4(ctor, shift, scale, disp, 'Float32x4', SIMD.Float32x4);
+}
+function testInt32x4(ctor, shift, scale, disp) {
+ testSimdX4(ctor, shift, scale, disp, 'Int32x4', SIMD.Int32x4);
+}
+
+function test(tester, ctor, shift) {
+ var arr = new ctor(ab);
+ for (var i = 0; i < arr.length; i++)
+ arr[i] = Math.imul(i, Math.imul((i & 1), 2) - 1);
+ for (scale of [0,1,2,3]) {
+ for (disp of [0,1,2,8,Math.pow(2,30),Math.pow(2,31)-1,Math.pow(2,31),Math.pow(2,32)-1])
+ tester(ctor, shift, scale, disp);
+ }
+ for (var i = 0; i < arr.length; i++) {
+ var v = arr[i];
+ arr[i] = Math.imul(i, Math.imul((i & 1), 2) - 1);
+ assertEq(arr[i], v);
+ }
+}
+
+test(testInt, Int8Array, 0);
+test(testInt, Uint8Array, 0);
+test(testInt, Int16Array, 1);
+test(testInt, Uint16Array, 1);
+test(testInt, Int32Array, 2);
+test(testInt, Uint32Array, 2);
+test(testFloat32, Float32Array, 2);
+test(testFloat64, Float64Array, 3);
+if (typeof SIMD !== 'undefined' && isSimdAvailable()) {
+ // Avoid pathological --ion-eager compile times due to bails in loops
+ setJitCompilerOption('ion.warmup.trigger', 1000000);
+
+ // Use a fresh ArrayBuffer so prepareForAsmJS can allocated a guard page
+ // which SIMD.js needs. Since the original ArrayBuffer was prepared for
+ // asm.js that didn't use SIMD.js, it has no guard page (on 32-bit).
+ ab = new ArrayBuffer(BUF_MIN);
+
+ test(testInt32x4, Uint8Array, 0);
+ test(testFloat32x4, Uint8Array, 0);
+}