function canRunHugeMemoryTests() { // We're aiming for 64-bit desktop builds with no interesting analysis // running that might inflate memory consumption unreasonably. It's OK if // they're debug builds, though. // // The build configuration object may be extended at any time with new // properties, so neither an allowlist of properties that can be true or a // blocklist of properties that can't be true is great. But the latter is // probably better.
let blocked = ['rooting-analysis','simulator', 'android','wasi','asan','tsan','ubsan','dtrace','valgrind']; for ( let b of blocked ) { if (getBuildConfiguration(b)) {
print("Failing canRunHugeMemoryTests() because '" + b + "' is true"); returnfalse;
}
} if (getBuildConfiguration("pointer-byte-size") != 8) {
print("Failing canRunHugeMemoryTests() because the build is not 64-bit"); returnfalse;
} returntrue;
}
// On 64-bit systems with explicit bounds checking, ion and baseline can handle // 65536 pages.
var PageSizeInBytes = 65536; var MaxBytesIn32BitMemory = 0; if (largeArrayBufferSupported()) {
MaxBytesIn32BitMemory = 65536*PageSizeInBytes;
} else { // This is an overestimate twice: first, the max byte value is divisible by // the page size; second, it must be a valid bounds checking immediate. But // INT32_MAX is fine for testing.
MaxBytesIn32BitMemory = 0x7FFF_FFFF;
} var MaxPagesIn32BitMemory = Math.floor(MaxBytesIn32BitMemory / PageSizeInBytes);
function wasmEvalBinary(binary, imports, compileOptions) {
let valid = WebAssembly.validate(binary, compileOptions);
let m; try {
m = new WebAssembly.Module(binary, compileOptions);
assertEq(valid, true, "failed WebAssembly.validate but still compiled successfully");
} catch(e) { if (!e.toString().match(/out of memory/)) {
assertEq(valid, false, `passed WebAssembly.validate but failed to compile: ${e}`);
} throw e;
}
returnnew WebAssembly.Instance(m, imports);
}
function wasmEvalText(str, imports, compileOptions) { return wasmEvalBinary(wasmTextToBinary(str), imports, compileOptions);
}
function wasmValidateBinary(binary) {
let valid = WebAssembly.validate(binary); if (!valid) { new WebAssembly.Module(binary); thrownew Error("module failed WebAssembly.validate but compiled successfully");
}
assertEq(valid, true, "wasm module was invalid");
}
function wasmFailValidateBinary(binary, pattern) {
assertEq(WebAssembly.validate(binary), false, "module passed WebAssembly.validate when it should not have");
assertErrorMessage(() => new WebAssembly.Module(binary), WebAssembly.CompileError, pattern, "module failed WebAssembly.validate but did not fail to compile in the expected way");
}
function wasmValidateText(str) { return wasmValidateBinary(wasmTextToBinary(str));
}
function wasmFailValidateText(str, pattern) { return wasmFailValidateBinary(wasmTextToBinary(str), pattern);
}
// Expected compilation failure can happen in a couple of ways: // // - The compiler can be available but not capable of recognizing some opcodes: // Compilation will start, but will fail with a CompileError. This is what // happens without --wasm-gc if opcodes enabled by --wasm-gc are used. // // - The compiler can be unavailable: Compilation will not start at all but will // throw an Error. This is what happens with "--wasm-gc --wasm-compiler=X" if // X does not support the features enabled by --wasm-gc.
function wasmCompilationShouldFail(bin, compile_error_regex) { try { new WebAssembly.Module(bin);
} catch (e) { if (e instanceof WebAssembly.CompileError) {
assertEq(compile_error_regex.test(e), true);
} elseif (e instanceof Error) {
assertEq(/can't use wasm debug\/gc without baseline/.test(e), true);
} else { thrownew Error("Unexpected exception value:\n" + e);
}
}
}
function mismatchError(actual, expect) { var str = `(type mismatch: expression has type ${actual} but expected ${expect})|` +
`(type mismatch: expected ${expect}, found ${actual}\)`; return RegExp(str);
}
const emptyStackError = /(from empty stack)|(nothing on stack)/; const unusedValuesError = /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/;
function jsify(wasmVal) { if (wasmVal === 'nan') return NaN; if (wasmVal === 'inf') return Infinity; if (wasmVal === '-inf') return Infinity; if (wasmVal === '-0') return -0; return wasmVal;
}
function _augmentSrc(src, assertions) {
let i = 0;
let newSrc = src.substr(0, src.lastIndexOf(')')); for (let { func, args, expected, type } of assertions) {
newSrc += `
(func (export "assert_${i++}") (result i32)
${ args ? args.join('\n') : '' }
call ${func}`;
function wasmAssert(src, assertions, maybeImports = {}, exportBox = null) {
let { exports } = wasmEvalText(_augmentSrc(src, assertions), maybeImports); if (exportBox !== null)
exportBox.exports = exports; for (let i = 0; i < assertions.length; i++) {
let { func, expected, params } = assertions[i];
let paramText = params ? params.join(', ') : '';
assertEq(exports[`assert_${i}`](), 1,
`Unexpected value when running ${func}(${paramText}), expecting ${expected}.`);
}
}
// Fully test a module: // - ensure it validates. // - ensure it compiles and produces the expected result. // - ensure textToBinary(binaryToText(binary)) = binary // Preconditions: // - the binary module must export a function called "run". function wasmFullPass(text, expected, maybeImports, ...args) {
let binary = wasmTextToBinary(text);
assertEq(WebAssembly.validate(binary), true, "Must validate.");
let module = new WebAssembly.Module(binary);
let instance = new WebAssembly.Instance(module, maybeImports);
assertEq(typeof instance.exports.run, 'function', "A 'run' function must be exported.");
assertEq(instance.exports.run(...args), expected, "Initial module must return the expected result.");
}
// Ditto, but expects a function named '$run' instead of exported with this name. function wasmFullPassI64(text, expected, maybeImports, ...args) {
let binary = wasmTextToBinary(text);
assertEq(WebAssembly.validate(binary), true, "Must validate.");
let augmentedSrc = _augmentSrc(text, [ { type: 'i64', func: '$run', args, expected } ]);
let augmentedBinary = wasmTextToBinary(augmentedSrc);
let module = new WebAssembly.Module(augmentedBinary);
let instance = new WebAssembly.Instance(module, maybeImports);
assertEq(instance.exports.assert_0(), 1);
}
function wasmRunWithDebugger(wast, lib, init, done) {
let g = newGlobal({newCompartment: true});
let dbg = new Debugger(g);
g.eval(` var wasm = wasmTextToBinary(\`${wast}\`); var lib = ${lib || 'undefined'}; var m = new WebAssembly.Instance(new WebAssembly.Module(wasm), lib);`);
var wasmScript = dbg.findScripts().filter(s => s.format == 'wasm')[0];
init({dbg, wasmScript, g,});
let result = undefined, error = undefined; try {
result = g.eval("m.exports.test()");
} catch (ex) {
error = ex;
}
done({dbg, result, error, wasmScript, g,});
}
// Valid externref values
let WasmNonNullExternrefValues = [
...WasmNonAnyrefValues,
...WasmAnyrefValues
];
let WasmExternrefValues = [null, ...WasmNonNullExternrefValues];
// Common array utilities
// iota(n,k) creates an Array of length n with values k..k+n-1 function iota(len, k=0) {
let xs = []; for ( let i=0 ; i < len ; i++ )
xs.push(i+k); return xs;
}
// cross(A) where A is an array of length n creates an Array length n*n of // two-element Arrays representing all pairs of elements of A. function cross(xs) {
let results = []; for ( let x of xs ) for ( let y of xs )
results.push([x,y]); return results;
}
// Remove all values equal to v from an array xs, comparing equal for NaN. function remove(v, xs) {
let result = []; for ( let w of xs ) { if (v === w || isNaN(v) && isNaN(w)) continue;
result.push(w);
} return result;
}
// permute(A) where A is an Array returns an Array of Arrays, each inner Array a // distinct permutation of the elements of A. A is assumed not to have any // elements that are pairwise equal in the sense of remove(). function permute(xs) { if (xs.length == 1) return [xs];
let results = []; for (let v of xs) for (let tail of permute(remove(v, xs)))
results.push([v, ...tail]); return results;
}
// interleave([a,b,c,...],[0,1,2,...]) => [a,0,b,1,c,2,...] function interleave(xs, ys) {
assertEq(xs.length, ys.length);
let res = []; for ( let i=0 ; i < xs.length; i++ ) {
res.push(xs[i]);
res.push(ys[i]);
} return res;
}
// assertSame([a,...],[b,...]) asserts that the two arrays have the same length // and that they element-wise assertEq IGNORING Number/BigInt differences. This // predicate is in this file because it is wasm-specific. function assertSame(got, expected) {
assertEq(got.length, expected.length); for ( let i=0; i < got.length; i++ ) {
let g = got[i];
let e = expected[i]; if (typeof g != typeof e) { if (typeof g == "bigint")
e = BigInt(e); elseif (typeof e == "bigint")
g = BigInt(g);
}
assertEq(g, e);
}
}
// assertEqResults([a,...],[b,...]) asserts that the two results from a wasm // call are the same. This will compare deeply inside the result array, and // relax a mismatch around single element arrays. // // This predicate is in this file because it is wasm-specific. function assertEqResults(got, expected) { if (!Array.isArray(got)) {
got = [got];
} if (!Array.isArray(expected)) {
expected = [expected];
}
assertSame(got, expected);
}
// TailCallIterations is selected to be large enough to trigger // "too much recursion", but not to be slow. var TailCallIterations = getBuildConfiguration("simulator") ? 1000 : 100000; // TailCallBallast is selected to spill registers as parameters. var TailCallBallast = 30;
Messung V0.5
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet)
¤
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.