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 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();
@@ -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)) return number(this.ptr(pages.get(reason).ind), Valtype.i32);
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
- return number(this.ptr(ind), Valtype.i32);
58
+ const ptr = this.lastPtr = this.ptr(ind);
59
+ return number(ptr, Valtype.i32);
56
60
  }
57
61
  }
58
62
 
@@ -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
- // fix call indexes for non-imports
98
- // also fix call_indirect types
99
- const delta = importedFuncs.length - importFuncs.length;
100
- for (const f of funcs) {
101
- f.originalIndex = f.index;
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
- for (const inst of f.wasm) {
105
- if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] >= importedFuncs.length) {
106
- inst[1] -= delta;
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
- const params = [];
113
- for (let i = 0; i < inst[1]; i++) {
114
- params.push(valtypeBinary, Valtype.i32);
115
- }
109
+ if (inst[0] === Opcodes.call_indirect) {
110
+ if (!funcs.table) funcs.table = true;
116
111
 
117
- if (inst.at(-1) === 'constr') {
118
- inst.pop();
119
- params.unshift(Valtype.i32);
120
- }
112
+ const params = [];
113
+ for (let i = 0; i < inst[1]; i++) {
114
+ params.push(valtypeBinary, Valtype.i32);
115
+ }
121
116
 
122
- let returns = [ valtypeBinary, Valtype.i32 ];
123
- if (inst.at(-1) === 'no_type_return') {
124
- inst.pop();
125
- returns = [ valtypeBinary ];
126
- }
117
+ if (inst.at(-1) === 'constr') {
118
+ inst.pop();
119
+ params.unshift(Valtype.i32);
120
+ }
127
121
 
128
- inst[1] = getType(params, returns);
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
- globalThis.importFuncs = importFuncs;
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') && !data.addedFuncArgcLut) {
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: pages.get('func lut').ind * pageSize,
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 a navigator class but bleh
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('_').replaceAll('_', '.');
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
  }
@@ -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 = read_signedLEB128(pointer[0].slice(1));
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 && firstAssign && useRawElements &&
4389
+ Prefs.data && useRawElements &&
4390
4390
  name !== '#member_prop' && name !== '#member_prop_assign' &&
4391
4391
  (!globalThis.precompile || !global)
4392
4392
  ) {
4393
- makeData(scope, elements, rawPtr, itemType, initEmpty);
4393
+ if (Prefs.activeData && firstAssign) {
4394
+ makeData(scope, elements, rawPtr, itemType, initEmpty);
4394
4395
 
4395
- // local value as pointer
4396
- return [ number(rawPtr, intOut ? Valtype.i32 : valtypeBinary), pointer ];
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
- // enable pgo by default for c/native
45
- if (target !== 'wasm') Prefs.pgo = Prefs.pgo === false ? false : true;
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
 
@@ -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-treeshake-wasm-imports', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--fast-length', '--parse-types', '--opt-types'];
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 {[func.name]() {}}[func.name];
124
+ return {[name]() {}}[name];
121
125
  }
122
126
 
123
127
  case TYPES.string: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
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.24.1+355a35a99",
4
+ "version": "0.24.2+c071f9a2f",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {},
package/runner/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs';
3
- globalThis.version = '0.24.1+355a35a99';
3
+ globalThis.version = '0.24.2+c071f9a2f';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {