Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/js/src/jit-test/tests/wasm/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 20 kB image not shown  

Quelle  memory.js   Sprache: JAVA

 
const RuntimeError = WebAssembly.RuntimeError;

function loadModuleSrc(type, ext, offset, align, drop = false) {
    let maybeResult = drop ? '' : `(result ${type})`;
    let maybeDrop = drop ? 'drop' : '';
    return `(module
       (memory 1)
       (data (i32.const 0) "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")
       (data (i32.const 16) "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")
       (func $load (param i32) ${maybeResult}
         (${type}.load${ext}
          offset=${offset}
          ${align != 0 ? 'align=' + align : ''}
          (local.get 0)
         )
         ${maybeDrop}
       ) (export "" (func 0)))`;
}
function loadModule(type, ext, offset, align, drop = false) {
    return wasmEvalText(loadModuleSrc(type, ext, offset, align, drop)).exports[""];
}

function storeModuleSrc(type, ext, offset, align) {
    var load_ext = ext === '' ? '' : ext + '_s';
    return `(module
       (memory 1)
       (data (i32.const 0) "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")
       (data (i32.const 16) "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")
       (func $store (param i32) (param ${type})
         (${type}.store${ext}
          offset=${offset}
          ${align != 0 ? 'align=' + align : ''}
          (local.get 0)
          (local.get 1)
         )
       ) (export "store" (func 0))
       (func $load (param i32) (result ${type})
        (${type}.load${load_ext}
         offset=${offset}
         ${align != 0 ? 'align=' + align : ''}
         (local.get 0)
        )
       ) (export "load" (func 1)))`;
}
function storeModule(type, ext, offset, align) {
    return wasmEvalText(storeModuleSrc(type, ext, offset, align)).exports;
}

function storeModuleCstSrc(type, ext, offset, align, value) {
    var load_ext = ext === '' ? '' : ext + '_s';
    return `(module
       (memory 1)
       (data (i32.const 0) "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")
       (data (i32.const 16) "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")
       (func $store (param i32)
         (${type}.store${ext}
          offset=${offset}
          ${align != 0 ? 'align=' + align : ''}
          (local.get 0)
          (${type}.const ${value})
         )
       ) (export "store" (func 0))
       (func $load (param i32) (result ${type})
        (${type}.load${load_ext}
         offset=${offset}
         ${align != 0 ? 'align=' + align : ''}
         (local.get 0)
        )
       ) (export "load" (func 1)))`;
}
function storeModuleCst(type, ext, offset, align, value) {
    return wasmEvalText(storeModuleCstSrc(type, ext, offset, align, value)).exports;
}

function testLoad(type, ext, base, offset, align, expect) {
    if (type === 'i64') {
        wasmAssert(loadModuleSrc(type, ext, offset, align), [{
            type,
            func: '$load',
            expected: expect,
            args: [`i32.const ${base}`]
        }]);
    }
    else {
        assertEq(loadModule(type, ext, offset, align)(base), expect);
    }
}

function testLoadOOB(type, ext, base, offset, align) {
    assertErrorMessage(() => loadModule(type, ext, offset, align, /*drop*/ true)(base), RuntimeError, /index out of bounds/);
}

function testStore(type, ext, base, offset, align, value) {
    if (type === 'i64') {
        wasmAssert(storeModuleSrc(type, ext, offset, align), [
            {type, func: '$store', args: [`i32.const ${base}`, `i64.const ${value}`]},
            {type, func: '$load', args: [`i32.const ${base}`], expected: value},
        ]);
        wasmAssert(storeModuleCstSrc(type, ext, offset, align, value), [
            {type, func: '$store', args: [`i32.const ${base}`]},
            {type, func: '$load', args: [`i32.const ${base}`], expected: value},
        ]);
    } else {
        let module = storeModule(type, ext, offset, align);
        let moduleCst = storeModuleCst(type, ext, offset, align, value);
        module.store(base, value);
        assertEq(module.load(base), value);
        moduleCst.store(base);
        assertEq(moduleCst.load(base), value);
    }
}

function testStoreOOB(type, ext, base, offset, align, value) {
    if (type === 'i64') {
        assertErrorMessage(() => wasmAssert(
            storeModuleSrc(type, ext, offset, align),
            [{type, func: '$store', args: [`i32.const ${base}`, `i64.const ${value}`]}]
        ), RuntimeError, /index out of bounds/);
    } else {
        assertErrorMessage(() => storeModule(type, ext, offset, align).store(base, value), RuntimeError, /index out of bounds/);
    }
}

function badLoadModule(type, ext) {
    wasmFailValidateText( `(module (func (param i32) (${type}.load${ext} (local.get 0))) (export "" (func 0)))`, /memory index/);
}

function badStoreModule(type, ext) {
    wasmFailValidateText(`(module (func (param i32) (${type}.store${ext} (local.get 0) (${type}.const 0))) (export "" (func 0)))`, /memory index/);
}

// Can't touch memory.
for (let [type, ext] of [
    ['i32'''],
    ['i32''8_s'],
    ['i32''8_u'],
    ['i32''16_s'],
    ['i32''16_u'],
    ['i64'''],
    ['i64''8_s'],
    ['i64''8_u'],
    ['i64''16_s'],
    ['i64''16_u'],
    ['i64''32_s'],
    ['i64''32_u'],
    ['f32'''],
    ['f64'''],
])
{
    badLoadModule(type, ext);
}

for (let [type, ext] of [
    ['i32'''],
    ['i32''8'],
    ['i32''16'],
    ['i64'''],
    ['i64''8'],
    ['i64''16'],
    ['i64''32'],
    ['f32'''],
    ['f64'''],
])
{
    badStoreModule(type, ext);
}

assertEq(getJitCompilerOptions()['wasm.fold-offsets'], 1);

for (var foldOffsets = 0; foldOffsets <= 1; foldOffsets++) {
    setJitCompilerOption('wasm.fold-offsets', foldOffsets | 0);

    testLoad('i32''', 0, 0, 0, 0x03020100);
    testLoad('i32''', 1, 0, 1, 0x04030201);
    testLoad('i32''', 0, 4, 0, 0x07060504);
    testLoad('i32''', 1, 3, 4, 0x07060504);
    testLoad('f32''', 0, 0, 0, 3.820471434542632e-37);
    testLoad('f32''', 1, 0, 1, 1.539989614439558e-36);
    testLoad('f32''', 0, 4, 0, 1.0082513512365273e-34);
    testLoad('f32''', 1, 3, 4, 1.0082513512365273e-34);
    testLoad('f64''', 0, 0, 0, 7.949928895127363e-275);
    testLoad('f64''', 1, 0, 1, 5.447603722011605e-270);
    testLoad('f64''', 0, 8, 0, 3.6919162048650923e-236);
    testLoad('f64''', 1, 7, 8, 3.6919162048650923e-236);

    testLoad('i32''8_s', 16, 0, 0, -0x10);
    testLoad('i32''8_u', 16, 0, 0, 0xf0);
    testLoad('i32''16_s', 16, 0, 0, -0xe10);
    testLoad('i32''16_u', 16, 0, 0, 0xf1f0);

    testStore('i32''', 0, 0, 0, -0x3f3e2c2c);
    testStore('i32''', 1, 0, 1, -0x3f3e2c2c);
    testStore('i32''', 0, 1, 1, -0x3f3e2c2c);
    testStore('i32''', 1, 1, 4, -0x3f3e2c2c);

    testStore('f32''', 0, 0, 0, 0.01234566979110241);
    testStore('f32''', 1, 0, 1, 0.01234566979110241);
    testStore('f32''', 0, 4, 0, 0.01234566979110241);
    testStore('f32''', 1, 3, 4, 0.01234566979110241);
    testStore('f64''', 0, 0, 0, 0.89012345);
    testStore('f64''', 1, 0, 1, 0.89012345);
    testStore('f64''', 0, 8, 0, 0.89012345);
    testStore('f64''', 1, 7, 8, 0.89012345);

    testStore('i32''8', 0, 0, 0, 0x23);
    testStore('i32''16', 0, 0, 0, 0x2345);

    wasmFailValidateText('(module (memory 2 1))', /maximum length 1 is less than initial length 2/);

    // Test bounds checks and edge cases.

    for (let align of [0,1,2,4]) {

        for (let offset of [0, 1, 2, 3, 4, 8, 16, 41, 0xfff8]) {
            // Accesses of 1 byte.
            let lastValidIndex = 0x10000 - 1 - offset;

            if (align < 2) {
                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;

            if (align < 4) {
                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;

            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;
        for (let index of [0, 1, 2, 3, 0x7fffffff, 0x80000000, 0x80000001]) {
            if (align < 2) {
                testLoadOOB('i32''8_s', index, offset, align);
            }
            if (align < 4) {
                testLoadOOB('i32''16_s', index, offset, align);
            }
            testLoadOOB('i32''', index, offset, align);
            testLoadOOB('f32''', index, offset, align);
            testLoadOOB('f64''', index, offset, align);
        }

        // Ensure out of bounds when the offset is greater than the immediate range.
        index = 0;
        for (let offset of [0x80000000, 0xfffffffe, 0xffffffff]) {
            testLoadOOB('i32''8_s', index, offset, 1);
            testLoadOOB('i32''16_s', index, offset, 1);
            testLoadOOB('i32''16_s', index, offset, 2);
            testLoadOOB('i32''', index, offset, 1);
            testLoadOOB('i32''', index, offset, 4);
            testLoadOOB('f32''', index, offset, 1);
            testLoadOOB('f32''', index, offset, 4);
            testLoadOOB('f64''', index, offset, 1);
            testLoadOOB('f64''', index, offset, 8);
        }

        wasmFailValidateText('(module (memory 1) (func (f64.store offset=0 (i32.const 0) (i32.const 0))))', mismatchError("i32""f64"));
        wasmFailValidateText('(module (memory 1) (func (f64.store offset=0 (i32.const 0) (f32.const 0))))', mismatchError("f32""f64"));

        wasmFailValidateText('(module (memory 1) (func (f32.store offset=0 (i32.const 0) (i32.const 0))))', mismatchError("i32""f32"));
        wasmFailValidateText('(module (memory 1) (func (f32.store offset=0 (i32.const 0) (f64.const 0))))', mismatchError("f64""f32"));

        wasmFailValidateText('(module (memory 1) (func (i32.store offset=0 (i32.const 0) (f32.const 0))))', mismatchError("f32""i32"));
        wasmFailValidateText('(module (memory 1) (func (i32.store offset=0 (i32.const 0) (f64.const 0))))', mismatchError("f64""i32"));

        // Test high number of registers.
        function testRegisters() {
            assertEq(wasmEvalText(
                `(module
              (memory 1)
              (data (i32.const 0) "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")
              (data (i32.const 16) "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")
              (func (param i32) (result i32) (local i32 i32 i32 i32 f32 f64)
               (local.set 1 (i32.load8_s offset=4 (local.get 0)))
               (local.set 2 (i32.load16_s (local.get 1)))
               (i32.store8 offset=4 (local.get 0) (local.get 1))
               (local.set 3 (i32.load16_u (local.get 2)))
               (i32.store16 (local.get 1) (local.get 2))
               (local.set 4 (i32.load (local.get 2)))
               (i32.store (local.get 1) (local.get 2))
               (local.set 5 (f32.load (local.get 4)))
               (f32.store (local.get 4) (local.get 5))
               (local.set 6 (f64.load (local.get 4)))
               (f64.store (local.get 4) (local.get 6))
               (i32.add
                (i32.add
                 (local.get 0)
                 (local.get 1)
                )
                (i32.add
                 (i32.add
                  (local.get 2)
                  (local.get 3)
                 )
                 (i32.add
                  (local.get 4)
                  (i32.reinterpret_f32 (local.get 5))
                 )
                )
               )
              ) (export "" (func 0)))`
            ).exports[""](1), 50464523);
        }

        testRegisters();

        testLoad('i64''', 0, 0, 0, '0x0706050403020100');
        testLoad('i64''', 1, 0, 0, '0x0807060504030201');
        testLoad('i64''', 0, 1, 0, '0x0807060504030201');
        testLoad('i64''', 1, 1, 4, '0x0908070605040302');

        testLoad('i64''8_s', 16, 0, 0, -0x10);
        testLoad('i64''8_u', 16, 0, 0, 0xf0);
        testLoad('i64''16_s', 16, 0, 0, -0xe10);
        testLoad('i64''16_u', 16, 0, 0, 0xf1f0);
        testLoad('i64''32_s', 16, 0, 0, 0xf3f2f1f0 | 0);
        testLoad('i64''32_u', 16, 0, 0, '0xf3f2f1f0');

        testStore('i64''', 0, 0, 0, '0xc0c1d3d4e6e7090a');
        testStore('i64''', 1, 0, 0, '0xc0c1d3d4e6e7090a');
        testStore('i64''', 0, 1, 0, '0xc0c1d3d4e6e7090a');
        testStore('i64''', 1, 1, 4, '0xc0c1d3d4e6e7090a');
        testStore('i64''8', 0, 0, 0, 0x23);
        testStore('i64''16', 0, 0, 0, 0x23);
        testStore('i64''32', 0, 0, 0, 0x23);

        for (let offset of [0, 1, 2, 3, 4, 8, 16, 41, 0xfff8]) {
            // Accesses of 1 byte.
            let lastValidIndex = 0x10000 - 1 - offset;

            if (align < 2) {
                testLoad('i64''8_s', lastValidIndex, offset, align, 0);
                testLoadOOB('i64''8_s', lastValidIndex + 1, offset, align);

                testLoad('i64''8_u', lastValidIndex, offset, align, 0);
                testLoadOOB('i64''8_u', lastValidIndex + 1, offset, align);

                testStore('i64''8', lastValidIndex, offset, align, -42);
                testStoreOOB('i64''8', lastValidIndex + 1, offset, align, -42);
            }

            // Accesses of 2 bytes.
            lastValidIndex = 0x10000 - 2 - offset;

            if (align < 4) {
                testLoad('i64''16_s', lastValidIndex, offset, align, 0);
                testLoadOOB('i64''16_s', lastValidIndex + 1, offset, align);

                testLoad('i64''16_u', lastValidIndex, offset, align, 0);
                testLoadOOB('i64''16_u', lastValidIndex + 1, offset, align);

                testStore('i64''16', lastValidIndex, offset, align, -32768);
                testStoreOOB('i64''16', lastValidIndex + 1, offset, align, -32768);
            }

            // Accesses of 4 bytes.
            lastValidIndex = 0x10000 - 4 - offset;

            testLoad('i64''32_s', lastValidIndex, offset, align, 0);
            testLoadOOB('i64''32_s', lastValidIndex + 1, offset, align);

            testLoad('i64''32_u', lastValidIndex, offset, align, 0);
            testLoadOOB('i64''32_u', lastValidIndex + 1, offset, align);

            testStore('i64''32', lastValidIndex, offset, align, 0xf1231337 | 0);
            testStoreOOB('i64''32', lastValidIndex + 1, offset, align, 0xf1231337 | 0);

            // Accesses of 8 bytes.
            lastValidIndex = 0x10000 - 8 - offset;

            testLoad('i64''', lastValidIndex, offset, align, 0);
            testLoadOOB('i64''', lastValidIndex + 1, offset, align);

            testStore('i64''', lastValidIndex, offset, align, '0x1234567887654321');
            testStoreOOB('i64''', lastValidIndex + 1, offset, align, '0x1234567887654321');
        }
    }
}

setJitCompilerOption('wasm.fold-offsets', 1);

// Test active segments with a memory index.

{
    function makeIt(flag, memindex) {
        return new Uint8Array([0x00, 0x61, 0x73, 0x6d,
                               0x01, 0x00, 0x00, 0x00,
                               0x05,                   // Memory section
                               0x03,                   // Section size
                               0x01,                   // One memory
                               0x00,                   // Unshared, min only
                               0x01,                   // Min
                               0x0b,                   // Data section
                               0x0a,                   // Section size
                               0x01,                   // One data segment
                               flag,                   // Flag should be 2, or > 2 if invalid
                               memindex,               // Memory index should be 0, or > 0 if invalid
                               0x41,                   // Init expr: i32.const
                               0x00,                   // Init expr: zero (payload)
                               0x0b,                   // Init expr: end
                               0x03,                   // Three bytes, because why not?
                               0x01,
                               0x02,
                               0x03]);
    }

    // Should succeed because this is what an active segment with index looks like
    new WebAssembly.Module(makeIt(0x02, 0x00));

    // Should fail because the kind is unknown
    assertErrorMessage(() => new WebAssembly.Module(makeIt(0x03, 0x00)),
                       WebAssembly.CompileError,
                       /invalid data initializer-kind/);

    // Should fail because the memory index is bad
    assertErrorMessage(() => new WebAssembly.Module(makeIt(0x02, 0x01)),
                       WebAssembly.CompileError,
                       /invalid memory index/);
}

// Misc syntax for data.

// When memory index is present it must be zero, and the offset must be present too;
// but it's OK for there to be neither
new WebAssembly.Module(wasmTextToBinary(`(module (memory 1) (data 0 (i32.const 0) ""))`));
new WebAssembly.Module(wasmTextToBinary(`(module (memory 1) (data 0 (offset (i32.const 0)) ""))`));
new WebAssembly.Module(wasmTextToBinary(`(module (memory 1) (data ""))`));
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`(module (memory 1) (data 0 ""))`)),
                   SyntaxError,
                   /wasm text error/);
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`(module (memory 1) (data 1 (i32.const 0) ""))`)),
                   WebAssembly.CompileError,
                   /invalid memory index/);


// Make sure we handle memory instructions without memory

var nomem = /memory index out of range/;

assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`(module (func (result i32) memory.size))`)),
                   WebAssembly.CompileError,
                   nomem);

assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`(module (func (result i32) (memory.grow (i32.const 1))))`)),
                   WebAssembly.CompileError,
                   nomem);

assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
(module (func (param i32 i32 i32)
  (memory.copy (local.get 0) (local.get 1) (local.get 2))))`)),
                   WebAssembly.CompileError,
                   nomem);

assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
(module (func (param i32 i32 i32)
  (memory.fill (local.get 0) (local.get 1) (local.get 2))))`)),
                   WebAssembly.CompileError,
                   nomem);

assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
(module
  (data $d "01234")
  (func (param i32 i32)
    (memory.init $d (local.get 0) (local.get 1))))`)),
                   WebAssembly.CompileError,
                   nomem);


Messung V0.5
C=89 H=91 G=89

¤ Dauer der Verarbeitung: 0.3 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.