porffor 0.16.0-6572d1c74 → 0.16.0-7143cc59c
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/CONTRIBUTING.md +1 -1
- package/README.md +3 -4
- package/compiler/2c.js +75 -15
- package/compiler/allocators.js +128 -0
- package/compiler/assemble.js +7 -1
- package/compiler/builtins/array.ts +3 -4
- package/compiler/builtins/date.ts +2 -5
- package/compiler/builtins/set.ts +2 -5
- package/compiler/codegen.js +253 -300
- package/compiler/cyclone.js +11 -11
- package/compiler/generated_builtins.js +46 -46
- package/compiler/index.js +30 -3
- package/compiler/opt.js +7 -5
- package/compiler/parse.js +1 -7
- package/compiler/pgo.js +13 -8
- package/compiler/precompile.js +12 -7
- package/compiler/prefs.js +2 -3
- package/compiler/prototype.js +34 -43
- package/compiler/wasmSpec.js +2 -2
- package/compiler/wrap.js +3 -2
- package/package.json +3 -5
- package/runner/index.js +13 -3
- package/no_pgo.txt +0 -923
- package/pgo.txt +0 -916
package/compiler/index.js
CHANGED
@@ -45,6 +45,8 @@ export default (code, flags) => {
|
|
45
45
|
if (target !== 'wasm') Prefs.pgo = Prefs.pgo === false ? false : true;
|
46
46
|
if (Prefs.pgo) pgo.setup();
|
47
47
|
|
48
|
+
if (Prefs.profileCompiler) console.log(`0. began compilation (host runtime startup) in ${performance.now().toFixed(2)}ms`);
|
49
|
+
|
48
50
|
const t0 = performance.now();
|
49
51
|
const program = parse(code, flags);
|
50
52
|
if (Prefs.profileCompiler) console.log(`1. parsed in ${(performance.now() - t0).toFixed(2)}ms`);
|
@@ -107,7 +109,7 @@ export default (code, flags) => {
|
|
107
109
|
|
108
110
|
if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
|
109
111
|
|
110
|
-
if (Prefs.
|
112
|
+
if (Prefs.compileAllocLog) {
|
111
113
|
const wasmPages = Math.ceil((pages.size * pageSize) / 65536);
|
112
114
|
const bytes = wasmPages * 65536;
|
113
115
|
log('alloc', `\x1B[1mallocated ${bytes / 1024}KiB\x1B[0m for ${pages.size} things using ${wasmPages} Wasm page${wasmPages === 1 ? '' : 's'}`);
|
@@ -148,7 +150,12 @@ export default (code, flags) => {
|
|
148
150
|
const args = [ ...compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO ];
|
149
151
|
if (!Prefs.compiler) args.push('-flto=thin', '-march=native', '-s', '-ffast-math', '-fno-exceptions', '-fno-ident', '-fno-asynchronous-unwind-tables', '-ffunction-sections', '-fdata-sections', '-Wl,--gc-sections');
|
150
152
|
|
153
|
+
const t4 = performance.now();
|
151
154
|
const c = toc(out);
|
155
|
+
if (Prefs.profileCompiler) console.log(`5. compiled to c in ${(performance.now() - t4).toFixed(2)}ms`);
|
156
|
+
|
157
|
+
const t5 = performance.now();
|
158
|
+
|
152
159
|
fs.writeFileSync(tmpfile, c);
|
153
160
|
|
154
161
|
// obvious command escape is obvious
|
@@ -156,12 +163,32 @@ export default (code, flags) => {
|
|
156
163
|
|
157
164
|
fs.unlinkSync(tmpfile);
|
158
165
|
|
166
|
+
if (Prefs.profileCompiler) console.log(`6. compiled to native (using ${compiler}) in ${(performance.now() - t5).toFixed(2)}ms`);
|
167
|
+
|
159
168
|
if (process.version) {
|
160
169
|
if (Prefs.native) {
|
170
|
+
const cleanup = () => {
|
171
|
+
try {
|
172
|
+
fs.unlinkSync(outFile);
|
173
|
+
} catch {}
|
174
|
+
};
|
175
|
+
|
176
|
+
process.on('exit', cleanup);
|
177
|
+
process.on('beforeExit', cleanup);
|
178
|
+
process.on('SIGINT', () => {
|
179
|
+
cleanup();
|
180
|
+
process.exit();
|
181
|
+
});
|
182
|
+
|
161
183
|
const runArgs = process.argv.slice(2).filter(x => !x.startsWith('-'));
|
162
|
-
|
184
|
+
try {
|
185
|
+
execSync([ outFile, ...runArgs.slice(1) ].join(' '), { stdio: 'inherit' });
|
186
|
+
} catch {}
|
187
|
+
}
|
163
188
|
|
164
|
-
|
189
|
+
if (!Prefs.native && globalThis.file) {
|
190
|
+
const total = performance.now();
|
191
|
+
console.log(`\u001b[90m[${total.toFixed(2)}ms]\u001b[0m \u001b[92mcompiled ${globalThis.file} -> ${outFile}\u001b[0m`);
|
165
192
|
}
|
166
193
|
|
167
194
|
process.exit();
|
package/compiler/opt.js
CHANGED
@@ -125,6 +125,8 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
125
125
|
// main pass
|
126
126
|
for (let i = 0; i < wasm.length; i++) {
|
127
127
|
let inst = wasm[i];
|
128
|
+
inst = [ ...inst ];
|
129
|
+
wasm[i] = inst;
|
128
130
|
|
129
131
|
if (inst[0] === Opcodes.if || inst[0] === Opcodes.loop || inst[0] === Opcodes.block) depth.push(inst[0]);
|
130
132
|
if (inst[0] === Opcodes.end) depth.pop();
|
@@ -172,14 +174,14 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
172
174
|
}
|
173
175
|
}
|
174
176
|
|
175
|
-
if (inst[inst.length - 1] === 'string_only' && !pages.hasAnyString &&
|
177
|
+
if (inst[inst.length - 1] === 'string_only' && !pages.hasAnyString && Prefs.rmUnusedTypes) {
|
176
178
|
// remove this inst
|
177
179
|
wasm.splice(i, 1);
|
178
180
|
if (i > 0) i--;
|
179
181
|
inst = wasm[i];
|
180
182
|
}
|
181
183
|
|
182
|
-
if (inst[inst.length - 1] === 'string_only|start' && !pages.hasAnyString&&
|
184
|
+
if (inst[inst.length - 1] === 'string_only|start' && !pages.hasAnyString && Prefs.rmUnusedTypes) {
|
183
185
|
let j = i;
|
184
186
|
for (; j < wasm.length; j++) {
|
185
187
|
const op = wasm[j];
|
@@ -193,7 +195,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
193
195
|
inst = wasm[i];
|
194
196
|
}
|
195
197
|
|
196
|
-
if (inst[0] === Opcodes.if && typeof inst[2] === 'string' &&
|
198
|
+
if (inst[0] === Opcodes.if && typeof inst[2] === 'string' && Prefs.rmUnusedTypes) {
|
197
199
|
// remove unneeded typeswitch checks
|
198
200
|
|
199
201
|
const type = inst[2].split('|')[1];
|
@@ -221,7 +223,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
221
223
|
}
|
222
224
|
}
|
223
225
|
|
224
|
-
if (inst[0] === Opcodes.end && inst[1] === 'TYPESWITCH_end') {
|
226
|
+
if (inst[0] === Opcodes.end && inst[1] === 'TYPESWITCH_end' && Prefs.rmUnusedTypes) {
|
225
227
|
// remove unneeded entire typeswitch
|
226
228
|
|
227
229
|
let j = i - 1, depth = -1, checks = 0;
|
@@ -369,7 +371,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
369
371
|
continue;
|
370
372
|
}
|
371
373
|
|
372
|
-
if (lastInst[0] === Opcodes.i32_const && (inst === Opcodes.i32_from || inst === Opcodes.i32_from_u)) {
|
374
|
+
if (lastInst[0] === Opcodes.i32_const && (inst[0] === Opcodes.i32_from[0] || inst[0] === Opcodes.i32_from_u[0])) {
|
373
375
|
// change i32 const and immediate convert to const (opposite way of previous)
|
374
376
|
// i32.const 0
|
375
377
|
// f64.convert_i32_s || f64.convert_i32_u
|
package/compiler/parse.js
CHANGED
@@ -1,12 +1,6 @@
|
|
1
1
|
import { log } from './log.js';
|
2
2
|
import Prefs from './prefs.js';
|
3
3
|
|
4
|
-
// deno compat
|
5
|
-
if (typeof process === 'undefined' && typeof Deno !== 'undefined') {
|
6
|
-
const textEncoder = new TextEncoder();
|
7
|
-
globalThis.process = { argv: ['', '', ...Deno.args], stdout: { write: str => Deno.writeAllSync(Deno.stdout, textEncoder.encode(str)) } };
|
8
|
-
}
|
9
|
-
|
10
4
|
const file = process.argv.slice(2).find(x => x[0] !== '-' && !['run', 'wasm', 'native', 'c', 'profile', 'debug', 'debug-wasm'].includes(x));
|
11
5
|
|
12
6
|
// should we try to support types (while parsing)
|
@@ -43,7 +37,7 @@ export default (input, flags) => {
|
|
43
37
|
webcompat: true,
|
44
38
|
|
45
39
|
// babel
|
46
|
-
plugins: types ? ['estree', 'typescript'] : ['estree'],
|
40
|
+
plugins: types || flags.includes('typed') ? ['estree', 'typescript'] : ['estree'],
|
47
41
|
|
48
42
|
// multiple
|
49
43
|
sourceType: flags.includes('module') ? 'module' : 'script',
|
package/compiler/pgo.js
CHANGED
@@ -11,7 +11,7 @@ export const setup = () => {
|
|
11
11
|
|
12
12
|
// enable these prefs by default for pgo
|
13
13
|
Prefs.typeswitchUniqueTmp = Prefs.typeswitchUniqueTmp === false ? false : true;
|
14
|
-
Prefs.cyclone = Prefs.cyclone === false ? false : true
|
14
|
+
Prefs.cyclone = Prefs.cyclone === false ? false : true;
|
15
15
|
};
|
16
16
|
|
17
17
|
export const run = obj => {
|
@@ -78,6 +78,9 @@ export const run = obj => {
|
|
78
78
|
try {
|
79
79
|
obj.wasm = assemble(obj.funcs, obj.globals, obj.tags, obj.pages, obj.data, obj.flags, true);
|
80
80
|
|
81
|
+
Prefs._profileCompiler = Prefs.profileCompiler;
|
82
|
+
Prefs.profileCompiler = false;
|
83
|
+
|
81
84
|
const { exports } = wrap(obj, [], {
|
82
85
|
y: n => {
|
83
86
|
activeFunc = n;
|
@@ -105,6 +108,8 @@ export const run = obj => {
|
|
105
108
|
throw e;
|
106
109
|
}
|
107
110
|
|
111
|
+
Prefs.profileCompiler = Prefs._profileCompiler;
|
112
|
+
|
108
113
|
for (const x of funcs) {
|
109
114
|
const wasmFunc = wasmFuncs.find(y => y.name === x.name);
|
110
115
|
wasmFunc.wasm = wasmFunc.originalWasm;
|
@@ -131,16 +136,18 @@ export const run = obj => {
|
|
131
136
|
func.localValues = localValues;
|
132
137
|
|
133
138
|
let counts = new Array(10).fill(0);
|
134
|
-
const consistents = localData[i].map(x => {
|
135
|
-
if (
|
139
|
+
const consistents = localData[i].map((x, j) => {
|
140
|
+
if (j < func.params.length) return false; // param
|
141
|
+
if (x.length === 0 || !x.every((y, i) => i < 1 ? true : y === x[i - 1])) return false; // not consistent
|
136
142
|
|
137
143
|
counts[0]++;
|
138
144
|
return x[0];
|
139
145
|
});
|
140
146
|
|
141
147
|
const integerOnlyF64s = localData[i].map((x, j) => {
|
148
|
+
if (j < func.params.length) return false; // param
|
142
149
|
if (localValues[j].type === Valtype.i32) return false; // already i32
|
143
|
-
if (x.length === 0 || !x.every(y => Number.isInteger(y))) return false;
|
150
|
+
if (x.length === 0 || !x.every(y => Number.isInteger(y))) return false; // not all integer values
|
144
151
|
|
145
152
|
counts[1]++;
|
146
153
|
return true;
|
@@ -151,14 +158,14 @@ export const run = obj => {
|
|
151
158
|
|
152
159
|
log += ` ${func.name}: identified ${counts[0]}/${total} locals as consistent${Prefs.verbosePgo ? ':' : ''}\n`;
|
153
160
|
if (Prefs.verbosePgo) {
|
154
|
-
for (let j =
|
161
|
+
for (let j = func.params.length; j < localData[i].length; j++) {
|
155
162
|
log += ` ${consistents[j] !== false ? '\u001b[92m' : '\u001b[91m'}${localKeys[j]}\u001b[0m: ${new Set(localData[i][j]).size} unique values set\n`;
|
156
163
|
}
|
157
164
|
}
|
158
165
|
|
159
166
|
log += ` ${func.name}: identified ${counts[1]}/${localValues.reduce((acc, x) => acc + (x.type === Valtype.f64 ? 1 : 0), 0)} f64 locals as integer usage only${Prefs.verbosePgo ? ':' : ''}\n`;
|
160
167
|
if (Prefs.verbosePgo) {
|
161
|
-
for (let j =
|
168
|
+
for (let j = func.params.length; j < localData[i].length; j++) {
|
162
169
|
if (localValues[j].type !== Valtype.f64) continue;
|
163
170
|
log += ` ${integerOnlyF64s[j] ? '\u001b[92m' : '\u001b[91m'}${localKeys[j]}\u001b[0m\n`;
|
164
171
|
}
|
@@ -178,7 +185,6 @@ export const run = obj => {
|
|
178
185
|
for (let i = 0; i < x.integerOnlyF64s.length; i++) {
|
179
186
|
const c = x.integerOnlyF64s[i];
|
180
187
|
if (c === false) continue;
|
181
|
-
if (i < x.params.length) continue;
|
182
188
|
|
183
189
|
targets.push(i);
|
184
190
|
}
|
@@ -191,7 +197,6 @@ export const run = obj => {
|
|
191
197
|
for (let i = 0; i < x.consistents.length; i++) {
|
192
198
|
const c = x.consistents[i];
|
193
199
|
if (c === false) continue;
|
194
|
-
if (i < x.params.length) continue;
|
195
200
|
|
196
201
|
targets.push(i);
|
197
202
|
|
package/compiler/precompile.js
CHANGED
@@ -26,7 +26,7 @@ const compile = async (file, [ _funcs, _globals ]) => {
|
|
26
26
|
|
27
27
|
const porfCompile = (await import(`./index.js?_=${Date.now()}`)).default;
|
28
28
|
|
29
|
-
let { funcs, globals, data, exceptions } = porfCompile(source, ['module']);
|
29
|
+
let { funcs, globals, data, exceptions } = porfCompile(source, ['module', 'typed']);
|
30
30
|
|
31
31
|
const allocated = new Set();
|
32
32
|
|
@@ -35,14 +35,17 @@ const compile = async (file, [ _funcs, _globals ]) => {
|
|
35
35
|
if (x.data) {
|
36
36
|
x.data = x.data.map(x => data[x]);
|
37
37
|
for (const y in x.data) {
|
38
|
-
x.data[y].offset -= x.data[0].offset;
|
38
|
+
if (x.data[y].offset != null) x.data[y].offset -= x.data[0].offset;
|
39
39
|
}
|
40
40
|
}
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
|
42
|
+
if (x.exceptions) {
|
43
|
+
x.exceptions = x.exceptions.map(x => {
|
44
|
+
const obj = exceptions[x];
|
45
|
+
if (obj) obj.exceptId = x;
|
46
|
+
return obj;
|
47
|
+
}).filter(x => x);
|
48
|
+
}
|
46
49
|
|
47
50
|
const locals = Object.keys(x.locals).reduce((acc, y) => {
|
48
51
|
acc[x.locals[y].idx] = { ...x.locals[y], name: y };
|
@@ -87,6 +90,8 @@ const compile = async (file, [ _funcs, _globals ]) => {
|
|
87
90
|
};
|
88
91
|
|
89
92
|
const precompile = async () => {
|
93
|
+
if (globalThis._porf_loadParser) await globalThis._porf_loadParser('@babel/parser');
|
94
|
+
|
90
95
|
const dir = join(__dirname, 'builtins');
|
91
96
|
|
92
97
|
let funcs = [], globals = [];
|
package/compiler/prefs.js
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
-
const onByDefault = [ 'bytestring', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls', 'optUnused' ];
|
1
|
+
const onByDefault = [ 'bytestring', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls', 'optUnused', 'data', 'rmUnusedTypes' ];
|
2
2
|
|
3
3
|
let cache = {};
|
4
4
|
const obj = new Proxy({}, {
|
5
5
|
get(_, p) {
|
6
|
-
|
7
|
-
if (cache[p]) return cache[p];
|
6
|
+
if (cache[p] != null) return cache[p];
|
8
7
|
|
9
8
|
const ret = (() => {
|
10
9
|
// fooBar -> foo-bar
|
package/compiler/prototype.js
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import { Opcodes, Blocktype, Valtype, ValtypeSize } from './wasmSpec.js';
|
2
2
|
import { number } from './embedding.js';
|
3
|
-
import { unsignedLEB128 } from './encoding.js';
|
4
3
|
import { UNDEFINED } from './builtins.js';
|
5
4
|
import { TYPES } from './types.js';
|
6
5
|
import Prefs from './prefs.js';
|
@@ -55,10 +54,10 @@ export const PrototypeFuncs = function() {
|
|
55
54
|
|
56
55
|
// read from memory
|
57
56
|
[ Opcodes.local_get, iTmp ],
|
58
|
-
[ Opcodes.load, 0,
|
57
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ],
|
59
58
|
|
60
59
|
[ Opcodes.local_get, iTmp ],
|
61
|
-
[ Opcodes.i32_load8_u, 0,
|
60
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
62
61
|
],
|
63
62
|
|
64
63
|
// todo: only for 1 argument
|
@@ -74,12 +73,12 @@ export const PrototypeFuncs = function() {
|
|
74
73
|
// store value
|
75
74
|
[ Opcodes.local_get, iTmp ],
|
76
75
|
...wNewMember,
|
77
|
-
[ Opcodes.store, 0,
|
76
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ],
|
78
77
|
|
79
78
|
// store type
|
80
79
|
[ Opcodes.local_get, iTmp ],
|
81
80
|
...wType,
|
82
|
-
[ Opcodes.i32_store8, 0,
|
81
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
|
83
82
|
|
84
83
|
// bump array length by 1 and return it
|
85
84
|
...length.setI32([
|
@@ -137,10 +136,10 @@ export const PrototypeFuncs = function() {
|
|
137
136
|
[ Opcodes.local_set, iTmp ],
|
138
137
|
|
139
138
|
[ Opcodes.local_get, iTmp ],
|
140
|
-
[ Opcodes.load, 0,
|
139
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ],
|
141
140
|
|
142
141
|
[ Opcodes.local_get, iTmp ],
|
143
|
-
[ Opcodes.i32_load8_u, 0,
|
142
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
144
143
|
])
|
145
144
|
],
|
146
145
|
|
@@ -168,10 +167,10 @@ export const PrototypeFuncs = function() {
|
|
168
167
|
// load first element
|
169
168
|
// todo/perf: unusedValue opt
|
170
169
|
...pointer,
|
171
|
-
[ Opcodes.load, 0,
|
170
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ],
|
172
171
|
|
173
172
|
...pointer,
|
174
|
-
[ Opcodes.i32_load8_u, 0,
|
173
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
|
175
174
|
|
176
175
|
// offset page by -1 ind
|
177
176
|
// ...number(pointer + ValtypeSize.i32, Valtype.i32), // dst = base array index + length size
|
@@ -250,12 +249,12 @@ export const PrototypeFuncs = function() {
|
|
250
249
|
// store value
|
251
250
|
[ Opcodes.local_get, iTmp2 ],
|
252
251
|
[ Opcodes.local_get, iTmp ],
|
253
|
-
[ Opcodes.store, 0,
|
252
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ],
|
254
253
|
|
255
254
|
// store type
|
256
255
|
[ Opcodes.local_get, iTmp2 ],
|
257
256
|
...wType,
|
258
|
-
[ Opcodes.i32_store8, 0,
|
257
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
|
259
258
|
|
260
259
|
// pointer - sizeof value
|
261
260
|
...length.getCachedI32(),
|
@@ -292,11 +291,8 @@ export const PrototypeFuncs = function() {
|
|
292
291
|
const [ newOut, newPointer ] = arrayShell(1, 'i16');
|
293
292
|
|
294
293
|
return [
|
295
|
-
// setup new/out array
|
294
|
+
// setup new/out array and use pointer for store
|
296
295
|
...newOut,
|
297
|
-
[ Opcodes.drop ],
|
298
|
-
|
299
|
-
...number(0, Valtype.i32), // base 0 for store later
|
300
296
|
|
301
297
|
...wIndex,
|
302
298
|
Opcodes.i32_to_u,
|
@@ -335,13 +331,14 @@ export const PrototypeFuncs = function() {
|
|
335
331
|
[ Opcodes.i32_add ],
|
336
332
|
|
337
333
|
// load current string ind {arg}
|
338
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
334
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
339
335
|
|
340
336
|
// store to new string ind 0
|
341
|
-
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1,
|
337
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
342
338
|
|
343
339
|
// return new string (pointer)
|
344
|
-
...
|
340
|
+
...newPointer,
|
341
|
+
Opcodes.i32_from_u
|
345
342
|
];
|
346
343
|
},
|
347
344
|
|
@@ -350,11 +347,8 @@ export const PrototypeFuncs = function() {
|
|
350
347
|
const [ newOut, newPointer ] = arrayShell(1, 'i16');
|
351
348
|
|
352
349
|
return [
|
353
|
-
// setup new/out array
|
350
|
+
// setup new/out array and use as pointer for store
|
354
351
|
...newOut,
|
355
|
-
[ Opcodes.drop ],
|
356
|
-
|
357
|
-
...number(0, Valtype.i32), // base 0 for store later
|
358
352
|
|
359
353
|
...wIndex,
|
360
354
|
Opcodes.i32_to,
|
@@ -366,13 +360,14 @@ export const PrototypeFuncs = function() {
|
|
366
360
|
[ Opcodes.i32_add ],
|
367
361
|
|
368
362
|
// load current string ind {arg}
|
369
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
363
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
370
364
|
|
371
365
|
// store to new string ind 0
|
372
|
-
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1,
|
366
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
373
367
|
|
374
368
|
// return new string (page)
|
375
|
-
...
|
369
|
+
...newPointer,
|
370
|
+
Opcodes.i32_from_u
|
376
371
|
];
|
377
372
|
},
|
378
373
|
|
@@ -411,7 +406,7 @@ export const PrototypeFuncs = function() {
|
|
411
406
|
[ Opcodes.i32_add ],
|
412
407
|
|
413
408
|
// load current string ind {arg}
|
414
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
409
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
415
410
|
Opcodes.i32_from_u
|
416
411
|
],
|
417
412
|
|
@@ -433,7 +428,7 @@ export const PrototypeFuncs = function() {
|
|
433
428
|
[ Opcodes.block, Blocktype.void ],
|
434
429
|
|
435
430
|
[ Opcodes.local_get, iTmp ],
|
436
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
431
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
437
432
|
[ Opcodes.local_set, iTmp2 ],
|
438
433
|
|
439
434
|
// if not surrogate, continue
|
@@ -455,7 +450,7 @@ export const PrototypeFuncs = function() {
|
|
455
450
|
|
456
451
|
// if not followed by trailing surrogate, return false
|
457
452
|
[ Opcodes.local_get, iTmp ],
|
458
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
453
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 + ValtypeSize.i16 ],
|
459
454
|
...number(0xFC00, Valtype.i32),
|
460
455
|
[ Opcodes.i32_and ],
|
461
456
|
...number(0xDC00, Valtype.i32),
|
@@ -507,11 +502,8 @@ export const PrototypeFuncs = function() {
|
|
507
502
|
const [ newOut, newPointer ] = arrayShell(1, 'i8');
|
508
503
|
|
509
504
|
return [
|
510
|
-
// setup new/out array
|
505
|
+
// setup new/out array and use pointer for store later
|
511
506
|
...newOut,
|
512
|
-
[ Opcodes.drop ],
|
513
|
-
|
514
|
-
...number(0, Valtype.i32), // base 0 for store later
|
515
507
|
|
516
508
|
...wIndex,
|
517
509
|
Opcodes.i32_to_u,
|
@@ -548,13 +540,14 @@ export const PrototypeFuncs = function() {
|
|
548
540
|
[ Opcodes.i32_add ],
|
549
541
|
|
550
542
|
// load current string ind {arg}
|
551
|
-
[ Opcodes.i32_load8_u, 0,
|
543
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
552
544
|
|
553
545
|
// store to new string ind 0
|
554
|
-
[ Opcodes.i32_store8, 0,
|
546
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
|
555
547
|
|
556
548
|
// return new string (pointer)
|
557
|
-
...
|
549
|
+
...newPointer,
|
550
|
+
Opcodes.i32_from_u
|
558
551
|
];
|
559
552
|
},
|
560
553
|
|
@@ -563,11 +556,8 @@ export const PrototypeFuncs = function() {
|
|
563
556
|
const [ newOut, newPointer ] = arrayShell(1, 'i8');
|
564
557
|
|
565
558
|
return [
|
566
|
-
// setup new/out array
|
559
|
+
// setup new/out array and use pointer for later
|
567
560
|
...newOut,
|
568
|
-
[ Opcodes.drop ],
|
569
|
-
|
570
|
-
...number(0, Valtype.i32), // base 0 for store later
|
571
561
|
|
572
562
|
...wIndex,
|
573
563
|
Opcodes.i32_to,
|
@@ -576,13 +566,14 @@ export const PrototypeFuncs = function() {
|
|
576
566
|
[ Opcodes.i32_add ],
|
577
567
|
|
578
568
|
// load current string ind {arg}
|
579
|
-
[ Opcodes.i32_load8_u, 0,
|
569
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
580
570
|
|
581
571
|
// store to new string ind 0
|
582
|
-
[ Opcodes.i32_store8, 0,
|
572
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
|
583
573
|
|
584
574
|
// return new string (page)
|
585
|
-
...
|
575
|
+
...newPointer,
|
576
|
+
Opcodes.i32_from_u
|
586
577
|
];
|
587
578
|
},
|
588
579
|
|
@@ -618,7 +609,7 @@ export const PrototypeFuncs = function() {
|
|
618
609
|
[ Opcodes.i32_add ],
|
619
610
|
|
620
611
|
// load current string ind {arg}
|
621
|
-
[ Opcodes.i32_load8_u, 0,
|
612
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
622
613
|
Opcodes.i32_from_u
|
623
614
|
],
|
624
615
|
|
package/compiler/wasmSpec.js
CHANGED
@@ -191,6 +191,8 @@ export const Opcodes = {
|
|
191
191
|
i32_trunc_sat_f64_s: [ 0xfc, 0x02 ],
|
192
192
|
i32_trunc_sat_f64_u: [ 0xfc, 0x03 ],
|
193
193
|
|
194
|
+
memory_init: [ 0xfc, 0x08 ],
|
195
|
+
data_drop: [ 0xfc, 0x09 ],
|
194
196
|
memory_copy: [ 0xfc, 0x0a ],
|
195
197
|
|
196
198
|
// simd insts are 0xFD simdop: varuint32
|
@@ -209,8 +211,6 @@ export const Opcodes = {
|
|
209
211
|
i32x4_add: [ 0xfd, 0xae, 0x01 ],
|
210
212
|
i32x4_sub: [ 0xfd, 0xb1, 0x01 ],
|
211
213
|
i32x4_mul: [ 0xfd, 0xb5, 0x01 ],
|
212
|
-
|
213
|
-
i32x4_dot_i16x8_s: [ 0xfd, 0xba, 0x01 ],
|
214
214
|
};
|
215
215
|
|
216
216
|
export const FuncType = 0x60;
|
package/compiler/wrap.js
CHANGED
@@ -104,13 +104,14 @@ const porfToJSValue = ({ memory, funcs, pages }, value, type) => {
|
|
104
104
|
|
105
105
|
case TYPES.symbol: {
|
106
106
|
const descStore = pages.get('bytestring: __Porffor_symbol_descStore/ptr').ind * pageSize;
|
107
|
+
if (!descStore) return Symbol();
|
108
|
+
|
107
109
|
const offset = descStore + 4 + ((value - 1) * 9);
|
108
110
|
|
109
111
|
const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
|
110
112
|
const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
|
111
113
|
|
112
114
|
const desc = porfToJSValue({ memory, funcs, pages }, v, t);
|
113
|
-
|
114
115
|
return Symbol(desc);
|
115
116
|
}
|
116
117
|
|
@@ -128,7 +129,7 @@ export default (source, flags = [ 'module' ], customImports = {}, print = str =>
|
|
128
129
|
|
129
130
|
if (source.includes?.('export ')) flags.push('module');
|
130
131
|
|
131
|
-
fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
132
|
+
// fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
132
133
|
|
133
134
|
times.push(performance.now() - t1);
|
134
135
|
if (Prefs.profileCompiler) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
|
package/package.json
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
{
|
2
2
|
"name": "porffor",
|
3
3
|
"description": "a basic experimental wip aot optimizing js -> wasm engine/compiler/runtime in js",
|
4
|
-
"version": "0.16.0-
|
4
|
+
"version": "0.16.0-7143cc59c",
|
5
5
|
"author": "CanadaHonk",
|
6
6
|
"license": "MIT",
|
7
|
-
"scripts": {
|
8
|
-
"precompile": "node ./compiler/precompile.js"
|
9
|
-
},
|
7
|
+
"scripts": {},
|
10
8
|
"dependencies": {
|
11
9
|
"acorn": "^8.11.3",
|
12
10
|
"node-repl-polyfill": "^0.1.1"
|
@@ -28,5 +26,5 @@
|
|
28
26
|
"bugs": {
|
29
27
|
"url": "https://github.com/CanadaHonk/porffor/issues"
|
30
28
|
},
|
31
|
-
"homepage": "https://porffor.
|
29
|
+
"homepage": "https://porffor.dev"
|
32
30
|
}
|
package/runner/index.js
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
-
|
3
|
-
import compile from '../compiler/wrap.js';
|
4
2
|
import fs from 'node:fs';
|
5
3
|
|
4
|
+
// deno compat
|
5
|
+
if (typeof process === 'undefined' && typeof Deno !== 'undefined') {
|
6
|
+
globalThis.process = await import('node:process');
|
7
|
+
}
|
8
|
+
|
6
9
|
const start = performance.now();
|
7
10
|
|
8
11
|
if (process.argv.includes('--compile-hints')) {
|
@@ -59,10 +62,15 @@ if (process.argv.includes('--help')) {
|
|
59
62
|
}
|
60
63
|
|
61
64
|
let file = process.argv.slice(2).find(x => x[0] !== '-');
|
62
|
-
if (['run', 'wasm', 'native', 'c', 'profile', 'debug', 'debug-wasm'].includes(file)) {
|
65
|
+
if (['precompile', 'run', 'wasm', 'native', 'c', 'profile', 'debug', 'debug-wasm'].includes(file)) {
|
63
66
|
// remove this arg
|
64
67
|
process.argv.splice(process.argv.indexOf(file), 1);
|
65
68
|
|
69
|
+
if (file === 'precompile') {
|
70
|
+
await import('../compiler/precompile.js');
|
71
|
+
await new Promise(() => {}); // do nothing for the rest of this file
|
72
|
+
}
|
73
|
+
|
66
74
|
if (file === 'profile') {
|
67
75
|
await import('./profile.js');
|
68
76
|
await new Promise(() => {}); // do nothing for the rest of this file
|
@@ -105,6 +113,8 @@ if (!file) {
|
|
105
113
|
|
106
114
|
const source = fs.readFileSync(file, 'utf8');
|
107
115
|
|
116
|
+
const compile = (await import('../compiler/wrap.js')).default;
|
117
|
+
|
108
118
|
let cache = '';
|
109
119
|
const print = str => {
|
110
120
|
/* cache += str;
|