Merge pull request #35 from danleh/hashset-wasm-scoring

Move HashSet-wasm to first, worst, average scoring
diff --git a/JetStreamDriver.js b/JetStreamDriver.js
index 35bb018..766724d 100644
--- a/JetStreamDriver.js
+++ b/JetStreamDriver.js
@@ -1941,13 +1941,14 @@
         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
     }),
diff --git a/wasm/HashSet.js b/wasm/HashSet.js
deleted file mode 100644
index 9507abd..0000000
--- a/wasm/HashSet.js
+++ /dev/null
@@ -1,1139 +0,0 @@
-function doRun() {
-let __startupStartTime = benchmarkTime();
-var moduleOverrides = {};
-var key;
-for (key in Module) {
- if (Module.hasOwnProperty(key)) {
-  moduleOverrides[key] = Module[key];
- }
-}
-Module["arguments"] = [];
-Module["thisProgram"] = "./this.program";
-Module["quit"] = (function(status, toThrow) {
- throw toThrow;
-});
-Module["preRun"] = [];
-Module["postRun"] = [];
-var ENVIRONMENT_IS_WEB = false;
-var ENVIRONMENT_IS_WORKER = false;
-var ENVIRONMENT_IS_NODE = false;
-var ENVIRONMENT_IS_SHELL = false;
-ENVIRONMENT_IS_WEB = typeof window === "object";
-ENVIRONMENT_IS_WORKER = typeof importScripts === "function";
-ENVIRONMENT_IS_NODE = typeof process === "object" && typeof require === "function" && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER;
-ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
-var scriptDirectory = "";
-function locateFile(path) {
- if (Module["locateFile"]) {
-  return Module["locateFile"](path, scriptDirectory);
- } else {
-  return scriptDirectory + path;
- }
-}
-if (ENVIRONMENT_IS_NODE) {
- scriptDirectory = __dirname + "/";
- var nodeFS;
- var nodePath;
- Module["read"] = function shell_read(filename, binary) {
-  var ret;
-  if (!nodeFS) nodeFS = require("fs");
-  if (!nodePath) nodePath = require("path");
-  filename = nodePath["normalize"](filename);
-  ret = nodeFS["readFileSync"](filename);
-  return binary ? ret : ret.toString();
- };
- Module["readBinary"] = function readBinary(filename) {
-  var ret = Module["read"](filename, true);
-  if (!ret.buffer) {
-   ret = new Uint8Array(ret);
-  }
-  assert(ret.buffer);
-  return ret;
- };
- if (process["argv"].length > 1) {
-  Module["thisProgram"] = process["argv"][1].replace(/\\/g, "/");
- }
- Module["arguments"] = process["argv"].slice(2);
- if (typeof module !== "undefined") {
-  module["exports"] = Module;
- }
- process["on"]("uncaughtException", (function(ex) {
-  if (!(ex instanceof ExitStatus)) {
-   throw ex;
-  }
- }));
- process["on"]("unhandledRejection", (function(reason, p) {
-  process["exit"](1);
- }));
- Module["quit"] = (function(status) {
-  process["exit"](status);
- });
- Module["inspect"] = (function() {
-  return "[Emscripten Module object]";
- });
-} else if (ENVIRONMENT_IS_SHELL) {
- if (typeof read != "undefined") {
-  Module["read"] = function shell_read(f) {
-   return read(f);
-  };
- }
- Module["readBinary"] = function readBinary(f) {
-  var data;
-  if (typeof readbuffer === "function") {
-   return new Uint8Array(readbuffer(f));
-  }
-  data = read(f, "binary");
-  assert(typeof data === "object");
-  return data;
- };
- if (typeof scriptArgs != "undefined") {
-  Module["arguments"] = scriptArgs;
- } else if (typeof arguments != "undefined") {
-  Module["arguments"] = arguments;
- }
- if (typeof quit === "function") {
-  Module["quit"] = (function(status) {
-   quit(status);
-  });
- }
-} else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
- if (ENVIRONMENT_IS_WEB) {
-  if (document.currentScript) {
-   scriptDirectory = document.currentScript.src;
-  }
- } else {
-  scriptDirectory = self.location.href;
- }
- if (scriptDirectory.indexOf("blob:") !== 0) {
-  scriptDirectory = scriptDirectory.split("/").slice(0, -1).join("/") + "/";
- } else {
-  scriptDirectory = "";
- }
- Module["read"] = function shell_read(url) {
-  var xhr = new XMLHttpRequest;
-  xhr.open("GET", url, false);
-  xhr.send(null);
-  return xhr.responseText;
- };
- if (ENVIRONMENT_IS_WORKER) {
-  Module["readBinary"] = function readBinary(url) {
-   var xhr = new XMLHttpRequest;
-   xhr.open("GET", url, false);
-   xhr.responseType = "arraybuffer";
-   xhr.send(null);
-   return new Uint8Array(xhr.response);
-  };
- }
- Module["readAsync"] = function readAsync(url, onload, onerror) {
-  var xhr = new XMLHttpRequest;
-  xhr.open("GET", url, true);
-  xhr.responseType = "arraybuffer";
-  xhr.onload = function xhr_onload() {
-   if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
-    onload(xhr.response);
-    return;
-   }
-   onerror();
-  };
-  xhr.onerror = onerror;
-  xhr.send(null);
- };
- Module["setWindowTitle"] = (function(title) {
-  document.title = title;
- });
-} else {}
-var out = Module["print"] || (typeof console !== "undefined" ? console.log.bind(console) : typeof print !== "undefined" ? print : null);
-var err = Module["printErr"] || (typeof printErr !== "undefined" ? printErr : typeof console !== "undefined" && console.warn.bind(console) || out);
-for (key in moduleOverrides) {
- if (moduleOverrides.hasOwnProperty(key)) {
-  Module[key] = moduleOverrides[key];
- }
-}
-moduleOverrides = undefined;
-var STACK_ALIGN = 16;
-function staticAlloc(size) {
- var ret = STATICTOP;
- STATICTOP = STATICTOP + size + 15 & -16;
- return ret;
-}
-function alignMemory(size, factor) {
- if (!factor) factor = STACK_ALIGN;
- var ret = size = Math.ceil(size / factor) * factor;
- return ret;
-}
-var asm2wasmImports = {
- "f64-rem": (function(x, y) {
-  return x % y;
- }),
- "debugger": (function() {
-  debugger;
- })
-};
-var functionPointers = new Array(0);
-var GLOBAL_BASE = 1024;
-var ABORT = 0;
-var EXITSTATUS = 0;
-function assert(condition, text) {
- if (!condition) {
-  abort("Assertion failed: " + text);
- }
-}
-function Pointer_stringify(ptr, length) {
- if (length === 0 || !ptr) return "";
- var hasUtf = 0;
- var t;
- var i = 0;
- while (1) {
-  t = HEAPU8[ptr + i >> 0];
-  hasUtf |= t;
-  if (t == 0 && !length) break;
-  i++;
-  if (length && i == length) break;
- }
- if (!length) length = i;
- var ret = "";
- if (hasUtf < 128) {
-  var MAX_CHUNK = 1024;
-  var curr;
-  while (length > 0) {
-   curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK)));
-   ret = ret ? ret + curr : curr;
-   ptr += MAX_CHUNK;
-   length -= MAX_CHUNK;
-  }
-  return ret;
- }
- return UTF8ToString(ptr);
-}
-var UTF8Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf8") : undefined;
-function UTF8ArrayToString(u8Array, idx) {
- var endPtr = idx;
- while (u8Array[endPtr]) ++endPtr;
- if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) {
-  return UTF8Decoder.decode(u8Array.subarray(idx, endPtr));
- } else {
-  var u0, u1, u2, u3, u4, u5;
-  var str = "";
-  while (1) {
-   u0 = u8Array[idx++];
-   if (!u0) return str;
-   if (!(u0 & 128)) {
-    str += String.fromCharCode(u0);
-    continue;
-   }
-   u1 = u8Array[idx++] & 63;
-   if ((u0 & 224) == 192) {
-    str += String.fromCharCode((u0 & 31) << 6 | u1);
-    continue;
-   }
-   u2 = u8Array[idx++] & 63;
-   if ((u0 & 240) == 224) {
-    u0 = (u0 & 15) << 12 | u1 << 6 | u2;
-   } else {
-    u3 = u8Array[idx++] & 63;
-    if ((u0 & 248) == 240) {
-     u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | u3;
-    } else {
-     u4 = u8Array[idx++] & 63;
-     if ((u0 & 252) == 248) {
-      u0 = (u0 & 3) << 24 | u1 << 18 | u2 << 12 | u3 << 6 | u4;
-     } else {
-      u5 = u8Array[idx++] & 63;
-      u0 = (u0 & 1) << 30 | u1 << 24 | u2 << 18 | u3 << 12 | u4 << 6 | u5;
-     }
-    }
-   }
-   if (u0 < 65536) {
-    str += String.fromCharCode(u0);
-   } else {
-    var ch = u0 - 65536;
-    str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
-   }
-  }
- }
-}
-function UTF8ToString(ptr) {
- return UTF8ArrayToString(HEAPU8, ptr);
-}
-function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) {
- if (!(maxBytesToWrite > 0)) return 0;
- var startIdx = outIdx;
- var endIdx = outIdx + maxBytesToWrite - 1;
- for (var i = 0; i < str.length; ++i) {
-  var u = str.charCodeAt(i);
-  if (u >= 55296 && u <= 57343) {
-   var u1 = str.charCodeAt(++i);
-   u = 65536 + ((u & 1023) << 10) | u1 & 1023;
-  }
-  if (u <= 127) {
-   if (outIdx >= endIdx) break;
-   outU8Array[outIdx++] = u;
-  } else if (u <= 2047) {
-   if (outIdx + 1 >= endIdx) break;
-   outU8Array[outIdx++] = 192 | u >> 6;
-   outU8Array[outIdx++] = 128 | u & 63;
-  } else if (u <= 65535) {
-   if (outIdx + 2 >= endIdx) break;
-   outU8Array[outIdx++] = 224 | u >> 12;
-   outU8Array[outIdx++] = 128 | u >> 6 & 63;
-   outU8Array[outIdx++] = 128 | u & 63;
-  } else if (u <= 2097151) {
-   if (outIdx + 3 >= endIdx) break;
-   outU8Array[outIdx++] = 240 | u >> 18;
-   outU8Array[outIdx++] = 128 | u >> 12 & 63;
-   outU8Array[outIdx++] = 128 | u >> 6 & 63;
-   outU8Array[outIdx++] = 128 | u & 63;
-  } else if (u <= 67108863) {
-   if (outIdx + 4 >= endIdx) break;
-   outU8Array[outIdx++] = 248 | u >> 24;
-   outU8Array[outIdx++] = 128 | u >> 18 & 63;
-   outU8Array[outIdx++] = 128 | u >> 12 & 63;
-   outU8Array[outIdx++] = 128 | u >> 6 & 63;
-   outU8Array[outIdx++] = 128 | u & 63;
-  } else {
-   if (outIdx + 5 >= endIdx) break;
-   outU8Array[outIdx++] = 252 | u >> 30;
-   outU8Array[outIdx++] = 128 | u >> 24 & 63;
-   outU8Array[outIdx++] = 128 | u >> 18 & 63;
-   outU8Array[outIdx++] = 128 | u >> 12 & 63;
-   outU8Array[outIdx++] = 128 | u >> 6 & 63;
-   outU8Array[outIdx++] = 128 | u & 63;
-  }
- }
- outU8Array[outIdx] = 0;
- return outIdx - startIdx;
-}
-function lengthBytesUTF8(str) {
- var len = 0;
- for (var i = 0; i < str.length; ++i) {
-  var u = str.charCodeAt(i);
-  if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023;
-  if (u <= 127) {
-   ++len;
-  } else if (u <= 2047) {
-   len += 2;
-  } else if (u <= 65535) {
-   len += 3;
-  } else if (u <= 2097151) {
-   len += 4;
-  } else if (u <= 67108863) {
-   len += 5;
-  } else {
-   len += 6;
-  }
- }
- return len;
-}
-var UTF16Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-16le") : undefined;
-function allocateUTF8OnStack(str) {
- var size = lengthBytesUTF8(str) + 1;
- var ret = stackAlloc(size);
- stringToUTF8Array(str, HEAP8, ret, size);
- return ret;
-}
-var WASM_PAGE_SIZE = 65536;
-var ASMJS_PAGE_SIZE = 16777216;
-function alignUp(x, multiple) {
- if (x % multiple > 0) {
-  x += multiple - x % multiple;
- }
- return x;
-}
-var buffer, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
-function updateGlobalBuffer(buf) {
- Module["buffer"] = buffer = buf;
-}
-function updateGlobalBufferViews() {
- Module["HEAP8"] = HEAP8 = new Int8Array(buffer);
- Module["HEAP16"] = HEAP16 = new Int16Array(buffer);
- Module["HEAP32"] = HEAP32 = new Int32Array(buffer);
- Module["HEAPU8"] = HEAPU8 = new Uint8Array(buffer);
- Module["HEAPU16"] = HEAPU16 = new Uint16Array(buffer);
- Module["HEAPU32"] = HEAPU32 = new Uint32Array(buffer);
- Module["HEAPF32"] = HEAPF32 = new Float32Array(buffer);
- Module["HEAPF64"] = HEAPF64 = new Float64Array(buffer);
-}
-var STATIC_BASE, STATICTOP, staticSealed;
-var STACK_BASE, STACKTOP, STACK_MAX;
-var DYNAMIC_BASE, DYNAMICTOP_PTR;
-STATIC_BASE = STATICTOP = STACK_BASE = STACKTOP = STACK_MAX = DYNAMIC_BASE = DYNAMICTOP_PTR = 0;
-staticSealed = false;
-function abortOnCannotGrowMemory() {
- abort("Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value " + TOTAL_MEMORY + ", (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 ");
-}
-function enlargeMemory() {
- abortOnCannotGrowMemory();
-}
-var TOTAL_STACK = Module["TOTAL_STACK"] || 5242880;
-var TOTAL_MEMORY = Module["TOTAL_MEMORY"] || 134217728;
-if (TOTAL_MEMORY < TOTAL_STACK) err("TOTAL_MEMORY should be larger than TOTAL_STACK, was " + TOTAL_MEMORY + "! (TOTAL_STACK=" + TOTAL_STACK + ")");
-if (Module["buffer"]) {
- buffer = Module["buffer"];
-} else {
- if (typeof WebAssembly === "object" && typeof WebAssembly.Memory === "function") {
-  Module["wasmMemory"] = new WebAssembly.Memory({
-   "initial": TOTAL_MEMORY / WASM_PAGE_SIZE,
-   "maximum": TOTAL_MEMORY / WASM_PAGE_SIZE
-  });
-  buffer = Module["wasmMemory"].buffer;
- } else {
-  buffer = new ArrayBuffer(TOTAL_MEMORY);
- }
- Module["buffer"] = buffer;
-}
-updateGlobalBufferViews();
-function getTotalMemory() {
- return TOTAL_MEMORY;
-}
-function callRuntimeCallbacks(callbacks) {
- while (callbacks.length > 0) {
-  var callback = callbacks.shift();
-  if (typeof callback == "function") {
-   callback();
-   continue;
-  }
-  var func = callback.func;
-  if (typeof func === "number") {
-   if (callback.arg === undefined) {
-    Module["dynCall_v"](func);
-   } else {
-    Module["dynCall_vi"](func, callback.arg);
-   }
-  } else {
-   func(callback.arg === undefined ? null : callback.arg);
-  }
- }
-}
-var __ATPRERUN__ = [];
-var __ATINIT__ = [];
-var __ATMAIN__ = [];
-var __ATEXIT__ = [];
-var __ATPOSTRUN__ = [];
-var runtimeInitialized = false;
-var runtimeExited = 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 ensureInitRuntime() {
- if (runtimeInitialized) return;
- runtimeInitialized = true;
- callRuntimeCallbacks(__ATINIT__);
-}
-function preMain() {
- callRuntimeCallbacks(__ATMAIN__);
-}
-function exitRuntime() {
- callRuntimeCallbacks(__ATEXIT__);
- runtimeExited = true;
-}
-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 addOnPostRun(cb) {
- __ATPOSTRUN__.unshift(cb);
-}
-var runDependencies = 0;
-var runDependencyWatcher = null;
-var dependenciesFulfilled = null;
-function addRunDependency(id) {
- runDependencies++;
- if (Module["monitorRunDependencies"]) {
-  Module["monitorRunDependencies"](runDependencies);
- }
-}
-function removeRunDependency(id) {
- runDependencies--;
- if (Module["monitorRunDependencies"]) {
-  Module["monitorRunDependencies"](runDependencies);
- }
- if (runDependencies == 0) {
-  if (runDependencyWatcher !== null) {
-   clearInterval(runDependencyWatcher);
-   runDependencyWatcher = null;
-  }
-  if (dependenciesFulfilled) {
-   var callback = dependenciesFulfilled;
-   dependenciesFulfilled = null;
-   callback();
-  }
- }
-}
-Module["preloadedImages"] = {};
-Module["preloadedAudios"] = {};
-var dataURIPrefix = "data:application/octet-stream;base64,";
-function isDataURI(filename) {
- return String.prototype.startsWith ? filename.startsWith(dataURIPrefix) : filename.indexOf(dataURIPrefix) === 0;
-}
-function integrateWasmJS() {
- var wasmTextFile = "HashSet.wast";
- var wasmBinaryFile = "HashSet.wasm";
- var asmjsCodeFile = "HashSet.temp.asm.js";
- if (!isDataURI(wasmTextFile)) {
-  wasmTextFile = locateFile(wasmTextFile);
- }
- if (!isDataURI(wasmBinaryFile)) {
-  wasmBinaryFile = locateFile(wasmBinaryFile);
- }
- if (!isDataURI(asmjsCodeFile)) {
-  asmjsCodeFile = locateFile(asmjsCodeFile);
- }
- var wasmPageSize = 64 * 1024;
- var info = {
-  "global": null,
-  "env": null,
-  "asm2wasm": asm2wasmImports,
-  "parent": Module
- };
- var exports = null;
- function mergeMemory(newBuffer) {
-  var oldBuffer = Module["buffer"];
-  if (newBuffer.byteLength < oldBuffer.byteLength) {
-   err("the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here");
-  }
-  var oldView = new Int8Array(oldBuffer);
-  var newView = new Int8Array(newBuffer);
-  newView.set(oldView);
-  updateGlobalBuffer(newBuffer);
-  updateGlobalBufferViews();
- }
- function fixImports(imports) {
-  return imports;
- }
- function getBinary() {
-  try {
-   if (Module["wasmBinary"]) {
-    return new Uint8Array(Module["wasmBinary"]);
-   }
-   if (Module["readBinary"]) {
-    return Module["readBinary"](wasmBinaryFile);
-   } else {
-    throw "both async and sync fetching of the wasm failed";
-   }
-  } catch (err) {
-   abort(err);
-  }
- }
- function getBinaryPromise() {
-  if (!Module["wasmBinary"] && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === "function") {
-   return fetch(wasmBinaryFile, {
-    credentials: "same-origin"
-   }).then((function(response) {
-    if (!response["ok"]) {
-     throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
-    }
-    return response["arrayBuffer"]();
-   })).catch((function() {
-    return getBinary();
-   }));
-  }
-  return new Promise((function(resolve, reject) {
-   resolve(getBinary());
-  }));
- }
- function doNativeWasm(global, env, providedBuffer) {
-  if (typeof WebAssembly !== "object") {
-   err("no native wasm support detected");
-   return false;
-  }
-  if (!(Module["wasmMemory"] instanceof WebAssembly.Memory)) {
-   err("no native wasm Memory in use");
-   return false;
-  }
-  env["memory"] = Module["wasmMemory"];
-  info["global"] = {
-   "NaN": NaN,
-   "Infinity": Infinity
-  };
-  info["global.Math"] = Math;
-  info["env"] = env;
-  function receiveInstance(instance, module) {
-   exports = instance.exports;
-   if (exports.memory) mergeMemory(exports.memory);
-   Module["asm"] = exports;
-   Module["usingWasm"] = true;
-   removeRunDependency("wasm-instantiate");
-  }
-  addRunDependency("wasm-instantiate");
-  if (Module["instantiateWasm"]) {
-   try {
-    return Module["instantiateWasm"](info, receiveInstance);
-   } catch (e) {
-    err("Module.instantiateWasm callback failed with error: " + e);
-    return false;
-   }
-  }
-  function receiveInstantiatedSource(output) {
-   receiveInstance(output["instance"], output["module"]);
-  }
-  function instantiateArrayBuffer(receiver) {
-   getBinaryPromise().then((function(binary) {
-    return WebAssembly.instantiate(binary, info);
-   }))
-   .then((...args) => {
-       reportCompileTime(benchmarkTime() - __startupStartTime);
-       return Promise.resolve(...args);
-   })
-   .then(receiver).catch((function(reason) {
-    err("failed to asynchronously prepare wasm: " + reason);
-    abort(reason);
-   }));
-  }
-  if (!Module["wasmBinary"] && typeof WebAssembly.instantiateStreaming === "function" && !isDataURI(wasmBinaryFile) && typeof fetch === "function") {
-   WebAssembly.instantiateStreaming(fetch(wasmBinaryFile, {
-    credentials: "same-origin"
-   }), info).then(receiveInstantiatedSource).catch((function(reason) {
-    err("wasm streaming compile failed: " + reason);
-    err("falling back to ArrayBuffer instantiation");
-    instantiateArrayBuffer(receiveInstantiatedSource);
-   }));
-  } else {
-   instantiateArrayBuffer(receiveInstantiatedSource);
-  }
-  return {};
- }
- Module["asmPreload"] = Module["asm"];
- var asmjsReallocBuffer = Module["reallocBuffer"];
- var wasmReallocBuffer = (function(size) {
-  var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE;
-  size = alignUp(size, PAGE_MULTIPLE);
-  var old = Module["buffer"];
-  var oldSize = old.byteLength;
-  if (Module["usingWasm"]) {
-   try {
-    var result = Module["wasmMemory"].grow((size - oldSize) / wasmPageSize);
-    if (result !== (-1 | 0)) {
-     return Module["buffer"] = Module["wasmMemory"].buffer;
-    } else {
-     return null;
-    }
-   } catch (e) {
-    return null;
-   }
-  }
- });
- Module["reallocBuffer"] = (function(size) {
-  if (finalMethod === "asmjs") {
-   return asmjsReallocBuffer(size);
-  } else {
-   return wasmReallocBuffer(size);
-  }
- });
- var finalMethod = "";
- Module["asm"] = (function(global, env, providedBuffer) {
-  env = fixImports(env);
-  if (!env["table"]) {
-   var TABLE_SIZE = Module["wasmTableSize"];
-   if (TABLE_SIZE === undefined) TABLE_SIZE = 1024;
-   var MAX_TABLE_SIZE = Module["wasmMaxTableSize"];
-   if (typeof WebAssembly === "object" && typeof WebAssembly.Table === "function") {
-    if (MAX_TABLE_SIZE !== undefined) {
-     env["table"] = new WebAssembly.Table({
-      "initial": TABLE_SIZE,
-      "maximum": MAX_TABLE_SIZE,
-      "element": "anyfunc"
-     });
-    } else {
-     env["table"] = new WebAssembly.Table({
-      "initial": TABLE_SIZE,
-      element: "anyfunc"
-     });
-    }
-   } else {
-    env["table"] = new Array(TABLE_SIZE);
-   }
-   Module["wasmTable"] = env["table"];
-  }
-  if (!env["memoryBase"]) {
-   env["memoryBase"] = Module["STATIC_BASE"];
-  }
-  if (!env["tableBase"]) {
-   env["tableBase"] = 0;
-  }
-  var exports;
-  exports = doNativeWasm(global, env, providedBuffer);
-  assert(exports, "no binaryen method succeeded.");
-  return exports;
- });
-}
-integrateWasmJS();
-STATIC_BASE = GLOBAL_BASE;
-STATICTOP = STATIC_BASE + 6640;
-__ATINIT__.push();
-var STATIC_BUMP = 6640;
-Module["STATIC_BASE"] = STATIC_BASE;
-Module["STATIC_BUMP"] = STATIC_BUMP;
-STATICTOP += 16;
-var EXCEPTIONS = {
- last: 0,
- caught: [],
- infos: {},
- deAdjust: (function(adjusted) {
-  if (!adjusted || EXCEPTIONS.infos[adjusted]) return adjusted;
-  for (var key in EXCEPTIONS.infos) {
-   var ptr = +key;
-   var info = EXCEPTIONS.infos[ptr];
-   if (info.adjusted === adjusted) {
-    return ptr;
-   }
-  }
-  return adjusted;
- }),
- addRef: (function(ptr) {
-  if (!ptr) return;
-  var info = EXCEPTIONS.infos[ptr];
-  info.refcount++;
- }),
- decRef: (function(ptr) {
-  if (!ptr) return;
-  var info = EXCEPTIONS.infos[ptr];
-  assert(info.refcount > 0);
-  info.refcount--;
-  if (info.refcount === 0 && !info.rethrown) {
-   if (info.destructor) {
-    Module["dynCall_vi"](info.destructor, ptr);
-   }
-   delete EXCEPTIONS.infos[ptr];
-   ___cxa_free_exception(ptr);
-  }
- }),
- clearRef: (function(ptr) {
-  if (!ptr) return;
-  var info = EXCEPTIONS.infos[ptr];
-  info.refcount = 0;
- })
-};
-var SYSCALLS = {
- varargs: 0,
- get: (function(varargs) {
-  SYSCALLS.varargs += 4;
-  var ret = HEAP32[SYSCALLS.varargs - 4 >> 2];
-  return ret;
- }),
- getStr: (function() {
-  var ret = Pointer_stringify(SYSCALLS.get());
-  return ret;
- }),
- get64: (function() {
-  var low = SYSCALLS.get(), high = SYSCALLS.get();
-  if (low >= 0) assert(high === 0); else assert(high === -1);
-  return low;
- }),
- getZero: (function() {
-  assert(SYSCALLS.get() === 0);
- })
-};
-function ___syscall140(which, varargs) {
- SYSCALLS.varargs = varargs;
- try {
-  var stream = SYSCALLS.getStreamFromFD(), offset_high = SYSCALLS.get(), offset_low = SYSCALLS.get(), result = SYSCALLS.get(), whence = SYSCALLS.get();
-  var offset = offset_low;
-  FS.llseek(stream, offset, whence);
-  HEAP32[result >> 2] = stream.position;
-  if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null;
-  return 0;
- } catch (e) {
-  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
-  return -e.errno;
- }
-}
-function ___syscall146(which, varargs) {
- SYSCALLS.varargs = varargs;
- try {
-  var stream = SYSCALLS.get(), iov = SYSCALLS.get(), iovcnt = SYSCALLS.get();
-  var ret = 0;
-  if (!___syscall146.buffers) {
-   ___syscall146.buffers = [ null, [], [] ];
-   ___syscall146.printChar = (function(stream, curr) {
-    var buffer = ___syscall146.buffers[stream];
-    assert(buffer);
-    if (curr === 0 || curr === 10) {
-     (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0));
-     buffer.length = 0;
-    } else {
-     buffer.push(curr);
-    }
-   });
-  }
-  for (var i = 0; i < iovcnt; i++) {
-   var ptr = HEAP32[iov + i * 8 >> 2];
-   var len = HEAP32[iov + (i * 8 + 4) >> 2];
-   for (var j = 0; j < len; j++) {
-    ___syscall146.printChar(stream, HEAPU8[ptr + j]);
-   }
-   ret += len;
-  }
-  return ret;
- } catch (e) {
-  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
-  return -e.errno;
- }
-}
-function ___syscall54(which, varargs) {
- SYSCALLS.varargs = varargs;
- try {
-  return 0;
- } catch (e) {
-  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
-  return -e.errno;
- }
-}
-function ___syscall6(which, varargs) {
- SYSCALLS.varargs = varargs;
- try {
-  var stream = SYSCALLS.getStreamFromFD();
-  FS.close(stream);
-  return 0;
- } catch (e) {
-  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
-  return -e.errno;
- }
-}
-function _abort() {
- Module["abort"]();
-}
-function _gettimeofday(ptr) {
- var now = Date.now();
- HEAP32[ptr >> 2] = now / 1e3 | 0;
- HEAP32[ptr + 4 >> 2] = now % 1e3 * 1e3 | 0;
- return 0;
-}
-function _emscripten_memcpy_big(dest, src, num) {
- HEAPU8.set(HEAPU8.subarray(src, src + num), dest);
- return dest;
-}
-var PTHREAD_SPECIFIC = {};
-function _pthread_getspecific(key) {
- return PTHREAD_SPECIFIC[key] || 0;
-}
-var PTHREAD_SPECIFIC_NEXT_KEY = 1;
-var ERRNO_CODES = {
- EPERM: 1,
- ENOENT: 2,
- ESRCH: 3,
- EINTR: 4,
- EIO: 5,
- ENXIO: 6,
- E2BIG: 7,
- ENOEXEC: 8,
- EBADF: 9,
- ECHILD: 10,
- EAGAIN: 11,
- EWOULDBLOCK: 11,
- ENOMEM: 12,
- EACCES: 13,
- EFAULT: 14,
- ENOTBLK: 15,
- EBUSY: 16,
- EEXIST: 17,
- EXDEV: 18,
- ENODEV: 19,
- ENOTDIR: 20,
- EISDIR: 21,
- EINVAL: 22,
- ENFILE: 23,
- EMFILE: 24,
- ENOTTY: 25,
- ETXTBSY: 26,
- EFBIG: 27,
- ENOSPC: 28,
- ESPIPE: 29,
- EROFS: 30,
- EMLINK: 31,
- EPIPE: 32,
- EDOM: 33,
- ERANGE: 34,
- ENOMSG: 42,
- EIDRM: 43,
- ECHRNG: 44,
- EL2NSYNC: 45,
- EL3HLT: 46,
- EL3RST: 47,
- ELNRNG: 48,
- EUNATCH: 49,
- ENOCSI: 50,
- EL2HLT: 51,
- EDEADLK: 35,
- ENOLCK: 37,
- EBADE: 52,
- EBADR: 53,
- EXFULL: 54,
- ENOANO: 55,
- EBADRQC: 56,
- EBADSLT: 57,
- EDEADLOCK: 35,
- EBFONT: 59,
- ENOSTR: 60,
- ENODATA: 61,
- ETIME: 62,
- ENOSR: 63,
- ENONET: 64,
- ENOPKG: 65,
- EREMOTE: 66,
- ENOLINK: 67,
- EADV: 68,
- ESRMNT: 69,
- ECOMM: 70,
- EPROTO: 71,
- EMULTIHOP: 72,
- EDOTDOT: 73,
- EBADMSG: 74,
- ENOTUNIQ: 76,
- EBADFD: 77,
- EREMCHG: 78,
- ELIBACC: 79,
- ELIBBAD: 80,
- ELIBSCN: 81,
- ELIBMAX: 82,
- ELIBEXEC: 83,
- ENOSYS: 38,
- ENOTEMPTY: 39,
- ENAMETOOLONG: 36,
- ELOOP: 40,
- EOPNOTSUPP: 95,
- EPFNOSUPPORT: 96,
- ECONNRESET: 104,
- ENOBUFS: 105,
- EAFNOSUPPORT: 97,
- EPROTOTYPE: 91,
- ENOTSOCK: 88,
- ENOPROTOOPT: 92,
- ESHUTDOWN: 108,
- ECONNREFUSED: 111,
- EADDRINUSE: 98,
- ECONNABORTED: 103,
- ENETUNREACH: 101,
- ENETDOWN: 100,
- ETIMEDOUT: 110,
- EHOSTDOWN: 112,
- EHOSTUNREACH: 113,
- EINPROGRESS: 115,
- EALREADY: 114,
- EDESTADDRREQ: 89,
- EMSGSIZE: 90,
- EPROTONOSUPPORT: 93,
- ESOCKTNOSUPPORT: 94,
- EADDRNOTAVAIL: 99,
- ENETRESET: 102,
- EISCONN: 106,
- ENOTCONN: 107,
- ETOOMANYREFS: 109,
- EUSERS: 87,
- EDQUOT: 122,
- ESTALE: 116,
- ENOTSUP: 95,
- ENOMEDIUM: 123,
- EILSEQ: 84,
- EOVERFLOW: 75,
- ECANCELED: 125,
- ENOTRECOVERABLE: 131,
- EOWNERDEAD: 130,
- ESTRPIPE: 86
-};
-function _pthread_key_create(key, destructor) {
- if (key == 0) {
-  return ERRNO_CODES.EINVAL;
- }
- HEAP32[key >> 2] = PTHREAD_SPECIFIC_NEXT_KEY;
- PTHREAD_SPECIFIC[PTHREAD_SPECIFIC_NEXT_KEY] = 0;
- PTHREAD_SPECIFIC_NEXT_KEY++;
- return 0;
-}
-function _pthread_once(ptr, func) {
- if (!_pthread_once.seen) _pthread_once.seen = {};
- if (ptr in _pthread_once.seen) return;
- Module["dynCall_v"](func);
- _pthread_once.seen[ptr] = 1;
-}
-function _pthread_setspecific(key, value) {
- if (!(key in PTHREAD_SPECIFIC)) {
-  return ERRNO_CODES.EINVAL;
- }
- PTHREAD_SPECIFIC[key] = value;
- return 0;
-}
-function ___setErrNo(value) {
- if (Module["___errno_location"]) HEAP32[Module["___errno_location"]() >> 2] = value;
- return value;
-}
-DYNAMICTOP_PTR = staticAlloc(4);
-STACK_BASE = STACKTOP = alignMemory(STATICTOP);
-STACK_MAX = STACK_BASE + TOTAL_STACK;
-DYNAMIC_BASE = alignMemory(STACK_MAX);
-HEAP32[DYNAMICTOP_PTR >> 2] = DYNAMIC_BASE;
-staticSealed = true;
-Module["wasmTableSize"] = 34;
-Module["wasmMaxTableSize"] = 34;
-Module.asmGlobalArg = {};
-Module.asmLibraryArg = {
- "abort": abort,
- "enlargeMemory": enlargeMemory,
- "getTotalMemory": getTotalMemory,
- "abortOnCannotGrowMemory": abortOnCannotGrowMemory,
- "___setErrNo": ___setErrNo,
- "___syscall140": ___syscall140,
- "___syscall146": ___syscall146,
- "___syscall54": ___syscall54,
- "___syscall6": ___syscall6,
- "_abort": _abort,
- "_emscripten_memcpy_big": _emscripten_memcpy_big,
- "_gettimeofday": _gettimeofday,
- "_pthread_getspecific": _pthread_getspecific,
- "_pthread_key_create": _pthread_key_create,
- "_pthread_once": _pthread_once,
- "_pthread_setspecific": _pthread_setspecific,
- "DYNAMICTOP_PTR": DYNAMICTOP_PTR,
- "STACKTOP": STACKTOP
-};
-var asm = Module["asm"](Module.asmGlobalArg, Module.asmLibraryArg, buffer);
-Module["asm"] = asm;
-var ___errno_location = Module["___errno_location"] = (function() {
- return Module["asm"]["___errno_location"].apply(null, arguments);
-});
-var _main = Module["_main"] = (function() {
- let start = benchmarkTime();
- let ret = Module["asm"]["_main"].apply(null, arguments);
- reportRunTime(benchmarkTime() - start);
- return ret;
-});
-var stackAlloc = Module["stackAlloc"] = (function() {
- return Module["asm"]["stackAlloc"].apply(null, arguments);
-});
-var dynCall_v = Module["dynCall_v"] = (function() {
- return Module["asm"]["dynCall_v"].apply(null, arguments);
-});
-var dynCall_vi = Module["dynCall_vi"] = (function() {
- return Module["asm"]["dynCall_vi"].apply(null, arguments);
-});
-Module["asm"] = asm;
-function ExitStatus(status) {
- this.name = "ExitStatus";
- this.message = "Program terminated with exit(" + status + ")";
- this.status = status;
-}
-ExitStatus.prototype = new Error;
-ExitStatus.prototype.constructor = ExitStatus;
-var initialStackTop;
-var calledMain = false;
-dependenciesFulfilled = function runCaller() {
- if (!Module["calledRun"]) run();
- if (!Module["calledRun"]) dependenciesFulfilled = runCaller;
-};
-Module["callMain"] = function callMain(args) {
- args = args || [];
- ensureInitRuntime();
- var argc = args.length + 1;
- var argv = stackAlloc((argc + 1) * 4);
- HEAP32[argv >> 2] = allocateUTF8OnStack(Module["thisProgram"]);
- for (var i = 1; i < argc; i++) {
-  HEAP32[(argv >> 2) + i] = allocateUTF8OnStack(args[i - 1]);
- }
- HEAP32[(argv >> 2) + argc] = 0;
- try {
-  var ret = Module["_main"](argc, argv, 0);
-  exit(ret, true);
- } catch (e) {
-  if (e instanceof ExitStatus) {
-   return;
-  } else if (e == "SimulateInfiniteLoop") {
-   Module["noExitRuntime"] = true;
-   return;
-  } else {
-   var toLog = e;
-   if (e && typeof e === "object" && e.stack) {
-    toLog = [ e, e.stack ];
-   }
-   err("exception thrown: " + toLog);
-   Module["quit"](1, e);
-  }
- } finally {
-  calledMain = true;
- }
-};
-function run(args) {
- args = args || Module["arguments"];
- if (runDependencies > 0) {
-  return;
- }
- preRun();
- if (runDependencies > 0) return;
- if (Module["calledRun"]) return;
- function doRun() {
-  if (Module["calledRun"]) return;
-  Module["calledRun"] = true;
-  if (ABORT) return;
-  ensureInitRuntime();
-  preMain();
-  if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"]();
-  if (Module["_main"] && shouldRunNow) Module["callMain"](args);
-  postRun();
- }
- if (Module["setStatus"]) {
-  Module["setStatus"]("Running...");
-  setTimeout((function() {
-   setTimeout((function() {
-    Module["setStatus"]("");
-   }), 1);
-   doRun();
-  }), 1);
- } else {
-  doRun();
- }
-}
-Module["run"] = run;
-function exit(status, implicit) {
- if (implicit && Module["noExitRuntime"] && status === 0) {
-  return;
- }
- if (Module["noExitRuntime"]) {} else {
-  ABORT = true;
-  EXITSTATUS = status;
-  STACKTOP = initialStackTop;
-  exitRuntime();
-  if (Module["onExit"]) Module["onExit"](status);
- }
- Module["quit"](status, new ExitStatus(status));
-}
-function abort(what) {
- if (Module["onAbort"]) {
-  Module["onAbort"](what);
- }
- if (what !== undefined) {
-  out(what);
-  err(what);
-  what = JSON.stringify(what);
- } else {
-  what = "";
- }
- ABORT = true;
- EXITSTATUS = 1;
- throw "abort(" + what + "). Build with -s ASSERTIONS=1 for more info.";
-}
-Module["abort"] = abort;
-if (Module["preInit"]) {
- if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
- while (Module["preInit"].length > 0) {
-  Module["preInit"].pop()();
- }
-}
-var shouldRunNow = true;
-if (Module["noInitialRun"]) {
- shouldRunNow = false;
-}
-Module["noExitRuntime"] = true;
-run();
-}
diff --git a/wasm/HashSet.wasm b/wasm/HashSet.wasm
deleted file mode 100644
index b61986f..0000000
--- a/wasm/HashSet.wasm
+++ /dev/null
Binary files differ
diff --git a/wasm/HashSet.cpp b/wasm/HashSet/HashSet.cpp
similarity index 99%
rename from wasm/HashSet.cpp
rename to wasm/HashSet/HashSet.cpp
index a8cea65..f00fb2a 100644
--- a/wasm/HashSet.cpp
+++ b/wasm/HashSet/HashSet.cpp
@@ -13473,8 +13473,8 @@
 
 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);
diff --git a/wasm/HashSet/benchmark.js b/wasm/HashSet/benchmark.js
new file mode 100644
index 0000000..0297acf
--- /dev/null
+++ b/wasm/HashSet/benchmark.js
@@ -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();
+    }
+};
diff --git a/wasm/HashSet/build.log b/wasm/HashSet/build.log
new file mode 100644
index 0000000..09609bb
--- /dev/null
+++ b/wasm/HashSet/build.log
@@ -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
diff --git a/wasm/HashSet/build.sh b/wasm/HashSet/build.sh
new file mode 100755
index 0000000..882b6d2
--- /dev/null
+++ b/wasm/HashSet/build.sh
@@ -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"
diff --git a/wasm/HashSet/build/HashSet.js b/wasm/HashSet/build/HashSet.js
new file mode 100644
index 0000000..03c6249
--- /dev/null
+++ b/wasm/HashSet/build/HashSet.js
@@ -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);
diff --git a/wasm/HashSet/build/HashSet.js.symbols b/wasm/HashSet/build/HashSet.js.symbols
new file mode 100644
index 0000000..59062bd
--- /dev/null
+++ b/wasm/HashSet/build/HashSet.js.symbols
@@ -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
diff --git a/wasm/HashSet/build/HashSet.wasm b/wasm/HashSet/build/HashSet.wasm
new file mode 100755
index 0000000..c2c0f03
--- /dev/null
+++ b/wasm/HashSet/build/HashSet.wasm
Binary files differ