porffor 0.24.1 → 0.24.2
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/2c.js +6 -0
- package/compiler/allocators.js +6 -2
- package/compiler/assemble.js +38 -33
- package/compiler/builtins_objects.js +30 -5
- package/compiler/codegen.js +25 -5
- package/compiler/index.js +10 -5
- package/compiler/precompile.js +1 -1
- package/compiler/prefs.js +1 -1
- package/compiler/wrap.js +5 -1
- package/package.json +1 -1
- package/runner/index.js +1 -1
package/compiler/2c.js
CHANGED
@@ -675,6 +675,12 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
675
675
|
|
676
676
|
break;
|
677
677
|
|
678
|
+
case Opcodes.call_indirect:
|
679
|
+
// stub, todo
|
680
|
+
vals.pop();
|
681
|
+
vals.push('0', '0');
|
682
|
+
break;
|
683
|
+
|
678
684
|
case Opcodes.drop:
|
679
685
|
// line(vals.pop());
|
680
686
|
vals.pop();
|
package/compiler/allocators.js
CHANGED
@@ -39,7 +39,10 @@ export class StaticAllocator {
|
|
39
39
|
if (globalThis.precompile && scopeName === 'main') scopeName = globalThis.precompile;
|
40
40
|
const reason = `${this.allocType(itemType)}: ${Prefs.scopedPageNames ? (scopeName + '/') : ''}${name}`;
|
41
41
|
|
42
|
-
if (pages.has(reason))
|
42
|
+
if (pages.has(reason)) {
|
43
|
+
const ptr = this.lastPtr = this.ptr(pages.get(reason).ind);
|
44
|
+
return number(ptr, Valtype.i32);
|
45
|
+
}
|
43
46
|
|
44
47
|
if (reason.startsWith('array:')) pages.hasArray = true;
|
45
48
|
if (reason.startsWith('string:')) pages.hasString = true;
|
@@ -52,7 +55,8 @@ export class StaticAllocator {
|
|
52
55
|
scope.pages ??= new Map();
|
53
56
|
scope.pages.set(reason, { ind, type: itemType });
|
54
57
|
|
55
|
-
|
58
|
+
const ptr = this.lastPtr = this.ptr(ind);
|
59
|
+
return number(ptr, Valtype.i32);
|
56
60
|
}
|
57
61
|
}
|
58
62
|
|
package/compiler/assemble.js
CHANGED
@@ -72,8 +72,7 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
72
72
|
return typeCache[hash] = idx;
|
73
73
|
};
|
74
74
|
|
75
|
-
let importFuncs = [];
|
76
|
-
|
75
|
+
let importFuncs = [], importDelta = 0;
|
77
76
|
if (optLevel < 1 || !Prefs.treeshakeWasmImports || noTreeshake) {
|
78
77
|
importFuncs = importedFuncs;
|
79
78
|
} else {
|
@@ -92,45 +91,45 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
92
91
|
}
|
93
92
|
}
|
94
93
|
|
95
|
-
importFuncs = [...imports.values()];
|
94
|
+
importFuncs = globalThis.importFuncs = [...imports.values()];
|
95
|
+
importDelta = importedFuncs.length - importFuncs.length;
|
96
|
+
}
|
96
97
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
f.index -= delta;
|
98
|
+
// fix call indexes for non-imports
|
99
|
+
// also fix call_indirect types
|
100
|
+
for (const f of funcs) {
|
101
|
+
f.originalIndex = f.index;
|
102
|
+
f.index -= importDelta;
|
103
103
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
if (inst[0] === Opcodes.call_indirect) {
|
110
|
-
if (!funcs.table) funcs.table = true;
|
104
|
+
for (const inst of f.wasm) {
|
105
|
+
if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] >= importedFuncs.length) {
|
106
|
+
inst[1] -= importDelta;
|
107
|
+
}
|
111
108
|
|
112
|
-
|
113
|
-
|
114
|
-
params.push(valtypeBinary, Valtype.i32);
|
115
|
-
}
|
109
|
+
if (inst[0] === Opcodes.call_indirect) {
|
110
|
+
if (!funcs.table) funcs.table = true;
|
116
111
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
112
|
+
const params = [];
|
113
|
+
for (let i = 0; i < inst[1]; i++) {
|
114
|
+
params.push(valtypeBinary, Valtype.i32);
|
115
|
+
}
|
121
116
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
}
|
117
|
+
if (inst.at(-1) === 'constr') {
|
118
|
+
inst.pop();
|
119
|
+
params.unshift(Valtype.i32);
|
120
|
+
}
|
127
121
|
|
128
|
-
|
122
|
+
let returns = [ valtypeBinary, Valtype.i32 ];
|
123
|
+
if (inst.at(-1) === 'no_type_return') {
|
124
|
+
inst.pop();
|
125
|
+
returns = [ valtypeBinary ];
|
129
126
|
}
|
127
|
+
|
128
|
+
inst[1] = getType(params, returns);
|
130
129
|
}
|
131
130
|
}
|
132
131
|
}
|
133
|
-
|
132
|
+
|
134
133
|
|
135
134
|
if (Prefs.optLog) log('assemble', `treeshake: using ${importFuncs.length}/${importedFuncs.length} imports`);
|
136
135
|
|
@@ -160,7 +159,13 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
160
159
|
] ])
|
161
160
|
);
|
162
161
|
|
163
|
-
if (pages.has('func lut')
|
162
|
+
if (pages.has('func lut')) {
|
163
|
+
const offset = pages.get('func lut').ind * pageSize;
|
164
|
+
if (data.addedFuncArgcLut) {
|
165
|
+
// remove existing data
|
166
|
+
data = data.filter(x => x.offset !== offset);
|
167
|
+
}
|
168
|
+
|
164
169
|
// generate func lut data
|
165
170
|
const bytes = [];
|
166
171
|
for (let i = 0; i < funcs.length; i++) {
|
@@ -192,7 +197,7 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
192
197
|
}
|
193
198
|
|
194
199
|
data.push({
|
195
|
-
offset
|
200
|
+
offset,
|
196
201
|
bytes
|
197
202
|
});
|
198
203
|
data.addedFuncArgcLut = true;
|
@@ -136,6 +136,17 @@ export default function({ builtinFuncs }, Prefs) {
|
|
136
136
|
|
137
137
|
object('Reflect', autoFuncs('Reflect'));
|
138
138
|
|
139
|
+
// automatically generate objects for prototypes
|
140
|
+
for (const x of builtinFuncKeys.reduce((acc, x) => {
|
141
|
+
const ind = x.indexOf('_prototype_');
|
142
|
+
if (ind === -1) return acc;
|
143
|
+
|
144
|
+
acc.add(x.slice(0, ind + 10));
|
145
|
+
return acc;
|
146
|
+
}, new Set())) {
|
147
|
+
object(x, autoFuncs(x));
|
148
|
+
}
|
149
|
+
|
139
150
|
|
140
151
|
// todo: support when existing func
|
141
152
|
// object('Number', {
|
@@ -153,7 +164,7 @@ export default function({ builtinFuncs }, Prefs) {
|
|
153
164
|
// });
|
154
165
|
|
155
166
|
|
156
|
-
// technically not spec compliant as it should be
|
167
|
+
// these technically not spec compliant as it should be classes or non-enumerable but eh
|
157
168
|
object('navigator', {
|
158
169
|
...props({
|
159
170
|
writable: false,
|
@@ -164,20 +175,34 @@ export default function({ builtinFuncs }, Prefs) {
|
|
164
175
|
})
|
165
176
|
});
|
166
177
|
|
178
|
+
for (const x of [
|
179
|
+
'console',
|
180
|
+
'crypto',
|
181
|
+
'performance',
|
182
|
+
]) {
|
183
|
+
object(x, {
|
184
|
+
...props({
|
185
|
+
writable: true,
|
186
|
+
enumerable: true,
|
187
|
+
configurable: true
|
188
|
+
}, autoFuncKeys(x).slice(0, 12))
|
189
|
+
});
|
190
|
+
}
|
191
|
+
|
167
192
|
if (Prefs.logMissingObjects) for (const x of Object.keys(builtinFuncs).concat(Object.keys(this))) {
|
168
193
|
if (!x.startsWith('__')) continue;
|
169
194
|
|
170
|
-
const name = x.split('_').slice(2, -1).join('_')
|
195
|
+
const name = x.split('_').slice(2, -1).join('_');
|
171
196
|
|
172
197
|
let t = globalThis;
|
173
|
-
for (const x of name.split('
|
198
|
+
for (const x of name.split('_')) {
|
174
199
|
t = t[x];
|
175
200
|
if (!t) break;
|
176
201
|
}
|
177
202
|
if (!t) continue;
|
178
203
|
|
179
|
-
if (!done.has(name)) {
|
180
|
-
console.log(name, !!builtinFuncs[name]);
|
204
|
+
if (!done.has(name) && !done.has('__' + name)) {
|
205
|
+
console.log(name.replaceAll('_', '.'), !!builtinFuncs[name]);
|
181
206
|
done.add(name);
|
182
207
|
}
|
183
208
|
}
|
package/compiler/codegen.js
CHANGED
@@ -4378,7 +4378,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
4378
4378
|
return [ out, pointer ];
|
4379
4379
|
}
|
4380
4380
|
} else {
|
4381
|
-
const rawPtr =
|
4381
|
+
const rawPtr = allocator.lastPtr;
|
4382
4382
|
|
4383
4383
|
scope.arrays ??= new Map();
|
4384
4384
|
const firstAssign = !scope.arrays.has(uniqueName);
|
@@ -4386,14 +4386,34 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
4386
4386
|
|
4387
4387
|
const local = global ? globals[name] : scope.locals?.[name];
|
4388
4388
|
if (
|
4389
|
-
Prefs.data &&
|
4389
|
+
Prefs.data && useRawElements &&
|
4390
4390
|
name !== '#member_prop' && name !== '#member_prop_assign' &&
|
4391
4391
|
(!globalThis.precompile || !global)
|
4392
4392
|
) {
|
4393
|
-
|
4393
|
+
if (Prefs.activeData && firstAssign) {
|
4394
|
+
makeData(scope, elements, rawPtr, itemType, initEmpty);
|
4394
4395
|
|
4395
|
-
|
4396
|
-
|
4396
|
+
// local value as pointer
|
4397
|
+
return [ number(rawPtr, intOut ? Valtype.i32 : valtypeBinary), pointer ];
|
4398
|
+
}
|
4399
|
+
|
4400
|
+
if (Prefs.passiveData) {
|
4401
|
+
const data = makeData(scope, elements, null, itemType, initEmpty);
|
4402
|
+
if (data) {
|
4403
|
+
// init data
|
4404
|
+
out.push(
|
4405
|
+
...pointer,
|
4406
|
+
...number(0, Valtype.i32),
|
4407
|
+
...number(data.size, Valtype.i32),
|
4408
|
+
[ ...Opcodes.memory_init, ...unsignedLEB128(data.idx), 0 ]
|
4409
|
+
);
|
4410
|
+
}
|
4411
|
+
|
4412
|
+
// return pointer in out
|
4413
|
+
out.push(...number(rawPtr, intOut ? Valtype.i32 : valtypeBinary));
|
4414
|
+
|
4415
|
+
return [ out, pointer ];
|
4416
|
+
}
|
4397
4417
|
}
|
4398
4418
|
|
4399
4419
|
if (local != null) {
|
package/compiler/index.js
CHANGED
@@ -41,8 +41,12 @@ export default (code, flags) => {
|
|
41
41
|
const pageSizeOpt = process.argv.find(x => x.startsWith('--page-size='));
|
42
42
|
if (pageSizeOpt) pageSize = parseInt(pageSizeOpt.split('=')[1]) * 1024;
|
43
43
|
|
44
|
-
//
|
45
|
-
if (target !== 'wasm')
|
44
|
+
// change some prefs by default for c/native
|
45
|
+
if (target !== 'wasm') {
|
46
|
+
Prefs.pgo = Prefs.pgo === false ? false : true;
|
47
|
+
Prefs.passiveData = false;
|
48
|
+
}
|
49
|
+
|
46
50
|
if (Prefs.pgo) pgo.setup();
|
47
51
|
|
48
52
|
if (Prefs.profileCompiler) console.log(`0. began compilation (host runtime startup) in ${performance.now().toFixed(2)}ms`);
|
@@ -104,8 +108,11 @@ export default (code, flags) => {
|
|
104
108
|
|
105
109
|
if (Prefs.profileCompiler) console.log(`3. optimized in ${(performance.now() - t2).toFixed(2)}ms`);
|
106
110
|
|
111
|
+
const out = { funcs, globals, tags, exceptions, pages, data };
|
112
|
+
if (globalThis.precompile) return out;
|
113
|
+
|
107
114
|
const t3 = performance.now();
|
108
|
-
const wasm = assemble(funcs, globals, tags, pages, data, flags);
|
115
|
+
const wasm = out.wasm = assemble(funcs, globals, tags, pages, data, flags);
|
109
116
|
if (Prefs.profileCompiler) console.log(`4. assembled in ${(performance.now() - t3).toFixed(2)}ms`);
|
110
117
|
|
111
118
|
if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
|
@@ -117,8 +124,6 @@ export default (code, flags) => {
|
|
117
124
|
console.log([...pages.keys()].map(x => `\x1B[36m - ${x}\x1B[0m`).join('\n') + '\n');
|
118
125
|
}
|
119
126
|
|
120
|
-
const out = { wasm, funcs, globals, tags, exceptions, pages, data };
|
121
|
-
|
122
127
|
if (target === 'wasm' && outFile) {
|
123
128
|
fs.writeFileSync(outFile, Buffer.from(wasm));
|
124
129
|
|
package/compiler/precompile.js
CHANGED
@@ -24,7 +24,7 @@ const compile = async (file, _funcs) => {
|
|
24
24
|
first = source.slice(0, source.indexOf('\n'));
|
25
25
|
}
|
26
26
|
|
27
|
-
let args = ['--bytestring', '--todo-time=compile', '--truthy=no_nan_negative', '--no-
|
27
|
+
let args = ['--bytestring', '--todo-time=compile', '--truthy=no_nan_negative', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--fast-length', '--parse-types', '--opt-types', '--no-passive-data', '--active-data'];
|
28
28
|
if (first.startsWith('// @porf')) {
|
29
29
|
args = first.slice('// @porf '.length).split(' ').concat(args);
|
30
30
|
}
|
package/compiler/prefs.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
const onByDefault = [ 'bytestring', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls', 'optUnused', 'data', 'rmUnusedTypes' ];
|
1
|
+
const onByDefault = [ 'bytestring', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls', 'optUnused', 'data', 'passiveData', 'rmUnusedTypes' ];
|
2
2
|
|
3
3
|
let cache = {};
|
4
4
|
const obj = new Proxy({}, {
|
package/compiler/wrap.js
CHANGED
@@ -116,8 +116,12 @@ ${flags & 0b0001 ? ` get func idx: ${get}
|
|
116
116
|
|
117
117
|
if (!func) return function () {};
|
118
118
|
|
119
|
+
let name = func.name;
|
120
|
+
// eg: __String_prototype_toLowerCase -> toLowerCase
|
121
|
+
if (name.startsWith('__')) name = name.split('_').pop();
|
122
|
+
|
119
123
|
// make fake empty func for repl/etc
|
120
|
-
return {[
|
124
|
+
return {[name]() {}}[name];
|
121
125
|
}
|
122
126
|
|
123
127
|
case TYPES.string: {
|
package/package.json
CHANGED