porffor 0.2.0-623cdf0 → 0.2.0-6aff0fa
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/README.md +69 -44
- package/asur/README.md +2 -0
- package/asur/index.js +978 -0
- package/compiler/2c.js +11 -11
- package/compiler/builtins/base64.ts +153 -0
- package/compiler/builtins/porffor.d.ts +23 -0
- package/compiler/builtins.js +65 -192
- package/compiler/codeGen.js +206 -110
- package/compiler/generated_builtins.js +15 -0
- package/compiler/index.js +9 -20
- package/compiler/log.js +4 -1
- package/compiler/opt.js +39 -26
- package/compiler/parse.js +4 -2
- package/compiler/precompile.js +129 -0
- package/compiler/prefs.js +26 -0
- package/compiler/prototype.js +11 -10
- package/compiler/sections.js +7 -6
- package/compiler/wasmSpec.js +14 -7
- package/compiler/wrap.js +12 -4
- package/package.json +1 -1
- package/porf +2 -0
- package/rhemyn/compile.js +2 -1
- package/runner/index.js +12 -2
- package/runner/profiler.js +83 -0
- package/compiler/builtins/base64.js +0 -92
- package/filesize.cmd +0 -2
- package/runner/profile.js +0 -46
- package/runner/results.json +0 -1
package/compiler/wasmSpec.js
CHANGED
@@ -32,17 +32,16 @@ export const Opcodes = {
|
|
32
32
|
throw: 0x08,
|
33
33
|
rethrow: 0x09,
|
34
34
|
|
35
|
-
call: 0x10,
|
36
|
-
call_indirect: 0x11,
|
37
|
-
return_call: 0x12,
|
38
|
-
return_call_indirect: 0x13,
|
39
|
-
|
40
35
|
end: 0x0b,
|
41
36
|
br: 0x0c,
|
42
37
|
br_if: 0x0d,
|
43
38
|
br_table: 0x0e,
|
44
39
|
return: 0x0f,
|
40
|
+
|
45
41
|
call: 0x10,
|
42
|
+
call_indirect: 0x11,
|
43
|
+
return_call: 0x12,
|
44
|
+
return_call_indirect: 0x13,
|
46
45
|
|
47
46
|
drop: 0x1a,
|
48
47
|
|
@@ -62,13 +61,21 @@ export const Opcodes = {
|
|
62
61
|
i32_load16_s: 0x2e,
|
63
62
|
i32_load16_u: 0x2f,
|
64
63
|
|
65
|
-
|
66
|
-
|
64
|
+
i64_load8_s: 0x30,
|
65
|
+
i64_load8_u: 0x31,
|
66
|
+
i64_load16_s: 0x32,
|
67
|
+
i64_load16_u: 0x33,
|
67
68
|
|
68
69
|
i32_store: 0x36,
|
69
70
|
i64_store: 0x37,
|
70
71
|
f64_store: 0x39,
|
71
72
|
|
73
|
+
i32_store8: 0x3a,
|
74
|
+
i32_store16: 0x3b,
|
75
|
+
|
76
|
+
i64_store8: 0x3c,
|
77
|
+
i64_store16: 0x3d,
|
78
|
+
|
72
79
|
memory_grow: 0x40,
|
73
80
|
|
74
81
|
i32_const: 0x41,
|
package/compiler/wrap.js
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
import compile from './index.js';
|
2
2
|
import decompile from './decompile.js';
|
3
3
|
import { encodeVector, encodeLocal } from './encoding.js';
|
4
|
-
|
4
|
+
import Prefs from './prefs.js';
|
5
|
+
import { log } from './log.js';
|
5
6
|
|
6
7
|
const bold = x => `\u001b[1m${x}\u001b[0m`;
|
7
8
|
|
@@ -31,7 +32,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
31
32
|
|
32
33
|
if (source.includes('export function')) flags.push('module');
|
33
34
|
|
34
|
-
// fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
35
|
+
// (await import('node:fs')).writeFileSync('out.wasm', Buffer.from(wasm));
|
35
36
|
|
36
37
|
times.push(performance.now() - t1);
|
37
38
|
if (flags.includes('info')) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
|
@@ -40,7 +41,13 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
40
41
|
|
41
42
|
let instance;
|
42
43
|
try {
|
43
|
-
|
44
|
+
let wasmEngine = WebAssembly;
|
45
|
+
if (Prefs.asur) {
|
46
|
+
log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
|
47
|
+
wasmEngine = await import('../asur/index.js');
|
48
|
+
}
|
49
|
+
|
50
|
+
0, { instance } = await wasmEngine.instantiate(wasm, {
|
44
51
|
'': {
|
45
52
|
p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
|
46
53
|
c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
|
@@ -191,7 +198,8 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
191
198
|
case 'function': {
|
192
199
|
// wasm func index, including all imports
|
193
200
|
const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
|
194
|
-
if (!func) return ret;
|
201
|
+
// if (!func) return ret;
|
202
|
+
if (!func) return function () {};
|
195
203
|
|
196
204
|
// make fake empty func for repl/etc
|
197
205
|
return {[func.name]() {}}[func.name];
|
package/package.json
CHANGED
package/porf
ADDED
package/rhemyn/compile.js
CHANGED
@@ -2,6 +2,7 @@ import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from '../compiler/
|
|
2
2
|
import { number } from '../compiler/embedding.js';
|
3
3
|
import { signedLEB128, unsignedLEB128 } from '../compiler/encoding.js';
|
4
4
|
import parse from './parse.js';
|
5
|
+
import Prefs from '../compiler/prefs.js';
|
5
6
|
|
6
7
|
// local indexes
|
7
8
|
const BasePointer = 0; // base string pointer
|
@@ -80,7 +81,7 @@ const generate = (node, negated = false, get = true, func = 'test') => {
|
|
80
81
|
})[func], Valtype.i32)
|
81
82
|
];
|
82
83
|
|
83
|
-
if (
|
84
|
+
if (Prefs.regexLog) {
|
84
85
|
const underline = x => `\u001b[4m\u001b[1m${x}\u001b[0m`;
|
85
86
|
console.log(`\n${underline('ast')}`);
|
86
87
|
console.log(node);
|
package/runner/index.js
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
import compile from '../compiler/wrap.js';
|
4
4
|
import fs from 'node:fs';
|
5
5
|
|
6
|
+
const start = performance.now();
|
7
|
+
|
6
8
|
if (process.argv.includes('-compile-hints')) {
|
7
9
|
const v8 = await import('node:v8');
|
8
10
|
v8.setFlagsFromString(`--experimental-wasm-compilation-hints`);
|
@@ -16,7 +18,13 @@ if (process.argv.includes('-compile-hints')) {
|
|
16
18
|
}
|
17
19
|
|
18
20
|
let file = process.argv.slice(2).find(x => x[0] !== '-');
|
19
|
-
if (['run', 'wasm', 'native', 'c'].includes(file)) {
|
21
|
+
if (['run', 'wasm', 'native', 'c', 'profile'].includes(file)) {
|
22
|
+
if (file === 'profile') {
|
23
|
+
process.argv.splice(process.argv.indexOf(file), 1);
|
24
|
+
await import('./profiler.js');
|
25
|
+
await new Promise(() => {});
|
26
|
+
}
|
27
|
+
|
20
28
|
if (['wasm', 'native', 'c'].includes(file)) {
|
21
29
|
process.argv.push(`-target=${file}`);
|
22
30
|
}
|
@@ -65,4 +73,6 @@ try {
|
|
65
73
|
} catch (e) {
|
66
74
|
if (cache) process.stdout.write(cache);
|
67
75
|
console.error(process.argv.includes('-i') ? e : `${e.constructor.name}: ${e.message}`);
|
68
|
-
}
|
76
|
+
}
|
77
|
+
|
78
|
+
if (process.argv.includes('-t')) console.log(`\n\ntotal time: ${(performance.now() - start).toFixed(2)}ms`);
|
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
import compile from '../compiler/wrap.js';
|
4
|
+
import fs from 'node:fs';
|
5
|
+
|
6
|
+
import Prefs from '../compiler/prefs.js';
|
7
|
+
|
8
|
+
const fast = Prefs.profiler === 'fast';
|
9
|
+
|
10
|
+
const file = process.argv.slice(2).find(x => x[0] !== '-');
|
11
|
+
let source = fs.readFileSync(file, 'utf8');
|
12
|
+
|
13
|
+
let profileId = 0;
|
14
|
+
source = fast ? source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});${_}profile(${profileId++});`) : source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});profile(${profileId++});${_}profile(${profileId++});`);
|
15
|
+
|
16
|
+
// console.log(source);
|
17
|
+
|
18
|
+
let tmp = new Array(profileId).fill(0);
|
19
|
+
let samples = 0;
|
20
|
+
|
21
|
+
const percents = process.argv.includes('-%');
|
22
|
+
|
23
|
+
const spinner = ['-', '\\', '|', '/'];
|
24
|
+
let spin = 0;
|
25
|
+
let last = 0;
|
26
|
+
|
27
|
+
try {
|
28
|
+
const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {
|
29
|
+
z: fast ? n => {
|
30
|
+
if (n % 2) {
|
31
|
+
tmp[n] += performance.now() - tmp[n - 1];
|
32
|
+
} else {
|
33
|
+
tmp[n] = performance.now();
|
34
|
+
}
|
35
|
+
} : n => {
|
36
|
+
if (n % 3 === 2) {
|
37
|
+
tmp[n] += (performance.now() - tmp[n - 1]) - (tmp[n - 1] - tmp[n - 2]);
|
38
|
+
samples++;
|
39
|
+
|
40
|
+
if (performance.now() > last) {
|
41
|
+
process.stdout.write(`\r${spinner[spin++ % 4]} running: collected ${samples} samples...`);
|
42
|
+
last = performance.now() + 100;
|
43
|
+
}
|
44
|
+
} else {
|
45
|
+
tmp[n] = performance.now();
|
46
|
+
}
|
47
|
+
}
|
48
|
+
});
|
49
|
+
|
50
|
+
const start = performance.now();
|
51
|
+
|
52
|
+
exports.main();
|
53
|
+
|
54
|
+
const total = performance.now() - start;
|
55
|
+
|
56
|
+
console.log(`\nsamples: ${fast ? 'not measured' : samples}\ntotal: ${total}ms\n\n` + source.split('\n').map(x => {
|
57
|
+
let time = 0;
|
58
|
+
if (x.startsWith('profile')) {
|
59
|
+
const id = parseInt(x.slice(8, x.indexOf(')')));
|
60
|
+
time = fast ? tmp[id + 1] : tmp[id + 2];
|
61
|
+
}
|
62
|
+
|
63
|
+
let color = [ 0, 0, 0 ];
|
64
|
+
if (time) {
|
65
|
+
const relativeTime = Math.sqrt(time / total);
|
66
|
+
if (percents) time = relativeTime;
|
67
|
+
|
68
|
+
color = [ (relativeTime * 250) | 0, (Math.sin(relativeTime * Math.PI) * 50) | 0, 0 ];
|
69
|
+
}
|
70
|
+
|
71
|
+
const ansiColor = `2;${color[0]};${color[1]};${color[2]}m`;
|
72
|
+
|
73
|
+
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, '')}`;
|
74
|
+
|
75
|
+
let digits = 2;
|
76
|
+
if (time >= 100) digits = 1;
|
77
|
+
if (time >= 1000) digits = 0;
|
78
|
+
|
79
|
+
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, '')}`;
|
80
|
+
}).join('\n'));
|
81
|
+
} catch (e) {
|
82
|
+
console.error(e);
|
83
|
+
}
|
@@ -1,92 +0,0 @@
|
|
1
|
-
var btoa_a = str => {
|
2
|
-
// todo: throw invalid character for unicode
|
3
|
-
|
4
|
-
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
5
|
-
const mask = (1 << 6) - 1;
|
6
|
-
|
7
|
-
let out = '';
|
8
|
-
let bits = 0, buffer = 0;
|
9
|
-
for (let i = 0; i < str.length; i++) {
|
10
|
-
buffer = (buffer << 8) | (0xff & str.charCodeAt(i));
|
11
|
-
bits += 8;
|
12
|
-
|
13
|
-
while (bits > 6) {
|
14
|
-
bits -= 6;
|
15
|
-
out += chars[mask & (buffer >> bits)];
|
16
|
-
}
|
17
|
-
}
|
18
|
-
|
19
|
-
if (bits) {
|
20
|
-
out += chars[mask & (buffer << (6 - bits))]
|
21
|
-
}
|
22
|
-
|
23
|
-
while ((out.length * 6) & 7) {
|
24
|
-
out += '=';
|
25
|
-
}
|
26
|
-
|
27
|
-
return out;
|
28
|
-
};
|
29
|
-
|
30
|
-
var btoa = function (input) {
|
31
|
-
// todo: throw invalid character for unicode
|
32
|
-
const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
33
|
-
|
34
|
-
let output = "";
|
35
|
-
let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
36
|
-
let i = 0;
|
37
|
-
|
38
|
-
while (i < input.length) {
|
39
|
-
chr1 = input.charCodeAt(i++);
|
40
|
-
chr2 = input.charCodeAt(i++);
|
41
|
-
chr3 = input.charCodeAt(i++);
|
42
|
-
|
43
|
-
enc1 = chr1 >> 2;
|
44
|
-
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
45
|
-
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
46
|
-
enc4 = chr3 & 63;
|
47
|
-
|
48
|
-
if (isNaN(chr2)) {
|
49
|
-
enc3 = enc4 = 64;
|
50
|
-
} else if (isNaN(chr3)) {
|
51
|
-
enc4 = 64;
|
52
|
-
}
|
53
|
-
|
54
|
-
output += keyStr.charAt(enc1);
|
55
|
-
output += keyStr.charAt(enc2);
|
56
|
-
output += keyStr.charAt(enc3);
|
57
|
-
output += keyStr.charAt(enc4);
|
58
|
-
}
|
59
|
-
|
60
|
-
return output;
|
61
|
-
};
|
62
|
-
|
63
|
-
var atob_b = function (input) {
|
64
|
-
const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
65
|
-
|
66
|
-
let output = "";
|
67
|
-
let chr1, chr2, chr3;
|
68
|
-
let enc1, enc2, enc3, enc4;
|
69
|
-
let i = 0;
|
70
|
-
|
71
|
-
while (i < input.length) {
|
72
|
-
enc1 = keyStr.indexOf(input.charAt(i++));
|
73
|
-
enc2 = keyStr.indexOf(input.charAt(i++));
|
74
|
-
enc3 = keyStr.indexOf(input.charAt(i++));
|
75
|
-
enc4 = keyStr.indexOf(input.charAt(i++));
|
76
|
-
|
77
|
-
chr1 = (enc1 << 2) | (enc2 >> 4);
|
78
|
-
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
79
|
-
chr3 = ((enc3 & 3) << 6) | enc4;
|
80
|
-
|
81
|
-
output += String.fromCharCode(chr1);
|
82
|
-
|
83
|
-
if (enc3 != 64) {
|
84
|
-
output += String.fromCharCode(chr2);
|
85
|
-
}
|
86
|
-
if (enc4 != 64) {
|
87
|
-
output += String.fromCharCode(chr3);
|
88
|
-
}
|
89
|
-
}
|
90
|
-
|
91
|
-
return output;
|
92
|
-
};
|
package/filesize.cmd
DELETED
package/runner/profile.js
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
import compile from '../compiler/index.js';
|
2
|
-
import fs from 'node:fs';
|
3
|
-
|
4
|
-
let csv = `phase,time\n`;
|
5
|
-
|
6
|
-
csv += `node,${performance.now()}\n`;
|
7
|
-
|
8
|
-
const t0 = performance.now();
|
9
|
-
const file = process.argv.slice(2).find(x => x[0] !== '-');
|
10
|
-
const source = fs.readFileSync(file, 'utf8');
|
11
|
-
csv += `read,${performance.now() - t0}\n`;
|
12
|
-
|
13
|
-
console.log = x => {
|
14
|
-
if (x.includes(' in ')) {
|
15
|
-
csv += [ 'parse', 'codegen', 'opt', 'sections' ][parseInt(x[0]) - 1] + ',' + x.split(' in ')[1].slice(0, -2) + '\n';
|
16
|
-
}
|
17
|
-
};
|
18
|
-
|
19
|
-
const wasm = compile(source, [ 'info' ]);
|
20
|
-
|
21
|
-
let cache = '';
|
22
|
-
const print = str => {
|
23
|
-
cache += str;
|
24
|
-
|
25
|
-
if (str === '\n') {
|
26
|
-
process.stdout.write(cache);
|
27
|
-
cache = '';
|
28
|
-
}
|
29
|
-
};
|
30
|
-
|
31
|
-
const t1 = performance.now();
|
32
|
-
const { instance } = await WebAssembly.instantiate(wasm, {
|
33
|
-
'': {
|
34
|
-
p: i => print(Number(i).toString()),
|
35
|
-
c: i => print(String.fromCharCode(Number(i)))
|
36
|
-
}
|
37
|
-
});
|
38
|
-
csv += `inst,${performance.now() - t1}\n`;
|
39
|
-
|
40
|
-
const t2 = performance.now();
|
41
|
-
instance.exports.m();
|
42
|
-
print('\n');
|
43
|
-
|
44
|
-
csv += `exec,${performance.now() - t2}`;
|
45
|
-
|
46
|
-
fs.writeFileSync(`profile.csv`, csv);
|