const INTERVAL_MS = 1; const RS_TOP_ADDR = 0x10000; const PROF_DATA_ADDR = 0x58; const PROF_DATA_IDX = PROF_DATA_ADDR / 8; let mem_8; let mem_64; let sampler; const samples = []; function sample() { const data = Atomics.load(mem_64, PROF_DATA_IDX); const ip = Number(data & 0xffffffffn); const rsp = Number(data >> 32n); samples.push({ ip, rs_bytes: mem_8.slice(rsp, RS_TOP_ADDR) }); } function i32(bytes) { return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24); } function postproc({ ip, rs_bytes }) { const rs = []; for (let i = 0; i < rs_bytes.length; i += 4) rs.push(i32(rs_bytes.slice(i, i + 4))); rs.reverse(); return { ip, rs }; } self.onmessage = (e) => { switch (e.data.type) { case "start": console.log("Starting profiler"); mem_8 = new Uint8Array(e.data.mem.buffer); mem_64 = new BigUint64Array(e.data.mem.buffer); ip = e.data.ip; rsp = e.data.rsp; sampler = setInterval(sample, INTERVAL_MS); break; case "stop": clearInterval(sample); console.log("Stopped profiler"); self.postMessage(samples.map(postproc)); } };