Move HashSet-wasm to first, worst, average scoring
Same steps as for the other Wasm line items: - Move files to subdirectory. - Rebuild with up-to-date Emscripten. - Reduce single iteration time, so that we can run multiple iterations (a single iteration before took ~300ms, now ~30ms). - Checked that we spend roughly the same amount of CPU samples in the top-tier and that overall profiles look similar.
This commit is contained in:
parent
21b9a95df3
commit
daf59cd3b4
10 changed files with 975 additions and 1144 deletions
|
|
@ -1952,13 +1952,14 @@ const BENCHMARKS = [
|
|||
testGroup: GeneratorsGroup,
|
||||
}),
|
||||
// Wasm
|
||||
new WasmLegacyBenchmark({
|
||||
new WasmEMCCBenchmark({
|
||||
name: "HashSet-wasm",
|
||||
files: [
|
||||
"./wasm/HashSet.js"
|
||||
"./wasm/HashSet/build/HashSet.js",
|
||||
"./wasm/HashSet/benchmark.js"
|
||||
],
|
||||
preload: {
|
||||
wasmBinary: "./wasm/HashSet.wasm"
|
||||
wasmBinary: "./wasm/HashSet/build/HashSet.wasm"
|
||||
},
|
||||
testGroup: WasmGroup
|
||||
}),
|
||||
|
|
|
|||
1139
wasm/HashSet.js
1139
wasm/HashSet.js
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
|
@ -13473,8 +13473,8 @@ void benchmark()
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
double before = currentTime();
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
double before = currentTime();
|
||||
for (unsigned i = 0; i < 100; ++i)
|
||||
benchmark();
|
||||
double after = currentTime();
|
||||
printf("That took %lf seconds.\n", after - before);
|
||||
12
wasm/HashSet/benchmark.js
Normal file
12
wasm/HashSet/benchmark.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2025 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
class Benchmark {
|
||||
async runIteration() {
|
||||
if (!Module._main)
|
||||
await setupModule(Module);
|
||||
|
||||
Module._main();
|
||||
}
|
||||
};
|
||||
5
wasm/HashSet/build.log
Normal file
5
wasm/HashSet/build.log
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
Built on 2025-01-23T14:26:43Z
|
||||
Toolchain versions
|
||||
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.73 (ac676d5e437525d15df5fd46bc2c208ec6d376a3)
|
||||
Building...
|
||||
Building done
|
||||
22
wasm/HashSet/build.sh
Executable file
22
wasm/HashSet/build.sh
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
touch build.log
|
||||
BUILD_LOG="$(realpath build.log)"
|
||||
echo "Built on $(date -u '+%Y-%m-%dT%H:%M:%SZ')" | tee "$BUILD_LOG"
|
||||
|
||||
echo "Toolchain versions" | tee -a "$BUILD_LOG"
|
||||
em++ --version | head -n1 | tee -a "$BUILD_LOG"
|
||||
|
||||
echo "Building..." | tee -a "$BUILD_LOG"
|
||||
mkdir -p build
|
||||
em++ -o build/HashSet.js \
|
||||
-std=c++11 \
|
||||
-s WASM=1 -O2 \
|
||||
-s MODULARIZE=1 -s EXPORT_NAME=setupModule \
|
||||
-g1 --emit-symbol-map \
|
||||
-s TOTAL_MEMORY=52428800 \
|
||||
HashSet.cpp | tee -a "$BUILD_LOG"
|
||||
|
||||
echo "Building done" | tee -a "$BUILD_LOG"
|
||||
887
wasm/HashSet/build/HashSet.js
Normal file
887
wasm/HashSet/build/HashSet.js
Normal file
|
|
@ -0,0 +1,887 @@
|
|||
|
||||
var setupModule = (() => {
|
||||
var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined;
|
||||
if (typeof __filename != 'undefined') _scriptName = _scriptName || __filename;
|
||||
return (
|
||||
function(moduleArg = {}) {
|
||||
var moduleRtn;
|
||||
|
||||
// include: shell.js
|
||||
// The Module object: Our interface to the outside world. We import
|
||||
// and export values on it. There are various ways Module can be used:
|
||||
// 1. Not defined. We create it here
|
||||
// 2. A function parameter, function(moduleArg) => Promise<Module>
|
||||
// 3. pre-run appended it, var Module = {}; ..generated code..
|
||||
// 4. External script tag defines var Module.
|
||||
// We need to check if Module already exists (e.g. case 3 above).
|
||||
// Substitution will be replaced with actual code on later stage of the build,
|
||||
// this way Closure Compiler will not mangle it (e.g. case 4. above).
|
||||
// Note that if you want to run closure, and also to use Module
|
||||
// after the generated code, you will need to define var Module = {};
|
||||
// before the code. Then that object will be used in the code, and you
|
||||
// can continue to use Module afterwards as well.
|
||||
var Module = moduleArg;
|
||||
|
||||
// Set up the promise that indicates the Module is initialized
|
||||
var readyPromiseResolve, readyPromiseReject;
|
||||
|
||||
var readyPromise = new Promise((resolve, reject) => {
|
||||
readyPromiseResolve = resolve;
|
||||
readyPromiseReject = reject;
|
||||
});
|
||||
|
||||
// Determine the runtime environment we are in. You can customize this by
|
||||
// setting the ENVIRONMENT setting at compile time (see settings.js).
|
||||
// Attempt to auto-detect the environment
|
||||
var ENVIRONMENT_IS_WEB = typeof window == "object";
|
||||
|
||||
var ENVIRONMENT_IS_WORKER = typeof WorkerGlobalScope != "undefined";
|
||||
|
||||
// N.b. Electron.js environment is simultaneously a NODE-environment, but
|
||||
// also a web environment.
|
||||
var ENVIRONMENT_IS_NODE = typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string" && process.type != "renderer";
|
||||
|
||||
if (ENVIRONMENT_IS_NODE) {}
|
||||
|
||||
// --pre-jses are emitted after the Module integration code, so that they can
|
||||
// refer to Module (if they choose; they can also define Module)
|
||||
// Sometimes an existing Module object exists with properties
|
||||
// meant to overwrite the default module functionality. Here
|
||||
// we collect those properties and reapply _after_ we configure
|
||||
// the current environment's defaults to avoid having to be so
|
||||
// defensive during initialization.
|
||||
var moduleOverrides = Object.assign({}, Module);
|
||||
|
||||
var arguments_ = [];
|
||||
|
||||
var thisProgram = "./this.program";
|
||||
|
||||
var quit_ = (status, toThrow) => {
|
||||
throw toThrow;
|
||||
};
|
||||
|
||||
// `/` should be present at the end if `scriptDirectory` is not empty
|
||||
var scriptDirectory = "";
|
||||
|
||||
function locateFile(path) {
|
||||
if (Module["locateFile"]) {
|
||||
return Module["locateFile"](path, scriptDirectory);
|
||||
}
|
||||
return scriptDirectory + path;
|
||||
}
|
||||
|
||||
// Hooks that are implemented differently in different runtime environments.
|
||||
var readAsync, readBinary;
|
||||
|
||||
if (ENVIRONMENT_IS_NODE) {
|
||||
// These modules will usually be used on Node.js. Load them eagerly to avoid
|
||||
// the complexity of lazy-loading.
|
||||
var fs = require("fs");
|
||||
var nodePath = require("path");
|
||||
scriptDirectory = __dirname + "/";
|
||||
// include: node_shell_read.js
|
||||
readBinary = filename => {
|
||||
// We need to re-wrap `file://` strings to URLs. Normalizing isn't
|
||||
// necessary in that case, the path should already be absolute.
|
||||
filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);
|
||||
var ret = fs.readFileSync(filename);
|
||||
return ret;
|
||||
};
|
||||
readAsync = (filename, binary = true) => {
|
||||
// See the comment in the `readBinary` function.
|
||||
filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(filename, binary ? undefined : "utf8", (err, data) => {
|
||||
if (err) reject(err); else resolve(binary ? data.buffer : data);
|
||||
});
|
||||
});
|
||||
};
|
||||
// end include: node_shell_read.js
|
||||
if (!Module["thisProgram"] && process.argv.length > 1) {
|
||||
thisProgram = process.argv[1].replace(/\\/g, "/");
|
||||
}
|
||||
arguments_ = process.argv.slice(2);
|
||||
// MODULARIZE will export the module in the proper place outside, we don't need to export here
|
||||
quit_ = (status, toThrow) => {
|
||||
process.exitCode = status;
|
||||
throw toThrow;
|
||||
};
|
||||
} else // Note that this includes Node.js workers when relevant (pthreads is enabled).
|
||||
// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and
|
||||
// ENVIRONMENT_IS_NODE.
|
||||
if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
|
||||
if (ENVIRONMENT_IS_WORKER) {
|
||||
// Check worker, not web, since window could be polyfilled
|
||||
scriptDirectory = self.location.href;
|
||||
} else if (typeof document != "undefined" && document.currentScript) {
|
||||
// web
|
||||
scriptDirectory = document.currentScript.src;
|
||||
}
|
||||
// When MODULARIZE, this JS may be executed later, after document.currentScript
|
||||
// is gone, so we saved it, and we use it here instead of any other info.
|
||||
if (_scriptName) {
|
||||
scriptDirectory = _scriptName;
|
||||
}
|
||||
// blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them.
|
||||
// otherwise, slice off the final part of the url to find the script directory.
|
||||
// if scriptDirectory does not contain a slash, lastIndexOf will return -1,
|
||||
// and scriptDirectory will correctly be replaced with an empty string.
|
||||
// If scriptDirectory contains a query (starting with ?) or a fragment (starting with #),
|
||||
// they are removed because they could contain a slash.
|
||||
if (scriptDirectory.startsWith("blob:")) {
|
||||
scriptDirectory = "";
|
||||
} else {
|
||||
scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1);
|
||||
}
|
||||
{
|
||||
// include: web_or_worker_shell_read.js
|
||||
if (ENVIRONMENT_IS_WORKER) {
|
||||
readBinary = url => {
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.open("GET", url, false);
|
||||
xhr.responseType = "arraybuffer";
|
||||
xhr.send(null);
|
||||
return new Uint8Array(/** @type{!ArrayBuffer} */ (xhr.response));
|
||||
};
|
||||
}
|
||||
readAsync = url => {
|
||||
// Fetch has some additional restrictions over XHR, like it can't be used on a file:// url.
|
||||
// See https://github.com/github/fetch/pull/92#issuecomment-140665932
|
||||
// Cordova or Electron apps are typically loaded from a file:// url.
|
||||
// So use XHR on webview if URL is a file URL.
|
||||
if (isFileURI(url)) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.open("GET", url, true);
|
||||
xhr.responseType = "arraybuffer";
|
||||
xhr.onload = () => {
|
||||
if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) {
|
||||
// file URLs can return 0
|
||||
resolve(xhr.response);
|
||||
return;
|
||||
}
|
||||
reject(xhr.status);
|
||||
};
|
||||
xhr.onerror = reject;
|
||||
xhr.send(null);
|
||||
});
|
||||
}
|
||||
return fetch(url, {
|
||||
credentials: "same-origin"
|
||||
}).then(response => {
|
||||
if (response.ok) {
|
||||
return response.arrayBuffer();
|
||||
}
|
||||
return Promise.reject(new Error(response.status + " : " + response.url));
|
||||
});
|
||||
};
|
||||
}
|
||||
} else // end include: web_or_worker_shell_read.js
|
||||
{}
|
||||
|
||||
var out = Module["print"] || console.log.bind(console);
|
||||
|
||||
var err = Module["printErr"] || console.error.bind(console);
|
||||
|
||||
// Merge back in the overrides
|
||||
Object.assign(Module, moduleOverrides);
|
||||
|
||||
// Free the object hierarchy contained in the overrides, this lets the GC
|
||||
// reclaim data used.
|
||||
moduleOverrides = null;
|
||||
|
||||
// Emit code to handle expected values on the Module object. This applies Module.x
|
||||
// to the proper local x. This has two benefits: first, we only emit it if it is
|
||||
// expected to arrive, and second, by using a local everywhere else that can be
|
||||
// minified.
|
||||
if (Module["arguments"]) arguments_ = Module["arguments"];
|
||||
|
||||
if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
|
||||
|
||||
// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message
|
||||
// end include: shell.js
|
||||
// include: preamble.js
|
||||
// === Preamble library stuff ===
|
||||
// Documentation for the public APIs defined in this file must be updated in:
|
||||
// site/source/docs/api_reference/preamble.js.rst
|
||||
// A prebuilt local version of the documentation is available at:
|
||||
// site/build/text/docs/api_reference/preamble.js.txt
|
||||
// You can also build docs locally as HTML or other formats in site/
|
||||
// An online HTML version (which may be of a different version of Emscripten)
|
||||
// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
|
||||
var wasmBinary = Module["wasmBinary"];
|
||||
|
||||
// Wasm globals
|
||||
var wasmMemory;
|
||||
|
||||
//========================================
|
||||
// Runtime essentials
|
||||
//========================================
|
||||
// whether we are quitting the application. no code should run after this.
|
||||
// set in exit() and abort()
|
||||
var ABORT = false;
|
||||
|
||||
// set by exit() and abort(). Passed to 'onExit' handler.
|
||||
// NOTE: This is also used as the process return code code in shell environments
|
||||
// but only when noExitRuntime is false.
|
||||
var EXITSTATUS;
|
||||
|
||||
// Memory management
|
||||
var /** @type {!Int8Array} */ HEAP8, /** @type {!Uint8Array} */ HEAPU8, /** @type {!Int16Array} */ HEAP16, /** @type {!Uint16Array} */ HEAPU16, /** @type {!Int32Array} */ HEAP32, /** @type {!Uint32Array} */ HEAPU32, /** @type {!Float32Array} */ HEAPF32, /** @type {!Float64Array} */ HEAPF64;
|
||||
|
||||
// include: runtime_shared.js
|
||||
function updateMemoryViews() {
|
||||
var b = wasmMemory.buffer;
|
||||
Module["HEAP8"] = HEAP8 = new Int8Array(b);
|
||||
Module["HEAP16"] = HEAP16 = new Int16Array(b);
|
||||
Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
|
||||
Module["HEAPU16"] = HEAPU16 = new Uint16Array(b);
|
||||
Module["HEAP32"] = HEAP32 = new Int32Array(b);
|
||||
Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
|
||||
Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
|
||||
Module["HEAPF64"] = HEAPF64 = new Float64Array(b);
|
||||
}
|
||||
|
||||
// end include: runtime_shared.js
|
||||
// include: runtime_stack_check.js
|
||||
// end include: runtime_stack_check.js
|
||||
var __ATPRERUN__ = [];
|
||||
|
||||
// functions called before the runtime is initialized
|
||||
var __ATINIT__ = [];
|
||||
|
||||
// functions called during startup
|
||||
var __ATMAIN__ = [];
|
||||
|
||||
// functions called during shutdown
|
||||
var __ATPOSTRUN__ = [];
|
||||
|
||||
// functions called after the main() is called
|
||||
var runtimeInitialized = false;
|
||||
|
||||
function preRun() {
|
||||
if (Module["preRun"]) {
|
||||
if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
|
||||
while (Module["preRun"].length) {
|
||||
addOnPreRun(Module["preRun"].shift());
|
||||
}
|
||||
}
|
||||
callRuntimeCallbacks(__ATPRERUN__);
|
||||
}
|
||||
|
||||
function initRuntime() {
|
||||
runtimeInitialized = true;
|
||||
callRuntimeCallbacks(__ATINIT__);
|
||||
}
|
||||
|
||||
function preMain() {
|
||||
callRuntimeCallbacks(__ATMAIN__);
|
||||
}
|
||||
|
||||
function postRun() {
|
||||
if (Module["postRun"]) {
|
||||
if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
|
||||
while (Module["postRun"].length) {
|
||||
addOnPostRun(Module["postRun"].shift());
|
||||
}
|
||||
}
|
||||
callRuntimeCallbacks(__ATPOSTRUN__);
|
||||
}
|
||||
|
||||
function addOnPreRun(cb) {
|
||||
__ATPRERUN__.unshift(cb);
|
||||
}
|
||||
|
||||
function addOnInit(cb) {
|
||||
__ATINIT__.unshift(cb);
|
||||
}
|
||||
|
||||
function addOnPostRun(cb) {
|
||||
__ATPOSTRUN__.unshift(cb);
|
||||
}
|
||||
|
||||
// include: runtime_math.js
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
|
||||
// end include: runtime_math.js
|
||||
// A counter of dependencies for calling run(). If we need to
|
||||
// do asynchronous work before running, increment this and
|
||||
// decrement it. Incrementing must happen in a place like
|
||||
// Module.preRun (used by emcc to add file preloading).
|
||||
// Note that you can add dependencies in preRun, even though
|
||||
// it happens right before run - run will be postponed until
|
||||
// the dependencies are met.
|
||||
var runDependencies = 0;
|
||||
|
||||
var runDependencyWatcher = null;
|
||||
|
||||
var dependenciesFulfilled = null;
|
||||
|
||||
function addRunDependency(id) {
|
||||
runDependencies++;
|
||||
Module["monitorRunDependencies"]?.(runDependencies);
|
||||
}
|
||||
|
||||
function removeRunDependency(id) {
|
||||
runDependencies--;
|
||||
Module["monitorRunDependencies"]?.(runDependencies);
|
||||
if (runDependencies == 0) {
|
||||
if (runDependencyWatcher !== null) {
|
||||
clearInterval(runDependencyWatcher);
|
||||
runDependencyWatcher = null;
|
||||
}
|
||||
if (dependenciesFulfilled) {
|
||||
var callback = dependenciesFulfilled;
|
||||
dependenciesFulfilled = null;
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {string|number=} what */ function abort(what) {
|
||||
Module["onAbort"]?.(what);
|
||||
what = "Aborted(" + what + ")";
|
||||
// TODO(sbc): Should we remove printing and leave it up to whoever
|
||||
// catches the exception?
|
||||
err(what);
|
||||
ABORT = true;
|
||||
what += ". Build with -sASSERTIONS for more info.";
|
||||
// Use a wasm runtime error, because a JS error might be seen as a foreign
|
||||
// exception, which means we'd run destructors on it. We need the error to
|
||||
// simply make the program stop.
|
||||
// FIXME This approach does not work in Wasm EH because it currently does not assume
|
||||
// all RuntimeErrors are from traps; it decides whether a RuntimeError is from
|
||||
// a trap or not based on a hidden field within the object. So at the moment
|
||||
// we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that
|
||||
// allows this in the wasm spec.
|
||||
// Suppress closure compiler warning here. Closure compiler's builtin extern
|
||||
// definition for WebAssembly.RuntimeError claims it takes no arguments even
|
||||
// though it can.
|
||||
// TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.
|
||||
/** @suppress {checkTypes} */ var e = new WebAssembly.RuntimeError(what);
|
||||
readyPromiseReject(e);
|
||||
// Throw the error whether or not MODULARIZE is set because abort is used
|
||||
// in code paths apart from instantiation where an exception is expected
|
||||
// to be thrown when abort is called.
|
||||
throw e;
|
||||
}
|
||||
|
||||
// include: memoryprofiler.js
|
||||
// end include: memoryprofiler.js
|
||||
// include: URIUtils.js
|
||||
// Prefix of data URIs emitted by SINGLE_FILE and related options.
|
||||
var dataURIPrefix = "data:application/octet-stream;base64,";
|
||||
|
||||
/**
|
||||
* Indicates whether filename is a base64 data URI.
|
||||
* @noinline
|
||||
*/ var isDataURI = filename => filename.startsWith(dataURIPrefix);
|
||||
|
||||
/**
|
||||
* Indicates whether filename is delivered via file protocol (as opposed to http/https)
|
||||
* @noinline
|
||||
*/ var isFileURI = filename => filename.startsWith("file://");
|
||||
|
||||
// end include: URIUtils.js
|
||||
// include: runtime_exceptions.js
|
||||
// end include: runtime_exceptions.js
|
||||
function findWasmBinary() {
|
||||
var f = "HashSet.wasm";
|
||||
if (!isDataURI(f)) {
|
||||
return locateFile(f);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
var wasmBinaryFile;
|
||||
|
||||
function getBinarySync(file) {
|
||||
if (file == wasmBinaryFile && wasmBinary) {
|
||||
return new Uint8Array(wasmBinary);
|
||||
}
|
||||
if (readBinary) {
|
||||
return readBinary(file);
|
||||
}
|
||||
throw "both async and sync fetching of the wasm failed";
|
||||
}
|
||||
|
||||
function getBinaryPromise(binaryFile) {
|
||||
// If we don't have the binary yet, load it asynchronously using readAsync.
|
||||
if (!wasmBinary) {
|
||||
// Fetch the binary using readAsync
|
||||
return readAsync(binaryFile).then(response => new Uint8Array(/** @type{!ArrayBuffer} */ (response)), // Fall back to getBinarySync if readAsync fails
|
||||
() => getBinarySync(binaryFile));
|
||||
}
|
||||
// Otherwise, getBinarySync should be able to get it synchronously
|
||||
return Promise.resolve().then(() => getBinarySync(binaryFile));
|
||||
}
|
||||
|
||||
function instantiateArrayBuffer(binaryFile, imports, receiver) {
|
||||
return getBinaryPromise(binaryFile).then(binary => WebAssembly.instantiate(binary, imports)).then(receiver, reason => {
|
||||
err(`failed to asynchronously prepare wasm: ${reason}`);
|
||||
abort(reason);
|
||||
});
|
||||
}
|
||||
|
||||
function instantiateAsync(binary, binaryFile, imports, callback) {
|
||||
if (!binary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(binaryFile) && // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously.
|
||||
!isFileURI(binaryFile) && // Avoid instantiateStreaming() on Node.js environment for now, as while
|
||||
// Node.js v18.1.0 implements it, it does not have a full fetch()
|
||||
// implementation yet.
|
||||
// Reference:
|
||||
// https://github.com/emscripten-core/emscripten/pull/16917
|
||||
!ENVIRONMENT_IS_NODE && typeof fetch == "function") {
|
||||
return fetch(binaryFile, {
|
||||
credentials: "same-origin"
|
||||
}).then(response => {
|
||||
// Suppress closure warning here since the upstream definition for
|
||||
// instantiateStreaming only allows Promise<Repsponse> rather than
|
||||
// an actual Response.
|
||||
// TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed.
|
||||
/** @suppress {checkTypes} */ var result = WebAssembly.instantiateStreaming(response, imports);
|
||||
return result.then(callback, function(reason) {
|
||||
// We expect the most common failure cause to be a bad MIME type for the binary,
|
||||
// in which case falling back to ArrayBuffer instantiation should work.
|
||||
err(`wasm streaming compile failed: ${reason}`);
|
||||
err("falling back to ArrayBuffer instantiation");
|
||||
return instantiateArrayBuffer(binaryFile, imports, callback);
|
||||
});
|
||||
});
|
||||
}
|
||||
return instantiateArrayBuffer(binaryFile, imports, callback);
|
||||
}
|
||||
|
||||
function getWasmImports() {
|
||||
// prepare imports
|
||||
return {
|
||||
"env": wasmImports,
|
||||
"wasi_snapshot_preview1": wasmImports
|
||||
};
|
||||
}
|
||||
|
||||
// Create the wasm instance.
|
||||
// Receives the wasm imports, returns the exports.
|
||||
function createWasm() {
|
||||
// Load the wasm module and create an instance of using native support in the JS engine.
|
||||
// handle a generated wasm instance, receiving its exports and
|
||||
// performing other necessary setup
|
||||
/** @param {WebAssembly.Module=} module*/ function receiveInstance(instance, module) {
|
||||
wasmExports = instance.exports;
|
||||
wasmMemory = wasmExports["memory"];
|
||||
updateMemoryViews();
|
||||
addOnInit(wasmExports["__wasm_call_ctors"]);
|
||||
removeRunDependency("wasm-instantiate");
|
||||
return wasmExports;
|
||||
}
|
||||
// wait for the pthread pool (if any)
|
||||
addRunDependency("wasm-instantiate");
|
||||
// Prefer streaming instantiation if available.
|
||||
function receiveInstantiationResult(result) {
|
||||
// 'result' is a ResultObject object which has both the module and instance.
|
||||
// receiveInstance() will swap in the exports (to Module.asm) so they can be called
|
||||
// TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
|
||||
// When the regression is fixed, can restore the above PTHREADS-enabled path.
|
||||
receiveInstance(result["instance"]);
|
||||
}
|
||||
var info = getWasmImports();
|
||||
// User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
|
||||
// to manually instantiate the Wasm module themselves. This allows pages to
|
||||
// run the instantiation parallel to any other async startup actions they are
|
||||
// performing.
|
||||
// Also pthreads and wasm workers initialize the wasm instance through this
|
||||
// path.
|
||||
if (Module["instantiateWasm"]) {
|
||||
try {
|
||||
return Module["instantiateWasm"](info, receiveInstance);
|
||||
} catch (e) {
|
||||
err(`Module.instantiateWasm callback failed with error: ${e}`);
|
||||
// If instantiation fails, reject the module ready promise.
|
||||
readyPromiseReject(e);
|
||||
}
|
||||
}
|
||||
wasmBinaryFile ??= findWasmBinary();
|
||||
// If instantiation fails, reject the module ready promise.
|
||||
instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult).catch(readyPromiseReject);
|
||||
return {};
|
||||
}
|
||||
|
||||
// include: runtime_debug.js
|
||||
// end include: runtime_debug.js
|
||||
// === Body ===
|
||||
// end include: preamble.js
|
||||
class ExitStatus {
|
||||
name="ExitStatus";
|
||||
constructor(status) {
|
||||
this.message = `Program terminated with exit(${status})`;
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
|
||||
var callRuntimeCallbacks = callbacks => {
|
||||
while (callbacks.length > 0) {
|
||||
// Pass the module as the first argument.
|
||||
callbacks.shift()(Module);
|
||||
}
|
||||
};
|
||||
|
||||
var noExitRuntime = Module["noExitRuntime"] || true;
|
||||
|
||||
var __abort_js = () => abort("");
|
||||
|
||||
var __emscripten_memcpy_js = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num);
|
||||
|
||||
var _emscripten_date_now = () => Date.now();
|
||||
|
||||
var abortOnCannotGrowMemory = requestedSize => {
|
||||
abort("OOM");
|
||||
};
|
||||
|
||||
var _emscripten_resize_heap = requestedSize => {
|
||||
var oldSize = HEAPU8.length;
|
||||
// With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
|
||||
requestedSize >>>= 0;
|
||||
abortOnCannotGrowMemory(requestedSize);
|
||||
};
|
||||
|
||||
var _fd_close = fd => 52;
|
||||
|
||||
var convertI32PairToI53Checked = (lo, hi) => ((hi + 2097152) >>> 0 < 4194305 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN;
|
||||
|
||||
function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
|
||||
var offset = convertI32PairToI53Checked(offset_low, offset_high);
|
||||
return 70;
|
||||
}
|
||||
|
||||
var printCharBuffers = [ null, [], [] ];
|
||||
|
||||
var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder : undefined;
|
||||
|
||||
/**
|
||||
* Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
|
||||
* array that contains uint8 values, returns a copy of that string as a
|
||||
* Javascript String object.
|
||||
* heapOrArray is either a regular array, or a JavaScript typed array view.
|
||||
* @param {number=} idx
|
||||
* @param {number=} maxBytesToRead
|
||||
* @return {string}
|
||||
*/ var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead = NaN) => {
|
||||
var endIdx = idx + maxBytesToRead;
|
||||
var endPtr = idx;
|
||||
// TextDecoder needs to know the byte length in advance, it doesn't stop on
|
||||
// null terminator by itself. Also, use the length info to avoid running tiny
|
||||
// strings through TextDecoder, since .subarray() allocates garbage.
|
||||
// (As a tiny code save trick, compare endPtr against endIdx using a negation,
|
||||
// so that undefined/NaN means Infinity)
|
||||
while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
|
||||
if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
|
||||
return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
|
||||
}
|
||||
var str = "";
|
||||
// If building with TextDecoder, we have already computed the string length
|
||||
// above, so test loop end condition against that
|
||||
while (idx < endPtr) {
|
||||
// For UTF8 byte structure, see:
|
||||
// http://en.wikipedia.org/wiki/UTF-8#Description
|
||||
// https://www.ietf.org/rfc/rfc2279.txt
|
||||
// https://tools.ietf.org/html/rfc3629
|
||||
var u0 = heapOrArray[idx++];
|
||||
if (!(u0 & 128)) {
|
||||
str += String.fromCharCode(u0);
|
||||
continue;
|
||||
}
|
||||
var u1 = heapOrArray[idx++] & 63;
|
||||
if ((u0 & 224) == 192) {
|
||||
str += String.fromCharCode(((u0 & 31) << 6) | u1);
|
||||
continue;
|
||||
}
|
||||
var u2 = heapOrArray[idx++] & 63;
|
||||
if ((u0 & 240) == 224) {
|
||||
u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
|
||||
} else {
|
||||
u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
|
||||
}
|
||||
if (u0 < 65536) {
|
||||
str += String.fromCharCode(u0);
|
||||
} else {
|
||||
var ch = u0 - 65536;
|
||||
str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023));
|
||||
}
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
var printChar = (stream, curr) => {
|
||||
var buffer = printCharBuffers[stream];
|
||||
if (curr === 0 || curr === 10) {
|
||||
(stream === 1 ? out : err)(UTF8ArrayToString(buffer));
|
||||
buffer.length = 0;
|
||||
} else {
|
||||
buffer.push(curr);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
|
||||
* emscripten HEAP, returns a copy of that string as a Javascript String object.
|
||||
*
|
||||
* @param {number} ptr
|
||||
* @param {number=} maxBytesToRead - An optional length that specifies the
|
||||
* maximum number of bytes to read. You can omit this parameter to scan the
|
||||
* string until the first 0 byte. If maxBytesToRead is passed, and the string
|
||||
* at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
|
||||
* string will cut short at that byte index (i.e. maxBytesToRead will not
|
||||
* produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing
|
||||
* frequent uses of UTF8ToString() with and without maxBytesToRead may throw
|
||||
* JS JIT optimizations off, so it is worth to consider consistently using one
|
||||
* @return {string}
|
||||
*/ var UTF8ToString = (ptr, maxBytesToRead) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
|
||||
|
||||
var _fd_write = (fd, iov, iovcnt, pnum) => {
|
||||
// hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0
|
||||
var num = 0;
|
||||
for (var i = 0; i < iovcnt; i++) {
|
||||
var ptr = HEAPU32[((iov) >> 2)];
|
||||
var len = HEAPU32[(((iov) + (4)) >> 2)];
|
||||
iov += 8;
|
||||
for (var j = 0; j < len; j++) {
|
||||
printChar(fd, HEAPU8[ptr + j]);
|
||||
}
|
||||
num += len;
|
||||
}
|
||||
HEAPU32[((pnum) >> 2)] = num;
|
||||
return 0;
|
||||
};
|
||||
|
||||
var runtimeKeepaliveCounter = 0;
|
||||
|
||||
var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
|
||||
|
||||
var _proc_exit = code => {
|
||||
EXITSTATUS = code;
|
||||
if (!keepRuntimeAlive()) {
|
||||
Module["onExit"]?.(code);
|
||||
ABORT = true;
|
||||
}
|
||||
quit_(code, new ExitStatus(code));
|
||||
};
|
||||
|
||||
/** @param {boolean|number=} implicit */ var exitJS = (status, implicit) => {
|
||||
EXITSTATUS = status;
|
||||
_proc_exit(status);
|
||||
};
|
||||
|
||||
var handleException = e => {
|
||||
// Certain exception types we do not treat as errors since they are used for
|
||||
// internal control flow.
|
||||
// 1. ExitStatus, which is thrown by exit()
|
||||
// 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others
|
||||
// that wish to return to JS event loop.
|
||||
if (e instanceof ExitStatus || e == "unwind") {
|
||||
return EXITSTATUS;
|
||||
}
|
||||
quit_(1, e);
|
||||
};
|
||||
|
||||
var lengthBytesUTF8 = str => {
|
||||
var len = 0;
|
||||
for (var i = 0; i < str.length; ++i) {
|
||||
// Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code
|
||||
// unit, not a Unicode code point of the character! So decode
|
||||
// UTF16->UTF32->UTF8.
|
||||
// See http://unicode.org/faq/utf_bom.html#utf16-3
|
||||
var c = str.charCodeAt(i);
|
||||
// possibly a lead surrogate
|
||||
if (c <= 127) {
|
||||
len++;
|
||||
} else if (c <= 2047) {
|
||||
len += 2;
|
||||
} else if (c >= 55296 && c <= 57343) {
|
||||
len += 4;
|
||||
++i;
|
||||
} else {
|
||||
len += 3;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
};
|
||||
|
||||
var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
|
||||
// Parameter maxBytesToWrite is not optional. Negative values, 0, null,
|
||||
// undefined and false each don't write out any bytes.
|
||||
if (!(maxBytesToWrite > 0)) return 0;
|
||||
var startIdx = outIdx;
|
||||
var endIdx = outIdx + maxBytesToWrite - 1;
|
||||
// -1 for string null terminator.
|
||||
for (var i = 0; i < str.length; ++i) {
|
||||
// Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code
|
||||
// unit, not a Unicode code point of the character! So decode
|
||||
// UTF16->UTF32->UTF8.
|
||||
// See http://unicode.org/faq/utf_bom.html#utf16-3
|
||||
// For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description
|
||||
// and https://www.ietf.org/rfc/rfc2279.txt
|
||||
// and https://tools.ietf.org/html/rfc3629
|
||||
var u = str.charCodeAt(i);
|
||||
// possibly a lead surrogate
|
||||
if (u >= 55296 && u <= 57343) {
|
||||
var u1 = str.charCodeAt(++i);
|
||||
u = 65536 + ((u & 1023) << 10) | (u1 & 1023);
|
||||
}
|
||||
if (u <= 127) {
|
||||
if (outIdx >= endIdx) break;
|
||||
heap[outIdx++] = u;
|
||||
} else if (u <= 2047) {
|
||||
if (outIdx + 1 >= endIdx) break;
|
||||
heap[outIdx++] = 192 | (u >> 6);
|
||||
heap[outIdx++] = 128 | (u & 63);
|
||||
} else if (u <= 65535) {
|
||||
if (outIdx + 2 >= endIdx) break;
|
||||
heap[outIdx++] = 224 | (u >> 12);
|
||||
heap[outIdx++] = 128 | ((u >> 6) & 63);
|
||||
heap[outIdx++] = 128 | (u & 63);
|
||||
} else {
|
||||
if (outIdx + 3 >= endIdx) break;
|
||||
heap[outIdx++] = 240 | (u >> 18);
|
||||
heap[outIdx++] = 128 | ((u >> 12) & 63);
|
||||
heap[outIdx++] = 128 | ((u >> 6) & 63);
|
||||
heap[outIdx++] = 128 | (u & 63);
|
||||
}
|
||||
}
|
||||
// Null-terminate the pointer to the buffer.
|
||||
heap[outIdx] = 0;
|
||||
return outIdx - startIdx;
|
||||
};
|
||||
|
||||
var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
|
||||
|
||||
var stackAlloc = sz => __emscripten_stack_alloc(sz);
|
||||
|
||||
var stringToUTF8OnStack = str => {
|
||||
var size = lengthBytesUTF8(str) + 1;
|
||||
var ret = stackAlloc(size);
|
||||
stringToUTF8(str, ret, size);
|
||||
return ret;
|
||||
};
|
||||
|
||||
var wasmImports = {
|
||||
/** @export */ _abort_js: __abort_js,
|
||||
/** @export */ _emscripten_memcpy_js: __emscripten_memcpy_js,
|
||||
/** @export */ emscripten_date_now: _emscripten_date_now,
|
||||
/** @export */ emscripten_resize_heap: _emscripten_resize_heap,
|
||||
/** @export */ fd_close: _fd_close,
|
||||
/** @export */ fd_seek: _fd_seek,
|
||||
/** @export */ fd_write: _fd_write
|
||||
};
|
||||
|
||||
var wasmExports = createWasm();
|
||||
|
||||
var ___wasm_call_ctors = () => (___wasm_call_ctors = wasmExports["__wasm_call_ctors"])();
|
||||
|
||||
var _main = Module["_main"] = (a0, a1) => (_main = Module["_main"] = wasmExports["__main_argc_argv"])(a0, a1);
|
||||
|
||||
var __emscripten_stack_restore = a0 => (__emscripten_stack_restore = wasmExports["_emscripten_stack_restore"])(a0);
|
||||
|
||||
var __emscripten_stack_alloc = a0 => (__emscripten_stack_alloc = wasmExports["_emscripten_stack_alloc"])(a0);
|
||||
|
||||
var _emscripten_stack_get_current = () => (_emscripten_stack_get_current = wasmExports["emscripten_stack_get_current"])();
|
||||
|
||||
var dynCall_jiji = Module["dynCall_jiji"] = (a0, a1, a2, a3, a4) => (dynCall_jiji = Module["dynCall_jiji"] = wasmExports["dynCall_jiji"])(a0, a1, a2, a3, a4);
|
||||
|
||||
// include: postamble.js
|
||||
// === Auto-generated postamble setup entry stuff ===
|
||||
var calledRun;
|
||||
|
||||
dependenciesFulfilled = function runCaller() {
|
||||
// If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
|
||||
if (!calledRun) run();
|
||||
if (!calledRun) dependenciesFulfilled = runCaller;
|
||||
};
|
||||
|
||||
// try this again later, after new deps are fulfilled
|
||||
function callMain(args = []) {
|
||||
var entryFunction = _main;
|
||||
args.unshift(thisProgram);
|
||||
var argc = args.length;
|
||||
var argv = stackAlloc((argc + 1) * 4);
|
||||
var argv_ptr = argv;
|
||||
args.forEach(arg => {
|
||||
HEAPU32[((argv_ptr) >> 2)] = stringToUTF8OnStack(arg);
|
||||
argv_ptr += 4;
|
||||
});
|
||||
HEAPU32[((argv_ptr) >> 2)] = 0;
|
||||
try {
|
||||
var ret = entryFunction(argc, argv);
|
||||
// if we're not running an evented main loop, it's time to exit
|
||||
exitJS(ret, /* implicit = */ true);
|
||||
return ret;
|
||||
} catch (e) {
|
||||
return handleException(e);
|
||||
}
|
||||
}
|
||||
|
||||
function run(args = arguments_) {
|
||||
if (runDependencies > 0) {
|
||||
return;
|
||||
}
|
||||
preRun();
|
||||
// a preRun added a dependency, run will be called later
|
||||
if (runDependencies > 0) {
|
||||
return;
|
||||
}
|
||||
function doRun() {
|
||||
// run may have just been called through dependencies being fulfilled just in this very frame,
|
||||
// or while the async setStatus time below was happening
|
||||
if (calledRun) return;
|
||||
calledRun = true;
|
||||
Module["calledRun"] = true;
|
||||
if (ABORT) return;
|
||||
initRuntime();
|
||||
preMain();
|
||||
readyPromiseResolve(Module);
|
||||
Module["onRuntimeInitialized"]?.();
|
||||
if (shouldRunNow) callMain(args);
|
||||
postRun();
|
||||
}
|
||||
if (Module["setStatus"]) {
|
||||
Module["setStatus"]("Running...");
|
||||
setTimeout(() => {
|
||||
setTimeout(() => Module["setStatus"](""), 1);
|
||||
doRun();
|
||||
}, 1);
|
||||
} else {
|
||||
doRun();
|
||||
}
|
||||
}
|
||||
|
||||
if (Module["preInit"]) {
|
||||
if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
|
||||
while (Module["preInit"].length > 0) {
|
||||
Module["preInit"].pop()();
|
||||
}
|
||||
}
|
||||
|
||||
// shouldRunNow refers to calling main(), not run().
|
||||
var shouldRunNow = true;
|
||||
|
||||
if (Module["noInitialRun"]) shouldRunNow = false;
|
||||
|
||||
run();
|
||||
|
||||
// end include: postamble.js
|
||||
// include: postamble_modularize.js
|
||||
// In MODULARIZE mode we wrap the generated code in a factory function
|
||||
// and return either the Module itself, or a promise of the module.
|
||||
// We assign to the `moduleRtn` global here and configure closure to see
|
||||
// this as and extern so it won't get minified.
|
||||
moduleRtn = readyPromise;
|
||||
|
||||
|
||||
return moduleRtn;
|
||||
}
|
||||
);
|
||||
})();
|
||||
if (typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = setupModule;
|
||||
else if (typeof define === 'function' && define['amd'])
|
||||
define([], () => setupModule);
|
||||
43
wasm/HashSet/build/HashSet.js.symbols
Normal file
43
wasm/HashSet/build/HashSet.js.symbols
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
0:_abort_js
|
||||
1:emscripten_date_now
|
||||
2:__wasi_fd_close
|
||||
3:__wasi_fd_write
|
||||
4:_emscripten_memcpy_js
|
||||
5:emscripten_resize_heap
|
||||
6:legalimport$__wasi_fd_seek
|
||||
7:__wasm_call_ctors
|
||||
8:WTF::HashTable<JSC::DFG::Node*\2c\20JSC::DFG::Node*\2c\20WTF::IdentityExtractor\2c\20WTF::PtrHash<JSC::DFG::Node*>\2c\20WTF::HashTraits<JSC::DFG::Node*>\2c\20WTF::HashTraits<JSC::DFG::Node*>>::add\28JSC::DFG::Node*&&\29
|
||||
9:WTF::HashTable<unsigned\20int\2c\20unsigned\20int\2c\20WTF::IdentityExtractor\2c\20WTF::IntHash<unsigned\20int>\2c\20WTF::UnsignedWithZeroKeyHashTraits<unsigned\20int>\2c\20WTF::UnsignedWithZeroKeyHashTraits<unsigned\20int>>::add\28unsigned\20int&&\29
|
||||
10:main
|
||||
11:WTF::HashTable<JSC::DFG::Node*\2c\20JSC::DFG::Node*\2c\20WTF::IdentityExtractor\2c\20WTF::PtrHash<JSC::DFG::Node*>\2c\20WTF::HashTraits<JSC::DFG::Node*>\2c\20WTF::HashTraits<JSC::DFG::Node*>>::rehash\28unsigned\20int\2c\20JSC::DFG::Node**\29
|
||||
12:WTF::HashTable<unsigned\20int\2c\20unsigned\20int\2c\20WTF::IdentityExtractor\2c\20WTF::IntHash<unsigned\20int>\2c\20WTF::UnsignedWithZeroKeyHashTraits<unsigned\20int>\2c\20WTF::UnsignedWithZeroKeyHashTraits<unsigned\20int>>::rehash\28unsigned\20int\2c\20unsigned\20int*\29
|
||||
13:abort
|
||||
14:__memset
|
||||
15:__gettimeofday
|
||||
16:fiprintf
|
||||
17:__stdio_close
|
||||
18:__stdio_write
|
||||
19:__stdio_seek
|
||||
20:__emscripten_stdout_close
|
||||
21:__emscripten_stdout_seek
|
||||
22:__towrite
|
||||
23:frexp
|
||||
24:__vfprintf_internal
|
||||
25:printf_core
|
||||
26:out
|
||||
27:getint
|
||||
28:pop_arg
|
||||
29:fmt_u
|
||||
30:pad
|
||||
31:fmt_fp
|
||||
32:__wasi_syscall_ret
|
||||
33:wctomb
|
||||
34:emscripten_builtin_malloc
|
||||
35:emscripten_builtin_free
|
||||
36:emscripten_builtin_calloc
|
||||
37:sbrk
|
||||
38:operator\20new\28unsigned\20long\29
|
||||
39:_emscripten_stack_restore
|
||||
40:_emscripten_stack_alloc
|
||||
41:emscripten_stack_get_current
|
||||
42:legalstub$dynCall_jiji
|
||||
BIN
wasm/HashSet/build/HashSet.wasm
Executable file
BIN
wasm/HashSet/build/HashSet.wasm
Executable file
Binary file not shown.
Loading…
Reference in a new issue