diff --git a/asur/index.js b/asur/index.js index 411bfb47..6980bbc3 100644 --- a/asur/index.js +++ b/asur/index.js @@ -985,7 +985,7 @@ const stringifyOp = ({ types, funcs, codes, imports, globals }, op, porfFunc = o if (!porfFunc.invLocals) porfFunc.invLocals = inv(porfFunc.locals, x => x.idx); if (op.func != null) { - str += ` \x1b[90m${op.func >= imports.length ? `${noHighlight(codes[op.func - imports.length].bc.porfFunc.name)}` : `${({ p: 'print', c: 'printChar', t: 'time', z: 'profile' })[imports[op.func].name]}`}`; + str += ` \x1b[90m${op.func >= imports.length ? `${noHighlight(codes[op.func - imports.length].bc.porfFunc.name)}` : `${({ p: 'print', c: 'printChar', t: 'time', y: 'profile1', z: 'profile2' })[imports[op.func].name]}`}`; const type = types[op.func >= imports.length ? funcs[op.func - imports.length] : imports[op.func].typeIdx]; str += ` (${type.params.map(x => noHighlight(invValtype[x])).join(', ')}) -> (${type.returns.map(x => noHighlight(invValtype[x])).join(', ')})`; str += '\x1b[0m'; diff --git a/compiler/assemble.js b/compiler/assemble.js index 97a4b40b..7e1c1198 100644 --- a/compiler/assemble.js +++ b/compiler/assemble.js @@ -84,7 +84,7 @@ export default (funcs, globals, tags, pages, data, flags) => { const importSection = importFuncs.length === 0 ? [] : createSection( Section.import, - encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(new Array(x.params).fill(valtypeBinary), new Array(x.returns).fill(valtypeBinary)) ])) + encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(new Array(x.params).fill(x.name.startsWith('profile') ? Valtype.i32 : valtypeBinary), new Array(x.returns).fill(valtypeBinary)) ])) ); const funcSection = createSection( diff --git a/compiler/builtins.js b/compiler/builtins.js index 96b8b733..46dcabdb 100644 --- a/compiler/builtins.js +++ b/compiler/builtins.js @@ -23,12 +23,18 @@ export const importedFuncs = [ returns: 1 }, { - name: 'profile', + name: 'profile1', + import: 'y', + params: 1, + returns: 0 + }, + { + name: 'profile2', import: 'z', params: 1, returns: 0 } -].filter(x => x); +]; for (let i = 0; i < importedFuncs.length; i++) { const f = importedFuncs[i]; diff --git a/compiler/codegen.js b/compiler/codegen.js index 80e9ee02..5b298093 100644 --- a/compiler/codegen.js +++ b/compiler/codegen.js @@ -1845,6 +1845,9 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => { // pointer, value, align, offset i32_store16: { imms: 2, args: 2 }, + // value + i32_const: { imms: 1, args: 0 }, + // a, b i32_or: { imms: 0, args: 2 }, }; diff --git a/compiler/wrap.js b/compiler/wrap.js index 458b8a85..5ed0fed8 100644 --- a/compiler/wrap.js +++ b/compiler/wrap.js @@ -54,6 +54,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print = p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()), c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)), t: () => performance.now(), + y: () => {}, z: () => {}, ...customImports } diff --git a/runner/debug.js b/runner/debug.js index 883342cf..2cef6061 100644 --- a/runner/debug.js +++ b/runner/debug.js @@ -14,13 +14,13 @@ let funcs = {}, funcId = 0; source = source.replace(/^\s*(function|const)\s*([a-zA-Z0-9]+)(\s*=\s*)?\([^)]*\)\s*(=>)?\s*\{$/gm, (x, _, n) => { const id = funcId++; funcs[funcId] = n; - return `${x}profile(${100000 + id})`; + return `${x}profile2(Porffor.wasm.i32.const(${id}))`; }); const lines = source.split('\n'); for (let i = 0; i < lines.length; i++) { // lines[line] = lines[line].replace(/^[^\n}]*;$/, _ => `profile(${line});${_}`); - if (lines[i].trim().replace('}', '') !== '') lines[i] = `profile(${i});` + lines[i]; + if (lines[i].trim().replace('}', '') !== '') lines[i] = `profile1(Porffor.wasm.i32.const(${i}));` + lines[i]; } source = lines.join('\n'); @@ -48,20 +48,7 @@ let output = ''; try { const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], { - z: n => { - if (n >= 100000) { - // start of call - callStack.push(funcs[n - 100000]); - - callStarts.push(lastLine); - - _paused = paused; - if (!stepIn) paused = false; - else paused = true; - - return; - } - + y: n => { if (callStarts[callStarts.length - 1] === n - 1) { // end of call @@ -116,6 +103,16 @@ try { } } } + }, + z: n => { + // start of call + callStack.push(funcs[n]); + + callStarts.push(lastLine); + + _paused = paused; + if (!stepIn) paused = false; + else paused = true; } }, s => output += s); diff --git a/runner/profiler.js b/runner/profiler.js index 4f820341..2b0b2e36 100644 --- a/runner/profiler.js +++ b/runner/profiler.js @@ -5,17 +5,22 @@ import fs from 'node:fs'; import Prefs from '../compiler/prefs.js'; -const fast = Prefs.profiler === 'fast'; +// const fast = Prefs.profiler === 'fast'; +const fast = !Prefs.experimentalProfiler; const file = process.argv.slice(2).find(x => x[0] !== '-'); let source = fs.readFileSync(file, 'utf8'); let profileId = 0; -source = fast ? source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});${_}profile(${profileId++});`) : source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});profile(${profileId++});${_}profile(${profileId++});`); +// source = fast ? source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});${_}profile(${profileId++});`) : source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});profile(${profileId++});${_}profile(${profileId++});`); +// source = fast ? source.replace(/^[^\n}]*;$/mg, _ => `profile(Porffor.wasm.i32.const(${profileId++}));${_}profile(Porffor.wasm.i32.const(${profileId++}));`) : source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});profile(${profileId++});${_}profile(${profileId++});`); +source = fast ? source.replace(/^[^\n}]*;$/mg, _ => `profile1(Porffor.wasm.i32.const(${profileId}));${_}profile2(Porffor.wasm.i32.const(${profileId++}));`) : source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});profile(${profileId++});${_}profile(${profileId++});`); // console.log(source); +// let tmp = new Array(profileId).fill(0); let tmp = new Array(profileId).fill(0); +let times = new Array(profileId).fill(0); let samples = 0; const percents = process.argv.includes('-%'); @@ -26,25 +31,31 @@ let last = 0; try { const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], { + y: fast ? n => { + tmp[n] = performance.now(); + } : n => { /* todo */ }, z: fast ? n => { - if (n % 2) { - tmp[n] += performance.now() - tmp[n - 1]; - } else { - tmp[n] = performance.now(); - } - } : n => { - if (n % 3 === 2) { - tmp[n] += (performance.now() - tmp[n - 1]) - (tmp[n - 1] - tmp[n - 2]); - samples++; - - if (performance.now() > last) { - process.stdout.write(`\r${spinner[spin++ % 4]} running: collected ${samples} samples...`); - last = performance.now() + 100; - } - } else { - tmp[n] = performance.now(); - } - } + times[n] += performance.now() - tmp[n]; + } : n => { /* todo */ } + // z: fast ? n => { + // if (n % 2) { + // tmp[n] += performance.now() - tmp[n - 1]; + // } else { + // tmp[n] = performance.now(); + // } + // } : n => { + // if (n % 3 === 2) { + // tmp[n] += (performance.now() - tmp[n - 1]) - (tmp[n - 1] - tmp[n - 2]); + // samples++; + + // if (performance.now() > last) { + // process.stdout.write(`\r${spinner[spin++ % 4]} running: collected ${samples} samples...`); + // last = performance.now() + 100; + // } + // } else { + // tmp[n] = performance.now(); + // } + // } }); const start = performance.now(); @@ -53,30 +64,38 @@ try { const total = performance.now() - start; - console.log(`\nsamples: ${fast ? 'not measured' : samples}\ntotal: ${total}ms\n\n` + source.split('\n').map(x => { + console.log(`\n${fast ? '' : `samples: ${samples}\n`}total: ${total}ms\n\n` + source.split('\n').map(x => { let time = 0; if (x.startsWith('profile')) { - const id = parseInt(x.slice(8, x.indexOf(')'))); - time = fast ? tmp[id + 1] : tmp[id + 2]; + // const id = parseInt(x.slice(8, x.indexOf(')'))); + // const id = parseInt(x.slice(31, x.indexOf(')') + 1)); + const id = parseInt(x.slice(32, x.indexOf(')'))); + // time = fast ? tmp[id + 1] : tmp[id + 2]; + time = fast ? times[id] : tmp[id + 2]; } let color = [ 0, 0, 0 ]; if (time) { - const relativeTime = Math.sqrt(time / total); + let relativeTime = time / total; if (percents) time = relativeTime; + relativeTime = Math.sqrt(relativeTime); color = [ (relativeTime * 250) | 0, (Math.sin(relativeTime * Math.PI) * 50) | 0, 0 ]; } const ansiColor = `2;${color[0]};${color[1]};${color[2]}m`; - if (percents) return `\x1b[48;${ansiColor}\x1b[97m${time ? ((time * 100).toFixed(0).padStart(4, ' ') + '%') : ' '}\x1b[0m\x1b[38;${ansiColor}▌\x1b[0m ${x.replace(/profile\([0-9]+\);/g, '')}`; + // const line = x.replace(/profile\([0-9]+\);/g, ''); + // const line = x.replace(/profile\(Porffor.wasm.i32.const\([0-9]+\)\);/g, ''); + const line = x.replace(/profile[0-9]\(Porffor.wasm.i32.const\([0-9]+\)\);/g, ''); + + if (percents) return `\x1b[48;${ansiColor}\x1b[97m${time ? ((time * 100).toFixed(0).padStart(4, ' ') + '%') : ' '}\x1b[0m\x1b[38;${ansiColor}▌\x1b[0m ${line}`; let digits = 2; if (time >= 100) digits = 1; if (time >= 1000) digits = 0; - return `\x1b[48;${ansiColor}\x1b[97m${time ? time.toFixed(digits).padStart(6, ' ') : ' '}\x1b[0m\x1b[38;${ansiColor}▌\x1b[0m ${x.replace(/profile\([0-9]+\);/g, '')}`; + return `\x1b[48;${ansiColor}\x1b[97m${time ? time.toFixed(digits).padStart(6, ' ') : ' '}\x1b[0m\x1b[38;${ansiColor}▌\x1b[0m ${line}`; }).join('\n')); } catch (e) { console.error(e); diff --git a/test262/index.js b/test262/index.js index af4083f4..e6f9dcc5 100644 --- a/test262/index.js +++ b/test262/index.js @@ -100,6 +100,7 @@ const run = ({ file, contents, attrs }) => { p: () => {}, c: () => {}, t: () => performance.now(), + y: () => {}, z: () => {}, } })).exports;