porffor 0.60.8 → 0.60.9

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.
@@ -1,5 +1,5 @@
1
1
  import { Blocktype, Opcodes, Valtype, ValtypeSize } from './wasmSpec.js';
2
- import { number, ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector, read_signedLEB128 } from './encoding.js';
2
+ import { number, ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector } from './encoding.js';
3
3
  import { operatorOpcode } from './expression.js';
4
4
  import { BuiltinFuncs, BuiltinVars, importedFuncs, NULL, UNDEFINED } from './builtins.js';
5
5
  import { TYPES, TYPE_FLAGS, TYPE_NAMES } from './types.js';
@@ -41,24 +41,30 @@ const allocBytes = (scope, reason, bytes) => {
41
41
  return allocs.get(reason);
42
42
  }
43
43
 
44
- let bin = bins.find(x => (pageSize - x.used) >= bytes);
45
- if (!bin) {
46
- // new bin
47
- const page = pages.size;
48
- bin = {
49
- used: 0,
50
- page
51
- };
44
+ let startingPtr = 0;
45
+ while (bytes > 0) {
46
+ const alloc = Math.min(bytes, pageSize);
47
+ bytes -= alloc;
52
48
 
53
- const id = bins.push(bin);
54
- pages.set(`#bin: ${id}`, page);
55
- }
49
+ let bin = bins.find(x => (pageSize - x.used) >= alloc);
50
+ if (!bin) {
51
+ // new bin
52
+ const page = pages.size;
53
+ bin = {
54
+ used: 0,
55
+ page
56
+ };
56
57
 
57
- const ptr = pagePtr(bin.page) + bin.used;
58
- bin.used += bytes;
58
+ const id = bins.push(bin);
59
+ pages.set(`#bin: ${id}`, page);
60
+ }
61
+
62
+ if (!startingPtr) startingPtr = pagePtr(bin.page) + bin.used;
63
+ bin.used += alloc;
64
+ }
59
65
 
60
- allocs.set(reason, ptr);
61
- return ptr;
66
+ allocs.set(reason, startingPtr);
67
+ return startingPtr;
62
68
  };
63
69
 
64
70
  export const allocStr = (scope, str, bytestring) => {
@@ -2840,7 +2846,7 @@ const knownType = (scope, type) => {
2840
2846
  if (typeof type === 'number') return type;
2841
2847
 
2842
2848
  if (type.length === 1 && type[0][0] === Opcodes.i32_const) {
2843
- return read_signedLEB128(type[0].slice(1));
2849
+ return type[0][1];
2844
2850
  }
2845
2851
 
2846
2852
  if (typedInput && type.length === 1 && type[0][0] === Opcodes.local_get) {
@@ -4319,7 +4325,7 @@ const generateUnary = (scope, decl) => {
4319
4325
  return [
4320
4326
  ...toNumeric(),
4321
4327
  Opcodes.i32_to,
4322
- [ Opcodes.i32_const, ...signedLEB128(-1) ],
4328
+ [ Opcodes.i32_const, -1 ],
4323
4329
  [ Opcodes.i32_xor ],
4324
4330
  Opcodes.i32_from
4325
4331
  ];
@@ -5118,14 +5124,14 @@ const generateForIn = (scope, decl) => {
5118
5124
  [ Opcodes.local_set, tmp ],
5119
5125
 
5120
5126
  // symbol is MSB 2 is set
5121
- [ Opcodes.i32_const, ...unsignedLEB128(TYPES.string) ],
5122
- [ Opcodes.i32_const, ...unsignedLEB128(TYPES.symbol) ],
5127
+ [ Opcodes.i32_const, TYPES.string ],
5128
+ [ Opcodes.i32_const, TYPES.symbol ],
5123
5129
  [ Opcodes.local_get, tmp ],
5124
5130
  number(0x40000000, Valtype.i32),
5125
5131
  [ Opcodes.i32_and ],
5126
5132
  [ Opcodes.select ],
5127
5133
  [ Opcodes.else ], // bytestring
5128
- [ Opcodes.i32_const, ...unsignedLEB128(TYPES.bytestring) ],
5134
+ [ Opcodes.i32_const, TYPES.bytestring ],
5129
5135
  [ Opcodes.end ]
5130
5136
  ]),
5131
5137
 
@@ -6615,6 +6621,7 @@ const generateTaggedTemplate = (scope, decl, global = false, name = undefined, v
6615
6621
 
6616
6622
  const encodeFunc = ({
6617
6623
  [Opcodes.f64_const]: x => x,
6624
+ [Opcodes.i32_const]: x => x,
6618
6625
  [Opcodes.if]: unsignedLEB128,
6619
6626
  [Opcodes.loop]: unsignedLEB128
6620
6627
  })[inst[0]] ?? signedLEB128;
@@ -1,5 +1,5 @@
1
1
  // cyclone: wasm partial constant evaluator (it is fast and dangerous hence "cyclone")
2
- import { number, read_signedLEB128 } from './encoding.js';
2
+ import { number } from './encoding.js';
3
3
  import { Opcodes, Valtype } from './wasmSpec.js';
4
4
  import './prefs.js';
5
5
 
@@ -123,7 +123,7 @@ export default ({ name, wasm, locals: _locals, params }) => {
123
123
  }
124
124
 
125
125
  case Opcodes.i32_const: {
126
- const n = read_signedLEB128(op.slice(1));
126
+ const n = op[1];
127
127
  push(n);
128
128
  break;
129
129
  }
@@ -1,5 +1,5 @@
1
1
  import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
2
- import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from './encoding.js';
2
+ import { read_unsignedLEB128 } from './encoding.js';
3
3
  import { importedFuncs } from './builtins.js';
4
4
 
5
5
  const inv = (obj, keyMap = x => x) => Object.keys(obj).reduce((acc, x) => { acc[keyMap(obj[x])] = x; return acc; }, {});
@@ -74,7 +74,7 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
74
74
  if (inst[0] === Opcodes.f64_const) {
75
75
  out += ` ${inst[1]}`;
76
76
  } else if (inst[0] === Opcodes.i32_const || inst[0] === Opcodes.i64_const) {
77
- out += ` ${read_signedLEB128(inst.slice(1))}`;
77
+ out += ` ${inst[1]}`;
78
78
  } else if (inst[0] === Opcodes.i32_load || inst[0] === Opcodes.i64_load || inst[0] === Opcodes.f64_load || inst[0] === Opcodes.i32_store || inst[0] === Opcodes.i64_store || inst[0] === Opcodes.f64_store || inst[0] === Opcodes.i32_store16 || inst[0] === Opcodes.i32_load16_u) {
79
79
  out += ` ${inst[1]} ${read_unsignedLEB128(inst.slice(2))}`;
80
80
  } else for (const operand of inst.slice(1)) {
@@ -3,10 +3,10 @@ import { Opcodes, Valtype } from './wasmSpec.js';
3
3
  export const number = (n, valtype = valtypeBinary) => {
4
4
  if (valtype === Valtype.f64) return [ Opcodes.f64_const, n ];
5
5
 
6
- const out = [ valtype === Valtype.i32 ? Opcodes.i32_const : Opcodes.i64_const ];
7
- signedLEB128_into(n, out);
8
-
9
- return out;
6
+ return [
7
+ valtype === Valtype.i32 ? Opcodes.i32_const : Opcodes.i64_const,
8
+ n
9
+ ];
10
10
  };
11
11
 
12
12
  export const codifyString = str => {
@@ -23,6 +23,9 @@ export const encodeVector = data => unsignedLEB128(data.length).concat(data.flat
23
23
 
24
24
  // todo: this only works with integers within 32 bit range
25
25
  export const signedLEB128 = n => {
26
+ if (n === Infinity) return signedLEB128(2147483647);
27
+ if (n === -Infinity) return signedLEB128(-2147483648);
28
+
26
29
  n |= 0;
27
30
 
28
31
  // just input for small numbers (for perf as common)
@@ -49,6 +52,9 @@ export const signedLEB128 = n => {
49
52
  };
50
53
 
51
54
  export const unsignedLEB128 = n => {
55
+ if (n === Infinity) return unsignedLEB128(4294967295);
56
+ if (n === -Infinity) return unsignedLEB128(0);
57
+
52
58
  n |= 0;
53
59
 
54
60
  // just input for small numbers (for perf as common)
@@ -69,6 +75,9 @@ export const unsignedLEB128 = n => {
69
75
  };
70
76
 
71
77
  export const unsignedLEB128_length = n => {
78
+ if (n === Infinity) return unsignedLEB128_length(4294967295);
79
+ if (n === -Infinity) return unsignedLEB128_length(0);
80
+
72
81
  if (n < 0) n = n >>> 0;
73
82
  if (n <= 127) return 1;
74
83
  if (n <= 16383) return 2;
@@ -85,6 +94,9 @@ export const unsignedLEB128_length = n => {
85
94
  };
86
95
 
87
96
  export const signedLEB128_length = n => {
97
+ if (n === Infinity) return signedLEB128_length(2147483647);
98
+ if (n === -Infinity) return signedLEB128_length(-2147483648);
99
+
88
100
  if (n >= -64 && n <= 63) return 1;
89
101
  if (n >= -8192 && n <= 8191) return 2;
90
102
  if (n >= -1048576 && n <= 1048575) return 3;
@@ -201,6 +213,9 @@ export const read_ieee754_binary64 = buffer => new Float64Array(new Uint8Array(b
201
213
 
202
214
  // into funcs append to a given existing buffer instead of creating our own for perf
203
215
  export const signedLEB128_into = (n, buffer) => {
216
+ if (n === Infinity) return signedLEB128_into(2147483647, buffer);
217
+ if (n === -Infinity) return signedLEB128_into(-2147483648, buffer);
218
+
204
219
  n |= 0;
205
220
 
206
221
  // just input for small numbers (for perf as common)
@@ -224,6 +239,9 @@ export const signedLEB128_into = (n, buffer) => {
224
239
  };
225
240
 
226
241
  export const unsignedLEB128_into = (n, buffer) => {
242
+ if (n === Infinity) return unsignedLEB128_into(4294967295, buffer);
243
+ if (n === -Infinity) return unsignedLEB128_into(0, buffer);
244
+
227
245
  n |= 0;
228
246
 
229
247
  // just input for small numbers (for perf as common)
@@ -46,31 +46,6 @@ export const operatorOpcode = {
46
46
  ]
47
47
  },
48
48
 
49
- i64: {
50
- '+': Opcodes.i64_add,
51
- '-': Opcodes.i64_sub,
52
- '*': Opcodes.i64_mul,
53
- '/': Opcodes.i64_div_s,
54
- '%': Opcodes.i64_rem_s,
55
-
56
- '&': Opcodes.i64_and,
57
- '|': Opcodes.i64_or,
58
- '^': Opcodes.i64_xor,
59
- '<<': Opcodes.i64_shl,
60
- '>>': Opcodes.i64_shr_s,
61
- '>>>': Opcodes.i64_shr_u,
62
-
63
- '==': Opcodes.i64_eq,
64
- '===': Opcodes.i64_eq,
65
- '!=': Opcodes.i64_ne,
66
- '!==': Opcodes.i64_ne,
67
-
68
- '>': Opcodes.i64_gt_s,
69
- '>=': Opcodes.i64_ge_s,
70
- '<': Opcodes.i64_lt_s,
71
- '<=': Opcodes.i64_le_s
72
- },
73
-
74
49
  f64: {
75
50
  '+': Opcodes.f64_add,
76
51
  '-': Opcodes.f64_sub,
package/compiler/opt.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Opcodes, Valtype } from './wasmSpec.js';
2
- import { number, read_signedLEB128 } from './encoding.js';
2
+ import { number } from './encoding.js';
3
3
  import { log } from './log.js';
4
4
  import './prefs.js';
5
5
 
@@ -177,7 +177,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
177
177
  // -->
178
178
  // i32.const 0
179
179
 
180
- wasm[i - 1] = number(valtype === 'f64' ? lastInst[1] : read_signedLEB128(lastInst.slice(1)), Valtype.i32); // f64.const -> i32.const
180
+ wasm[i - 1] = number(lastInst[1], Valtype.i32); // f64.const -> i32.const
181
181
 
182
182
  wasm.splice(i, 1); // remove this inst
183
183
  i--;
@@ -192,7 +192,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
192
192
  // -->
193
193
  // f64.const 0
194
194
 
195
- wasm[i - 1] = number(read_signedLEB128(lastInst.slice(1))); // i32.const -> f64.const
195
+ wasm[i - 1] = number(lastInst[1], Valtype.f64); // i32.const -> f64.const
196
196
 
197
197
  wasm.splice(i, 1); // remove this inst
198
198
  i--;
@@ -215,18 +215,18 @@ export default (funcs, globals, pages, tags, exceptions) => {
215
215
  continue;
216
216
  }
217
217
 
218
- if (false && i === wasm.length - 1 && inst[0] === Opcodes.return) {
219
- // replace final return, end -> end (wasm has implicit return)
220
- // return
221
- // end
222
- // -->
223
- // end
224
-
225
- wasm.splice(i, 1); // remove this inst (return)
226
- i--;
227
- // if (Prefs.optLog) log('opt', `removed redundant return at end`);
228
- continue;
229
- }
218
+ // if (i === wasm.length - 1 && inst[0] === Opcodes.return) {
219
+ // // replace final return, end -> end (wasm has implicit return)
220
+ // // return
221
+ // // end
222
+ // // -->
223
+ // // end
224
+
225
+ // wasm.splice(i, 1); // remove this inst (return)
226
+ // i--;
227
+ // // if (Prefs.optLog) log('opt', `removed redundant return at end`);
228
+ // continue;
229
+ // }
230
230
 
231
231
  // remove unneeded before get with update exprs (n++, etc) when value is unused
232
232
  if (i < wasm.length - 4 && lastInst[1] === inst[1] && lastInst[0] === Opcodes.local_get && inst[0] === Opcodes.local_get && wasm[i + 1][0] === Opcodes.const && [Opcodes.add, Opcodes.sub].includes(wasm[i + 2][0]) && wasm[i + 3][0] === Opcodes.local_set && wasm[i + 3][1] === inst[1] && (wasm[i + 4][0] === Opcodes.drop || wasm[i + 4][0] === Opcodes.br)) {
@@ -176,7 +176,7 @@ const compile = async (file, _funcs) => {
176
176
  x.usesTag = true;
177
177
  let id;
178
178
  if (y[0] === Opcodes.i32_const && n[1] === 0) {
179
- id = read_signedLEB128(y.slice(1));
179
+ id = y[1];
180
180
  wasm[i] = [ 'throw', exceptions[id].constructor, exceptions[id].message ];
181
181
 
182
182
  // remove throw inst
@@ -244,7 +244,7 @@ ${funcs.map(x => {
244
244
  if (Number.isNaN(v) || v === Infinity || v === -Infinity) return v.toString();
245
245
  return v;
246
246
  })
247
- .replace(/\["alloc","(.*?)",(.*?)\]/g, (_, reason, valtype) => `number(allocPage(_,'${reason}'),${valtype})`)
247
+ .replace(/\["alloc","(.*?)",(.*?)\]/g, (_, reason, valtype) => `[${valtype === Valtype.i32 ? Opcodes.i32_const : Opcodes.f64_const},allocPage(_,'${reason}')]`)
248
248
  .replace(/\["global",(.*?),"(.*?)",(.*?)\]/g, (_, opcode, name, valtype) => `...glbl(${opcode},'${name}',${valtype})`)
249
249
  .replace(/\"local","(.*?)",(.*?)\]/g, (_, name, valtype) => `loc('${name}',${valtype})]`)
250
250
  .replace(/\[16,"(.*?)"]/g, (_, name) => `[16,builtin('${name}')]`)
package/compiler/wrap.js CHANGED
@@ -586,7 +586,10 @@ export default (source, module = undefined, print = str => process.stdout.write(
586
586
  }
587
587
 
588
588
  times.push(performance.now() - t2);
589
- if (Prefs.profileCompiler && !globalThis.onProgress) console.log(`instantiated in ${times[1].toFixed(2)}ms`);
589
+ if (Prefs.profileCompiler) {
590
+ if (globalThis.onProgress) globalThis.onProgress('instantiated', times[1]);
591
+ else console.log(`instantiated in ${times[1].toFixed(2)}ms`);
592
+ }
590
593
 
591
594
  const exports = {};
592
595
  const rawValues = Prefs.d;
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "porffor",
3
3
  "description": "An ahead-of-time JavaScript compiler",
4
- "version": "0.60.8",
4
+ "version": "0.60.9",
5
5
  "author": "Oliver Medhurst <honk@goose.icu>",
6
6
  "license": "MIT",
7
7
  "scripts": {},
8
8
  "dependencies": {
9
9
  "acorn": "^8.15.0",
10
- "node-repl-polyfill": "github:CanadaHonk/node-repl-polyfill"
10
+ "node-repl-polyfill": "^0.1.2"
11
11
  },
12
12
  "optionalDependencies": {
13
13
  "@babel/parser": "^7.24.4",
package/runtime/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs';
3
- globalThis.version = '0.60.8';
3
+ globalThis.version = '0.60.9';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {