Bug 1268024: Tests; r=luke
authorBenjamin Bouvier <benj@benj.me>
Wed, 29 Jun 2016 18:36:21 +0200
changeset 304213 51492e49def40176b397323b5389b972d10e01b4
parent 304212 6a6dc548346867fa14af5b75a22e898e5c9f10cd
child 304214 5010bd1c3b0106d46004f1d0ac2deacba9b0d677
push id30417
push userkwierso@gmail.com
push dateFri, 08 Jul 2016 21:56:02 +0000
treeherdermozilla-central@fd8ff97bc294 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1268024
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1268024: Tests; r=luke MozReview-Commit-ID: 2AlSN0sQck3
js/src/jit-test/tests/wasm/basic-memory.js
js/src/jit-test/tests/wasm/spec/address.wast.js
js/src/jit-test/tests/wasm/spec/memory.wast.js
js/src/jit-test/tests/wasm/spec/traps.wast.js
--- a/js/src/jit-test/tests/wasm/basic-memory.js
+++ b/js/src/jit-test/tests/wasm/basic-memory.js
@@ -1,79 +1,70 @@
 // |jit-test| test-also-wasm-baseline
 load(libdir + "wasm.js");
 
+function loadModule(type, ext, offset, align) {
+    return wasmEvalText(
+    `(module
+       (memory 1
+         (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")
+         (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")
+       )
+       (func (param i32) (result ${type})
+         (${type}.load${ext}
+          offset=${offset}
+          ${align != 0 ? 'align=' + align : ''}
+          (get_local 0)
+         )
+       ) (export "" 0))`
+    );
+}
+
+function storeModule(type, ext, offset, align) {
+    var load_ext = ext === '' ? '' : ext + '_s';
+    return wasmEvalText(
+    `(module
+       (memory 1
+         (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")
+         (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")
+       )
+       (func (param i32) (param ${type}) (result ${type})
+         (${type}.store${ext}
+          offset=${offset}
+          ${align != 0 ? 'align=' + align : ''}
+          (get_local 0)
+          (get_local 1)
+         )
+       ) (export "store" 0)
+       (func (param i32) (result ${type})
+        (${type}.load${load_ext}
+         offset=${offset}
+         ${align != 0 ? 'align=' + align : ''}
+         (get_local 0)
+        )
+       ) (export "load" 1))`
+    );
+}
+
 function testLoad(type, ext, base, offset, align, expect) {
-  assertEq(wasmEvalText(
-    '(module' +
-    '  (memory 1' +
-    '    (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")' +
-    '    (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")' +
-    '  )' +
-    '  (func (param i32) (result ' + type + ')' +
-    '    (' + type + '.load' + ext +
-    '     offset=' + offset +
-    '     ' + (align != 0 ? 'align=' + align : '') +
-    '     (get_local 0)' +
-    '    )' +
-    '  ) (export "" 0))'
-  )(base), expect);
+    assertEq(loadModule(type, ext, offset, align)(base), expect);
+}
+
+function testLoadOOB(type, ext, base, offset, align) {
+    assertErrorMessage(() => loadModule(type, ext, offset, align)(base), Error, /invalid or out-of-range index/);
 }
 
 function testStore(type, ext, base, offset, align, value) {
-  assertEq(wasmEvalText(
-    '(module' +
-    '  (memory 1' +
-    '    (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")' +
-    '    (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")' +
-    '  )' +
-    '  (func (param i32) (param ' + type + ') (result ' + type + ')' +
-    '    (' + type + '.store' + ext +
-    '     offset=' + offset +
-    '     ' + (align != 0 ? 'align=' + align : '') +
-    '     (get_local 0)' +
-    '     (get_local 1)' +
-    '    )' +
-    '  ) (export "" 0))'
-  )(base, value), value);
+    let module = storeModule(type, ext, offset, align);
+    assertEq(module.store(base, value), value);
+    assertEq(module.load(base), value);
 }
 
-function testLoadError(type, ext, base, offset, align, errorMsg) {
-  assertErrorMessage(() => wasmEvalText(
-    '(module' +
-    '  (memory 1' +
-    '    (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")' +
-    '    (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")' +
-    '  )' +
-    '  (func (param i32) (result ' + type + ')' +
-    '    (' + type + '.load' + ext +
-    '     offset=' + offset +
-    '     ' + (align != 0 ? 'align=' + align : '') +
-    '     (get_local 0)' +
-    '    )' +
-    '  ) (export "" 0))'
-  ), Error, errorMsg);
-}
-
-function testStoreError(type, ext, base, offset, align, errorMsg) {
-  assertErrorMessage(() => wasmEvalText(
-    '(module' +
-    '  (memory 1' +
-    '    (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")' +
-    '    (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")' +
-    '  )' +
-    '  (func (param i32) (param ' + type + ') (result ' + type + ')' +
-    '    (' + type + '.store' + ext +
-    '     offset=' + offset +
-    '     ' + (align != 0 ? 'align=' + align : '') +
-    '     (get_local 0)' +
-    '     (get_local 1)' +
-    '    )' +
-    '  ) (export "" 0))'
-  ), Error, errorMsg);
+function testStoreOOB(type, ext, base, offset, align, value) {
+    assertErrorMessage(() => storeModule(type, ext, offset, align).store(base, value), Error, /invalid or out-of-range index/);
 }
 
 testLoad('i32', '', 0, 0, 0, 0x03020100);
 testLoad('i32', '', 1, 0, 0, 0x04030201);
 testLoad('i32', '', 0, 4, 0, 0x07060504);
 testLoad('i32', '', 1, 3, 4, 0x07060504);
 //testLoad('i64', '', 0, 0, 0, 0x0001020304050607); // TODO: i64 NYI
 //testLoad('i64', '', 1, 0, 0, 0x0102030405060708); // TODO: i64 NYI
@@ -138,35 +129,125 @@ testStore('f32', '', 1, 3, 4, 0.01234566
 testStore('f64', '', 0, 0, 0, 0.89012345);
 testStore('f64', '', 1, 0, 0, 0.89012345);
 testStore('f64', '', 0, 8, 0, 0.89012345);
 testStore('f64', '', 1, 7, 4, 0.89012345);
 
 testStore('i32', '8', 0, 0, 0, 0x23);
 testStore('i32', '16', 0, 0, 0, 0x2345);
 
-testLoadError('i32', '8_s', 0, 0, 2, /greater than natural alignment/);
-testLoadError('i32', '8_u', 0, 0, 2, /greater than natural alignment/);
-testLoadError('i32', '16_s', 0, 0, 4, /greater than natural alignment/);
-testLoadError('i32', '16_u', 0, 0, 4, /greater than natural alignment/);
-testLoadError('i32', '', 0, 0, 8, /greater than natural alignment/);
-testLoadError('f32', '', 0, 0, 8, /greater than natural alignment/);
-testLoadError('f64', '', 0, 0, 16, /greater than natural alignment/);
-testStoreError('i32', '8', 0, 0, 2, /greater than natural alignment/);
-testStoreError('i32', '16', 0, 0, 4, /greater than natural alignment/);
-testStoreError('i32', '', 0, 0, 8, /greater than natural alignment/);
-testStoreError('f32', '', 0, 0, 8, /greater than natural alignment/);
-testStoreError('f64', '', 0, 0, 16, /greater than natural alignment/);
+assertErrorMessage(() => wasmEvalText('(module (memory 2 1))'), TypeError, /maximum memory size less than initial memory size/);
+
+// Test bounds checks and edge cases.
+const align = 0;
+for (let offset of [0, 1, 2, 3, 4, 8, 16, 41, 0xfff8]) {
+    // Accesses of 1 byte.
+    let lastValidIndex = 0x10000 - 1 - offset;
+
+    testLoad('i32', '8_s', lastValidIndex, offset, align, 0);
+    testLoadOOB('i32', '8_s', lastValidIndex + 1, offset, align);
+
+    testLoad('i32', '8_u', lastValidIndex, offset, align, 0);
+    testLoadOOB('i32', '8_u', lastValidIndex + 1, offset, align);
+
+    testStore('i32', '8', lastValidIndex, offset, align, -42);
+    testStoreOOB('i32', '8', lastValidIndex + 1, offset, align, -42);
+
+    // Accesses of 2 bytes.
+    lastValidIndex = 0x10000 - 2 - offset;
+
+    testLoad('i32', '16_s', lastValidIndex, offset, align, 0);
+    testLoadOOB('i32', '16_s', lastValidIndex + 1, offset, align);
+
+    testLoad('i32', '16_u', lastValidIndex, offset, align, 0);
+    testLoadOOB('i32', '16_u', lastValidIndex + 1, offset, align);
+
+    testStore('i32', '16', lastValidIndex, offset, align, -32768);
+    testStoreOOB('i32', '16', lastValidIndex + 1, offset, align, -32768);
+
+    // Accesses of 4 bytes.
+    lastValidIndex = 0x10000 - 4 - offset;
 
-assertErrorMessage(() => wasmEvalText('(module (memory 2 1))'), TypeError, /maximum memory size less than initial memory size/);
+    testLoad('i32', '', lastValidIndex, offset, align, 0);
+    testLoadOOB('i32', '', lastValidIndex + 1, offset, align);
+
+    testLoad('f32', '', lastValidIndex, offset, align, 0);
+    testLoadOOB('f32', '', lastValidIndex + 1, offset, align);
+
+    testStore('i32', '', lastValidIndex, offset, align, 1337);
+    testStoreOOB('i32', '', lastValidIndex + 1, offset, align, 1337);
+
+    testStore('f32', '', lastValidIndex, offset, align, Math.fround(13.37));
+    testStoreOOB('f32', '', lastValidIndex + 1, offset, align, Math.fround(13.37));
+
+    // Accesses of 8 bytes.
+    lastValidIndex = 0x10000 - 8 - offset;
+
+    testLoad('f64', '', lastValidIndex, offset, align, 0);
+    testLoadOOB('f64', '', lastValidIndex + 1, offset, align);
+
+    testStore('f64', '', lastValidIndex, offset, align, 1.23456789);
+    testStoreOOB('f64', '', lastValidIndex + 1, offset, align, 1.23456789);
+}
+
+// Ensure wrapping doesn't apply.
+offset = 0x7fffffff; // maximum allowed offset that doesn't always throw.
+for (let index of [0, 1, 2, 3, 0x7fffffff, 0x80000000, 0x80000001]) {
+    testLoadOOB('i32', '8_s', index, offset, align);
+    testLoadOOB('i32', '16_s', index, offset, align);
+    testLoadOOB('i32', '', index, offset, align);
+    testLoadOOB('f32', '', index, offset, align);
+    testLoadOOB('f64', '', index, offset, align);
+}
 
 assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (f64.store offset=0 (i32.const 0) (i32.const 0))))'), TypeError, mismatchError("i32", "f64"));
 assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (f64.store offset=0 (i32.const 0) (f32.const 0))))'), TypeError, mismatchError("f32", "f64"));
 
 assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (f32.store offset=0 (i32.const 0) (i32.const 0))))'), TypeError, mismatchError("i32", "f32"));
 assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (f32.store offset=0 (i32.const 0) (f64.const 0))))'), TypeError, mismatchError("f64", "f32"));
 
 assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (i32.store offset=0 (i32.const 0) (f32.const 0))))'), TypeError, mismatchError("f32", "i32"));
 assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (i32.store offset=0 (i32.const 0) (f64.const 0))))'), TypeError, mismatchError("f64", "i32"));
 
 wasmEvalText('(module (memory 0 65535))')
 assertErrorMessage(() => wasmEvalText('(module (memory 0 65536))'), TypeError, /maximum memory size too big/);
 
+// Test high charge of registers
+function testRegisters() {
+    assertEq(wasmEvalText(
+    `(module
+       (memory 1
+         (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")
+         (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")
+       )
+       (func (param i32) (local i32 i32 i32 i32 f32 f64) (result i32)
+         (set_local 1 (i32.load8_s offset=4 (get_local 0)))
+         (set_local 2 (i32.load16_s (get_local 1)))
+         (i32.store8 offset=4 (get_local 0) (get_local 1))
+         (set_local 3 (i32.load16_u (get_local 2)))
+         (i32.store16 (get_local 1) (get_local 2))
+         (set_local 4 (i32.load (get_local 2)))
+         (i32.store (get_local 1) (get_local 2))
+         (set_local 5 (f32.load (get_local 4)))
+         (f32.store (get_local 4) (get_local 5))
+         (set_local 6 (f64.load (get_local 4)))
+         (f64.store (get_local 4) (get_local 6))
+         (i32.add
+          (i32.add
+           (get_local 0)
+           (get_local 1)
+          )
+          (i32.add
+           (i32.add
+            (get_local 2)
+            (get_local 3)
+           )
+           (i32.add
+            (get_local 4)
+            (i32.reinterpret/f32 (get_local 5))
+           )
+          )
+         )
+       ) (export "" 0))`
+    )(1), 50464523);
+}
+
+testRegisters();
--- a/js/src/jit-test/tests/wasm/spec/address.wast.js
+++ b/js/src/jit-test/tests/wasm/spec/address.wast.js
@@ -1,4 +1,2 @@
 // |jit-test| test-also-wasm-baseline
-// TODO: wrapping offsets
-quit();
 var importedArgs = ['address.wast']; load(scriptdir + '../spec.js');
--- a/js/src/jit-test/tests/wasm/spec/memory.wast.js
+++ b/js/src/jit-test/tests/wasm/spec/memory.wast.js
@@ -1,4 +1,4 @@
 // |jit-test| test-also-wasm-baseline
-// TODO unaligned memory accesses
+// TODO i64 loads
 quit();
 var importedArgs = ['memory.wast']; load(scriptdir + '../spec.js');
--- a/js/src/jit-test/tests/wasm/spec/traps.wast.js
+++ b/js/src/jit-test/tests/wasm/spec/traps.wast.js
@@ -1,4 +1,4 @@
 // |jit-test| test-also-wasm-baseline
-// TODO trap on OOB
+// TODO dce'd effectful instructions
 quit();
 var importedArgs = ['traps.wast']; load(scriptdir + '../spec.js');