porffor 0.57.6 → 0.57.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiler/assemble.js +7 -1
- package/compiler/builtins.js +37 -54
- package/compiler/encoding.js +11 -9
- package/compiler/index.js +3 -0
- package/compiler/pgo.js +13 -13
- package/compiler/wrap.js +55 -34
- package/package.json +1 -1
- package/runtime/debug.js +61 -61
- package/runtime/flamegraph.js +15 -17
- package/runtime/hotlines.js +16 -19
- package/runtime/index.js +1 -1
package/compiler/assemble.js
CHANGED
@@ -95,7 +95,13 @@ export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
|
|
95
95
|
|
96
96
|
const importSection = importFuncs.length === 0 ? [] : createSection(
|
97
97
|
Section.import,
|
98
|
-
encodeVector(importFuncs.map(x =>
|
98
|
+
encodeVector(importFuncs.map(x => {
|
99
|
+
return [
|
100
|
+
0, 1, x.import.charCodeAt(0),
|
101
|
+
ExportDesc.func,
|
102
|
+
getType(x.params, x.returns)
|
103
|
+
];
|
104
|
+
}))
|
99
105
|
);
|
100
106
|
time('import section');
|
101
107
|
|
package/compiler/builtins.js
CHANGED
@@ -5,61 +5,44 @@ import { TYPES, TYPE_NAMES } from './types.js';
|
|
5
5
|
import { number, unsignedLEB128 } from './encoding.js';
|
6
6
|
import './prefs.js';
|
7
7
|
|
8
|
-
export const importedFuncs =
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
name: 'profile1',
|
35
|
-
import: 'y',
|
36
|
-
params: [ Valtype.i32 ],
|
37
|
-
returns: 0
|
38
|
-
},
|
39
|
-
{
|
40
|
-
name: 'profile2',
|
41
|
-
import: 'z',
|
42
|
-
params: [ Valtype.i32 ],
|
43
|
-
returns: 0
|
44
|
-
},
|
45
|
-
{
|
46
|
-
name: '__Porffor_readArgv',
|
47
|
-
import: 'w',
|
48
|
-
params: 2,
|
49
|
-
returns: 1
|
50
|
-
},
|
51
|
-
{
|
52
|
-
name: '__Porffor_readFile',
|
53
|
-
import: 'q',
|
54
|
-
params: 2,
|
55
|
-
returns: 1
|
56
|
-
}
|
57
|
-
];
|
8
|
+
export const importedFuncs = {};
|
9
|
+
Object.defineProperty(importedFuncs, 'length', { configurable: true, writable: true, value: 0 });
|
10
|
+
|
11
|
+
export const createImport = (name, params, returns, js = null, c = null) => {
|
12
|
+
if (name in importedFuncs) return false;
|
13
|
+
|
14
|
+
const call = importedFuncs.length;
|
15
|
+
const ident = String.fromCharCode(97 + importedFuncs.length);
|
16
|
+
let obj;
|
17
|
+
const get = () => {
|
18
|
+
if (obj) return obj;
|
19
|
+
|
20
|
+
if (typeof params === 'function') params = params();
|
21
|
+
if (typeof returns === 'function') returns = returns();
|
22
|
+
if (typeof params === 'number') params = new Array(params).fill(valtypeBinary);
|
23
|
+
if (typeof returns === 'number') returns = new Array(returns).fill(valtypeBinary);
|
24
|
+
|
25
|
+
obj = new Number(call);
|
26
|
+
obj.name = name;
|
27
|
+
obj.import = ident;
|
28
|
+
obj.params = params;
|
29
|
+
obj.returns = returns;
|
30
|
+
obj.js = js;
|
31
|
+
obj.c = c;
|
32
|
+
return obj;
|
33
|
+
};
|
58
34
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
35
|
+
Object.defineProperty(importedFuncs, name, {
|
36
|
+
get,
|
37
|
+
configurable: true,
|
38
|
+
enumerable: true
|
39
|
+
});
|
40
|
+
Object.defineProperty(importedFuncs, call, {
|
41
|
+
get,
|
42
|
+
configurable: true
|
43
|
+
});
|
44
|
+
importedFuncs.length = call + 1;
|
45
|
+
};
|
63
46
|
|
64
47
|
export const UNDEFINED = 0;
|
65
48
|
export const NULL = 0;
|
package/compiler/encoding.js
CHANGED
@@ -28,9 +28,9 @@ export const signedLEB128 = n => {
|
|
28
28
|
// just input for small numbers (for perf as common)
|
29
29
|
if (n >= 0 && n <= 63) return [ n ];
|
30
30
|
if (n >= -64 && n <= 0) return [ 128 + n ];
|
31
|
+
if (n >= 0 && n <= 8191) return [ 128 + (n % 128), Math.floor(n / 128) ];
|
31
32
|
|
32
33
|
const buffer = [];
|
33
|
-
|
34
34
|
while (true) {
|
35
35
|
let byte = n & 0x7f;
|
36
36
|
n >>= 7;
|
@@ -53,6 +53,7 @@ export const unsignedLEB128 = n => {
|
|
53
53
|
|
54
54
|
// just input for small numbers (for perf as common)
|
55
55
|
if (n >= 0 && n <= 127) return [ n ];
|
56
|
+
if (n >= 0 && n <= 16383) return [ 128 + (n % 128), Math.floor(n / 128) ];
|
56
57
|
|
57
58
|
const buffer = [];
|
58
59
|
do {
|
@@ -63,6 +64,7 @@ export const unsignedLEB128 = n => {
|
|
63
64
|
}
|
64
65
|
buffer.push(byte);
|
65
66
|
} while (n !== 0);
|
67
|
+
|
66
68
|
return buffer;
|
67
69
|
};
|
68
70
|
|
@@ -122,14 +124,13 @@ export const big_unsignedLEB128 = n => {
|
|
122
124
|
return buffer;
|
123
125
|
};
|
124
126
|
|
125
|
-
export const read_signedLEB128 =
|
126
|
-
const input = [..._input];
|
127
|
+
export const read_signedLEB128 = input => {
|
127
128
|
let result = 0, shift = 0;
|
128
129
|
|
130
|
+
let i = 0;
|
129
131
|
while (true) {
|
130
|
-
const byte = input
|
132
|
+
const byte = input[i++];
|
131
133
|
result |= (byte & 0x7f) << shift;
|
132
|
-
|
133
134
|
shift += 7;
|
134
135
|
|
135
136
|
if ((0x80 & byte) === 0) {
|
@@ -143,14 +144,13 @@ export const read_signedLEB128 = _input => {
|
|
143
144
|
};
|
144
145
|
|
145
146
|
// todo: check this with large unsigned values
|
146
|
-
export const read_unsignedLEB128 =
|
147
|
-
const input = [..._input];
|
147
|
+
export const read_unsignedLEB128 = input => {
|
148
148
|
let result = 0, shift = 0;
|
149
149
|
|
150
|
+
let i = 0;
|
150
151
|
while (true) {
|
151
|
-
const byte = input
|
152
|
+
const byte = input[i++];
|
152
153
|
result |= (byte & 0x7f) << shift;
|
153
|
-
|
154
154
|
shift += 7;
|
155
155
|
|
156
156
|
if ((0x80 & byte) === 0) {
|
@@ -184,6 +184,7 @@ export const signedLEB128_into = (n, buffer) => {
|
|
184
184
|
// just input for small numbers (for perf as common)
|
185
185
|
if (n >= 0 && n <= 63) return buffer.push(n);
|
186
186
|
if (n >= -64 && n <= 0) return buffer.push(128 + n);
|
187
|
+
if (n >= 0 && n <= 8191) return buffer.push(128 + (n % 128), Math.floor(n / 128));
|
187
188
|
|
188
189
|
while (true) {
|
189
190
|
let byte = n & 0x7f;
|
@@ -205,6 +206,7 @@ export const unsignedLEB128_into = (n, buffer) => {
|
|
205
206
|
|
206
207
|
// just input for small numbers (for perf as common)
|
207
208
|
if (n >= 0 && n <= 127) return buffer.push(n);
|
209
|
+
if (n >= 0 && n <= 16383) return buffer.push(128 + (n % 128), Math.floor(n / 128));
|
208
210
|
|
209
211
|
do {
|
210
212
|
let byte = n & 0x7f;
|
package/compiler/index.js
CHANGED
@@ -62,6 +62,9 @@ const progressClear = () => {
|
|
62
62
|
export default (code, module = undefined) => {
|
63
63
|
if (module !== undefined) Prefs.module = module;
|
64
64
|
|
65
|
+
globalThis.valtype = Prefs.valtype ?? 'f64';
|
66
|
+
globalThis.valtypeBinary = Valtype[valtype];
|
67
|
+
|
65
68
|
const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
|
66
69
|
|
67
70
|
let target = Prefs.target ?? 'wasm';
|
package/compiler/pgo.js
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
import { Opcodes, Valtype } from './wasmSpec.js';
|
2
2
|
import { number } from './encoding.js';
|
3
|
-
import { importedFuncs } from './builtins.js';
|
3
|
+
import { createImport, importedFuncs } from './builtins.js';
|
4
4
|
import assemble from './assemble.js';
|
5
5
|
import wrap, { writeByteStr } from './wrap.js';
|
6
6
|
import * as Havoc from './havoc.js';
|
7
7
|
import './prefs.js';
|
8
8
|
|
9
9
|
export const setup = () => {
|
10
|
-
importedFuncs[importedFuncs.profile2].params = [ Valtype.i32, valtypeBinary ];
|
11
|
-
|
12
10
|
// enable these prefs by default for pgo
|
13
11
|
for (const x of [
|
14
12
|
'typeswitchUniqueTmp', // use unique tmps for typeswitches
|
@@ -36,6 +34,15 @@ export const run = obj => {
|
|
36
34
|
|
37
35
|
time(0, `injecting PGO logging...`);
|
38
36
|
|
37
|
+
let activeFunc = null, abort = false;
|
38
|
+
createImport('profile1', 1, 0, n => {
|
39
|
+
activeFunc = n;
|
40
|
+
});
|
41
|
+
createImport('profile2', 2, 0, (i, n) => {
|
42
|
+
if (activeFunc == null) throw 'fail';
|
43
|
+
localData[activeFunc][i].push(n);
|
44
|
+
});
|
45
|
+
|
39
46
|
let funcs = [];
|
40
47
|
for (let i = 0; i < wasmFuncs.length; i++) {
|
41
48
|
const { name, internal, params, locals, wasm } = wasmFuncs[i];
|
@@ -79,7 +86,7 @@ export const run = obj => {
|
|
79
86
|
time(0, `injected PGO logging`);
|
80
87
|
time(1, `running with PGO logging...`);
|
81
88
|
|
82
|
-
|
89
|
+
|
83
90
|
try {
|
84
91
|
obj.wasm = assemble(obj.funcs, obj.globals, obj.tags, obj.pages, obj.data, true);
|
85
92
|
|
@@ -87,14 +94,7 @@ export const run = obj => {
|
|
87
94
|
Prefs.profileCompiler = false;
|
88
95
|
|
89
96
|
const { exports } = wrap(obj, undefined, {
|
90
|
-
|
91
|
-
activeFunc = n;
|
92
|
-
},
|
93
|
-
z: (i, n) => {
|
94
|
-
if (activeFunc == null) throw 'fail';
|
95
|
-
localData[activeFunc][i].push(n);
|
96
|
-
},
|
97
|
-
w: (ind, outPtr) => { // readArgv
|
97
|
+
readArgv: (ind, outPtr) => {
|
98
98
|
const pgoInd = process.argv.indexOf('--pgo');
|
99
99
|
let args = process.argv.slice(pgoInd);
|
100
100
|
args = args.slice(args.findIndex(x => !x.startsWith('-')) + 1);
|
@@ -108,7 +108,7 @@ export const run = obj => {
|
|
108
108
|
writeByteStr(exports.$, outPtr, str);
|
109
109
|
return str.length;
|
110
110
|
},
|
111
|
-
|
111
|
+
readFile: (pathPtr, outPtr) => {
|
112
112
|
return -1;
|
113
113
|
}
|
114
114
|
}, () => {});
|
package/compiler/wrap.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { encodeVector } from './encoding.js';
|
2
|
-
import { importedFuncs } from './builtins.js';
|
2
|
+
import { importedFuncs, createImport } from './builtins.js';
|
3
3
|
import compile from './index.js';
|
4
4
|
import disassemble from './disassemble.js';
|
5
5
|
import { TYPES, TYPE_NAMES } from './types.js';
|
@@ -352,16 +352,61 @@ ${flags & 0b0001 ? ` get func idx: ${get}
|
|
352
352
|
}
|
353
353
|
};
|
354
354
|
|
355
|
+
export { createImport };
|
355
356
|
export default (source, module = undefined, customImports = {}, print = str => process.stdout.write(str)) => {
|
357
|
+
createImport('print', 1, 0, i => print(i.toString()));
|
358
|
+
createImport('printChar', 1, 0, i => print(String.fromCharCode(i)));
|
359
|
+
createImport('time', 0, 1, () => performance.now());
|
360
|
+
createImport('timeOrigin', 0, 1, () => performance.timeOrigin);
|
361
|
+
|
362
|
+
// todo: these should be provided elsewhere in runtime itself
|
363
|
+
createImport('__Porffor_readArgv', 2, 1, (ind, outPtr) => {
|
364
|
+
let args = process.argv.slice(2);
|
365
|
+
args = args.slice(args.findIndex(x => !x.startsWith('-')) + 1);
|
366
|
+
|
367
|
+
const str = args[ind - 1];
|
368
|
+
if (!str) return -1;
|
369
|
+
|
370
|
+
writeByteStr(memory, outPtr, str);
|
371
|
+
return str.length;
|
372
|
+
});
|
373
|
+
createImport('__Porffor_readFile', 2, 1, (pathPtr, outPtr) => { // readFile
|
374
|
+
try {
|
375
|
+
const path = pathPtr === 0 ? 0 : readByteStr(memory, pathPtr);
|
376
|
+
const contents = fs.readFileSync(path, 'utf8');
|
377
|
+
writeByteStr(memory, outPtr, contents);
|
378
|
+
return contents.length;
|
379
|
+
} catch {
|
380
|
+
return -1;
|
381
|
+
}
|
382
|
+
});
|
383
|
+
|
384
|
+
for (const x in customImports) {
|
385
|
+
const custom = customImports[x];
|
386
|
+
|
387
|
+
if (x in importedFuncs) {
|
388
|
+
// overwrite with user custom import
|
389
|
+
const existing = importedFuncs[x];
|
390
|
+
if (typeof custom === 'function') {
|
391
|
+
existing.js = custom;
|
392
|
+
} else {
|
393
|
+
existing.params = custom.params;
|
394
|
+
existing.returns = custom.returns;
|
395
|
+
existing.js = custom.js;
|
396
|
+
existing.c = custom.c;
|
397
|
+
}
|
398
|
+
continue;
|
399
|
+
}
|
400
|
+
|
401
|
+
// todo: make a simpler api for just js functions at some point using function.length etc
|
402
|
+
createImport(x, custom.params, custom.returns, custom.js, custom.c);
|
403
|
+
}
|
404
|
+
|
356
405
|
const times = [];
|
357
406
|
|
358
407
|
const t1 = performance.now();
|
359
408
|
const { wasm, funcs, globals, tags, exceptions, pages, c } = typeof source === 'object' ? source : compile(source, module);
|
360
409
|
|
361
|
-
globalThis.porfDebugInfo = { funcs, globals };
|
362
|
-
|
363
|
-
// fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
364
|
-
|
365
410
|
times.push(performance.now() - t1);
|
366
411
|
if (Prefs.profileCompiler && !globalThis.onProgress) console.log(`\u001b[1mcompiled in ${times[0].toFixed(2)}ms\u001b[0m`);
|
367
412
|
|
@@ -448,35 +493,11 @@ export default (source, module = undefined, customImports = {}, print = str => p
|
|
448
493
|
try {
|
449
494
|
const module = new WebAssembly.Module(wasm);
|
450
495
|
instance = new WebAssembly.Instance(module, {
|
451
|
-
'': {
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
y: () => {},
|
457
|
-
z: () => {},
|
458
|
-
w: (ind, outPtr) => { // readArgv
|
459
|
-
let args = process.argv.slice(2);
|
460
|
-
args = args.slice(args.findIndex(x => !x.startsWith('-')) + 1);
|
461
|
-
|
462
|
-
const str = args[ind - 1];
|
463
|
-
if (!str) return -1;
|
464
|
-
|
465
|
-
writeByteStr(memory, outPtr, str);
|
466
|
-
return str.length;
|
467
|
-
},
|
468
|
-
q: (pathPtr, outPtr) => { // readFile
|
469
|
-
try {
|
470
|
-
const path = pathPtr === 0 ? 0 : readByteStr(memory, pathPtr);
|
471
|
-
const contents = fs.readFileSync(path, 'utf8');
|
472
|
-
writeByteStr(memory, outPtr, contents);
|
473
|
-
return contents.length;
|
474
|
-
} catch {
|
475
|
-
return -1;
|
476
|
-
}
|
477
|
-
},
|
478
|
-
...customImports
|
479
|
-
}
|
496
|
+
'': Object.keys(importedFuncs).reduce((acc, y) => {
|
497
|
+
const x = importedFuncs[y];
|
498
|
+
acc[x.import] = x.js ?? (() => {});
|
499
|
+
return acc;
|
500
|
+
}, {})
|
480
501
|
});
|
481
502
|
} catch (e) {
|
482
503
|
if (!Prefs.d) throw e;
|
package/package.json
CHANGED
package/runtime/debug.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
-
import compile from '../compiler/wrap.js';
|
2
|
+
import compile, { createImport } from '../compiler/wrap.js';
|
3
3
|
import Byg from '../byg/index.js';
|
4
4
|
import fs from 'node:fs';
|
5
5
|
|
@@ -41,75 +41,75 @@ let lastLine;
|
|
41
41
|
|
42
42
|
let output = '';
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
if (callStarts[callStarts.length - 1] === n - 1) {
|
48
|
-
// end of call
|
44
|
+
createImport('profile1', 1, 0, n => {
|
45
|
+
if (callStarts[callStarts.length - 1] === n - 1) {
|
46
|
+
// end of call
|
49
47
|
|
50
|
-
|
51
|
-
|
48
|
+
callStarts.pop();
|
49
|
+
callStack.pop();
|
52
50
|
|
53
|
-
|
54
|
-
|
51
|
+
paused = _paused;
|
52
|
+
}
|
55
53
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
}
|
76
|
-
]
|
77
|
-
)) {
|
78
|
-
case 'resume': {
|
79
|
-
paused = false;
|
80
|
-
break;
|
81
|
-
}
|
82
|
-
|
83
|
-
case 'stepOver': {
|
84
|
-
break;
|
85
|
-
}
|
86
|
-
|
87
|
-
case 'stepIn': {
|
88
|
-
stepIn = true;
|
89
|
-
// paused = false;
|
90
|
-
break;
|
91
|
-
}
|
92
|
-
|
93
|
-
case 'stepOut': {
|
94
|
-
stepOut = true;
|
95
|
-
paused = false;
|
96
|
-
break;
|
97
|
-
}
|
54
|
+
lastLine = n;
|
55
|
+
|
56
|
+
if (breakpoints[n]) paused = true;
|
57
|
+
|
58
|
+
if (paused) {
|
59
|
+
stepIn = false; stepOut = false;
|
60
|
+
|
61
|
+
switch (byg(
|
62
|
+
paused,
|
63
|
+
n,
|
64
|
+
`\x1b[1mporffor debugger\x1b[22m: ${file}@${n + 1} ${callStack.join('->')}`,
|
65
|
+
[
|
66
|
+
{
|
67
|
+
x: termWidth - 1 - 40 - 6,
|
68
|
+
y: () => 4,
|
69
|
+
width: 40,
|
70
|
+
height: 20,
|
71
|
+
title: 'console',
|
72
|
+
content: output.split('\n')
|
98
73
|
}
|
74
|
+
]
|
75
|
+
)) {
|
76
|
+
case 'resume': {
|
77
|
+
paused = false;
|
78
|
+
break;
|
99
79
|
}
|
100
|
-
},
|
101
|
-
z: n => {
|
102
|
-
// start of call
|
103
|
-
callStack.push(funcs[n]);
|
104
80
|
|
105
|
-
|
81
|
+
case 'stepOver': {
|
82
|
+
break;
|
83
|
+
}
|
106
84
|
|
107
|
-
|
108
|
-
|
109
|
-
|
85
|
+
case 'stepIn': {
|
86
|
+
stepIn = true;
|
87
|
+
// paused = false;
|
88
|
+
break;
|
89
|
+
}
|
90
|
+
|
91
|
+
case 'stepOut': {
|
92
|
+
stepOut = true;
|
93
|
+
paused = false;
|
94
|
+
break;
|
95
|
+
}
|
110
96
|
}
|
111
|
-
}
|
97
|
+
}
|
98
|
+
});
|
99
|
+
|
100
|
+
createImport('profile2', 1, 0, n => {
|
101
|
+
// start of call
|
102
|
+
callStack.push(funcs[n]);
|
103
|
+
|
104
|
+
callStarts.push(lastLine);
|
112
105
|
|
106
|
+
_paused = paused;
|
107
|
+
if (!stepIn) paused = false;
|
108
|
+
else paused = true;
|
109
|
+
});
|
110
|
+
|
111
|
+
try {
|
112
|
+
const { exports } = compile(source, undefined, {}, s => output += s);
|
113
113
|
exports.main();
|
114
114
|
} catch (e) {
|
115
115
|
console.error(e);
|
package/runtime/flamegraph.js
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
import { Opcodes, Valtype } from '../compiler/wasmSpec.js';
|
3
3
|
import { number } from '../compiler/encoding.js';
|
4
4
|
import { importedFuncs } from '../compiler/builtins.js';
|
5
|
-
import compile from '../compiler/wrap.js';
|
5
|
+
import compile, { createImport } from '../compiler/wrap.js';
|
6
6
|
import fs from 'node:fs';
|
7
7
|
|
8
8
|
const file = process.argv.slice(2).find(x => x[0] !== '-');
|
@@ -148,7 +148,19 @@ const render = () => {
|
|
148
148
|
lastRenderTime = performance.now() - renderStart;
|
149
149
|
};
|
150
150
|
|
151
|
-
|
151
|
+
createImport('profile1', 1, 0, f => { // pre-call
|
152
|
+
samplesStart.push(performance.now());
|
153
|
+
running[runningIdx++] = samplesFunc.push(f) - 1;
|
154
|
+
});
|
155
|
+
createImport('profile2', 1, 0, f => { // post-call
|
156
|
+
const now = performance.now();
|
157
|
+
samplesEnd[running[--runningIdx]] = now;
|
158
|
+
|
159
|
+
if (now > last) {
|
160
|
+
last = now + 500;
|
161
|
+
render();
|
162
|
+
}
|
163
|
+
});
|
152
164
|
|
153
165
|
Prefs.treeshakeWasmImports = false;
|
154
166
|
let funcLookup = new Map();
|
@@ -180,21 +192,7 @@ globalThis.compileCallback = ({ funcs }) => {
|
|
180
192
|
|
181
193
|
let last = 0;
|
182
194
|
let running = new Uint32Array(1024), runningIdx = 0;
|
183
|
-
const { exports } = compile(source, undefined, {
|
184
|
-
y: f => { // pre-call
|
185
|
-
samplesStart.push(performance.now());
|
186
|
-
running[runningIdx++] = samplesFunc.push(f) - 1;
|
187
|
-
},
|
188
|
-
z: f => { // post-call
|
189
|
-
const now = performance.now();
|
190
|
-
samplesEnd[running[--runningIdx]] = now;
|
191
|
-
|
192
|
-
if (now > last) {
|
193
|
-
last = now + 500;
|
194
|
-
render();
|
195
|
-
}
|
196
|
-
}
|
197
|
-
}, () => {});
|
195
|
+
const { exports } = compile(source, undefined, {}, () => {});
|
198
196
|
|
199
197
|
start = performance.now();
|
200
198
|
render();
|
package/runtime/hotlines.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
-
import compile from '../compiler/wrap.js';
|
2
|
+
import compile, { createImport } from '../compiler/wrap.js';
|
3
3
|
import fs from 'node:fs';
|
4
4
|
|
5
5
|
const file = process.argv.slice(2).find(x => x[0] !== '-');
|
@@ -18,29 +18,26 @@ const spinner = ['-', '\\', '|', '/'];
|
|
18
18
|
let spin = 0;
|
19
19
|
let last = 0;
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
const t = performance.now();
|
28
|
-
times[n] += t - tmp[n];
|
29
|
-
|
30
|
-
samples++;
|
31
|
-
if (t > last) {
|
32
|
-
process.stdout.write(`\r${spinner[spin++ % 4]} running: collected ${samples} samples...`);
|
33
|
-
last = t + 100;
|
34
|
-
}
|
35
|
-
}
|
36
|
-
});
|
21
|
+
createImport('profile1', 1, 0, n => {
|
22
|
+
tmp[n] = performance.now();
|
23
|
+
});
|
24
|
+
createImport('profile2', 1, 0, n => {
|
25
|
+
const t = performance.now();
|
26
|
+
times[n] += t - tmp[n];
|
37
27
|
|
38
|
-
|
28
|
+
samples++;
|
29
|
+
if (t > last) {
|
30
|
+
process.stdout.write(`\r${spinner[spin++ % 4]} running: collected ${samples} samples...`);
|
31
|
+
last = t + 100;
|
32
|
+
}
|
33
|
+
})
|
39
34
|
|
35
|
+
try {
|
36
|
+
const { exports } = compile(source, undefined);
|
37
|
+
const start = performance.now();
|
40
38
|
exports.main();
|
41
39
|
|
42
40
|
const total = performance.now() - start;
|
43
|
-
|
44
41
|
console.log(`\ntotal: ${total}ms\nsamples: ${samples}\n\n\n` + source.split('\n').map(x => {
|
45
42
|
let time = 0;
|
46
43
|
if (x.startsWith('profile')) {
|