porffor 0.14.0-f67c123a1 → 0.16.0-a2e115b05

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/wrap.js CHANGED
@@ -8,7 +8,7 @@ import Prefs from './prefs.js';
8
8
 
9
9
  const bold = x => `\u001b[1m${x}\u001b[0m`;
10
10
 
11
- const porfToJSValue = (memory, funcs, value, type) => {
11
+ const porfToJSValue = ({ memory, funcs, pages }, value, type) => {
12
12
  switch (type) {
13
13
  case TYPES.boolean: return Boolean(value);
14
14
  case TYPES.undefined: return undefined;
@@ -41,9 +41,22 @@ const porfToJSValue = (memory, funcs, value, type) => {
41
41
  case TYPES.array: {
42
42
  const length = (new Int32Array(memory.buffer, value, 1))[0];
43
43
 
44
- // have to slice because of memory alignment (?)
45
- const buf = memory.buffer.slice(value + 4, value + 4 + 8 * length);
46
- return Array.from(new Float64Array(buf, 0, length));
44
+ const out = [];
45
+ for (let i = 0; i < length; i++) {
46
+ const offset = value + 4 + (i * 9);
47
+
48
+ // have to slice because of memory alignment (?)
49
+ const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
50
+ const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
51
+
52
+ // console.log(`reading value at index ${i}...`)
53
+ // console.log(' memory:', Array.from(new Uint8Array(memory.buffer, offset, 9)).map(x => x.toString(16).padStart(2, '0')).join(' '));
54
+ // console.log(' read:', { value: v, type: t }, '\n');
55
+
56
+ out.push(porfToJSValue({ memory, funcs, pages }, v, t));
57
+ }
58
+
59
+ return out;
47
60
  }
48
61
 
49
62
  case TYPES.date: {
@@ -66,12 +79,24 @@ const porfToJSValue = (memory, funcs, value, type) => {
66
79
  // console.log(' memory:', Array.from(new Uint8Array(memory.buffer, offset, 9)).map(x => x.toString(16).padStart(2, '0')).join(' '));
67
80
  // console.log(' read:', { value: v, type: t }, '\n');
68
81
 
69
- out.add(porfToJSValue(memory, funcs, v, t));
82
+ out.add(porfToJSValue({ memory, funcs, pages }, v, t));
70
83
  }
71
84
 
72
85
  return out;
73
86
  }
74
87
 
88
+ case TYPES.symbol: {
89
+ const descStore = pages.get('bytestring: __Porffor_symbol_descStore/ptr').ind * pageSize;
90
+ const offset = descStore + 4 + ((value - 1) * 9);
91
+
92
+ const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
93
+ const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
94
+
95
+ const desc = porfToJSValue({ memory, funcs, pages }, v, t);
96
+
97
+ return Symbol(desc);
98
+ }
99
+
75
100
  default: return value;
76
101
  }
77
102
  };
@@ -91,40 +116,12 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
91
116
  times.push(performance.now() - t1);
92
117
  if (Prefs.profileCompiler) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
93
118
 
94
- const t2 = performance.now();
95
-
96
- let instance;
97
- try {
98
- let wasmEngine = WebAssembly;
99
- if (Prefs.asur) {
100
- log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
101
- wasmEngine = await import('../asur/index.js');
102
- }
103
-
104
- 0, { instance } = await wasmEngine.instantiate(wasm, {
105
- '': {
106
- p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
107
- c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
108
- t: () => performance.now(),
109
- u: () => performance.timeOrigin,
110
- y: () => {},
111
- z: () => {},
112
- ...customImports
113
- }
114
- });
115
- } catch (e) {
116
- // only backtrace for runner, not test262/etc
117
- if (!process.argv[1].includes('/runner')) throw e;
118
-
119
- const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
120
- const blobOffset = parseInt(e.message.split('@')?.[1]);
121
-
122
- if (!funcInd) throw e;
119
+ const backtrace = (funcInd, blobOffset) => {
120
+ if (funcInd == null || blobOffset == null) return false;
123
121
 
124
122
  // convert blob offset -> function wasm offset.
125
123
  // this is not good code and is somewhat duplicated
126
124
  // I just want it to work for debugging, I don't care about perf/yes
127
-
128
125
  const func = funcs.find(x => x.index === funcInd);
129
126
  const locals = Object.values(func.locals).sort((a, b) => a.idx - b.idx).slice(func.params.length).sort((a, b) => a.idx - b.idx);
130
127
 
@@ -142,7 +139,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
142
139
 
143
140
  if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
144
141
 
145
- const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0, 40));
142
+ const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0, 60));
146
143
 
147
144
  let i = 0;
148
145
  for (; i < wasm.length; i++) {
@@ -157,7 +154,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
157
154
  if (!mismatch) break;
158
155
  }
159
156
 
160
- if (i === wasm.length) throw e;
157
+ if (i === wasm.length) return false;
161
158
 
162
159
  const offset = (blobOffset - i) + encodeVector(localDecl).length;
163
160
 
@@ -168,7 +165,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
168
165
  if (cumLen === offset) break;
169
166
  }
170
167
 
171
- if (cumLen !== offset) throw e;
168
+ if (cumLen !== offset) return false;
172
169
 
173
170
  i -= 1;
174
171
 
@@ -193,6 +190,38 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
193
190
  console.log(decomp.join('\n'));
194
191
  console.log('\x1B[90m...\x1B[0m\n');
195
192
 
193
+ return true;
194
+ };
195
+
196
+ const t2 = performance.now();
197
+
198
+ let instance;
199
+ try {
200
+ let wasmEngine = WebAssembly;
201
+ if (Prefs.asur) {
202
+ log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
203
+ wasmEngine = await import('../asur/index.js');
204
+ }
205
+
206
+ 0, { instance } = await wasmEngine.instantiate(wasm, {
207
+ '': {
208
+ p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
209
+ c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
210
+ t: () => performance.now(),
211
+ u: () => performance.timeOrigin,
212
+ y: () => {},
213
+ z: () => {},
214
+ ...customImports
215
+ }
216
+ });
217
+ } catch (e) {
218
+ // only backtrace for runner, not test262/etc
219
+ if (!process.argv[1].includes('/runner')) throw e;
220
+
221
+ const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
222
+ const blobOffset = parseInt(e.message.split('@')?.[1]);
223
+
224
+ backtrace(funcInd, blobOffset);
196
225
  throw e;
197
226
  }
198
227
 
@@ -200,6 +229,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
200
229
  if (Prefs.profileCompiler) console.log(`instantiated in ${times[1].toFixed(2)}ms`);
201
230
 
202
231
  const exports = {};
232
+ const rawValues = process.argv.includes('-i');
203
233
 
204
234
  const exceptTag = instance.exports['0'], memory = instance.exports['$'];
205
235
  for (const x in instance.exports) {
@@ -218,10 +248,11 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
218
248
  exports[func.name] = function() {
219
249
  try {
220
250
  const ret = exp.apply(this, arguments);
221
-
222
251
  if (ret == null) return undefined;
223
252
 
224
- return porfToJSValue(memory, funcs, ret[0], ret[1]);
253
+ if (rawValues) return { value: ret[0], type: ret[1], js: porfToJSValue({ memory, funcs, pages }, ret[0], ret[1]) };
254
+
255
+ return porfToJSValue({ memory, funcs, pages }, ret[0], ret[1]);
225
256
  } catch (e) {
226
257
  if (e.is && e.is(exceptTag)) {
227
258
  const exceptId = e.getArg(exceptTag, 0);
@@ -236,6 +267,17 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
236
267
  throw new constructor(exception.message);
237
268
  }
238
269
 
270
+ if (e instanceof WebAssembly.RuntimeError) {
271
+ // only backtrace for runner, not test262/etc
272
+ if (!process.argv[1].includes('/runner')) throw e;
273
+
274
+ const match = e.stack.match(/wasm-function\[([0-9]+)\]:([0-9a-z]+)/) ?? [];
275
+ const funcInd = parseInt(match[1]);
276
+ const blobOffset = parseInt(match[2]);
277
+
278
+ backtrace(funcInd, blobOffset);
279
+ }
280
+
239
281
  throw e;
240
282
  }
241
283
  };
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.14.0-f67c123a1",
4
+ "version": "0.16.0-a2e115b05",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {
package/runner/index.js CHANGED
@@ -25,7 +25,7 @@ if (process.argv.includes('--help')) {
25
25
  console.log(`Usage: \x1B[1mporf [command] path/to/script.js [...prefs] [...args]\x1B[0m`);
26
26
 
27
27
  // commands
28
- console.log(`\n\u001b[4mCommands\x1B[0m`);
28
+ console.log(`\n\x1B[1mCommands:\x1B[0m`);
29
29
  for (const [ cmd, [ color, desc ] ] of Object.entries({
30
30
  run: [ 34, 'Run a JS file' ],
31
31
  wasm: [ 34, 'Compile a JS file to a Wasm binary\n' ],
@@ -60,8 +60,10 @@ if (process.argv.includes('--help')) {
60
60
 
61
61
  let file = process.argv.slice(2).find(x => x[0] !== '-');
62
62
  if (['run', 'wasm', 'native', 'c', 'profile', 'debug', 'debug-wasm'].includes(file)) {
63
+ // remove this arg
64
+ process.argv.splice(process.argv.indexOf(file), 1);
65
+
63
66
  if (file === 'profile') {
64
- process.argv.splice(process.argv.indexOf(file), 1);
65
67
  await import('./profiler.js');
66
68
  await new Promise(() => {}); // do nothing for the rest of this file
67
69
  }
@@ -75,12 +77,11 @@ if (['run', 'wasm', 'native', 'c', 'profile', 'debug', 'debug-wasm'].includes(fi
75
77
  }
76
78
 
77
79
  if (file === 'debug') {
78
- process.argv.splice(process.argv.indexOf(file), 1);
79
80
  await import('./debug.js');
80
81
  await new Promise(() => {}); // do nothing for the rest of this file
81
82
  }
82
83
 
83
- file = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
84
+ file = process.argv.slice(2).find(x => x[0] !== '-');
84
85
 
85
86
  const nonOptOutFile = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
86
87
  if (nonOptOutFile) {
package/runner/repl.js CHANGED
@@ -1,6 +1,11 @@
1
+ import { TYPE_NAMES } from '../compiler/types.js';
1
2
  import compile from '../compiler/wrap.js';
2
3
  import version from './version.js';
3
4
 
5
+ import util from 'node:util';
6
+
7
+ process.argv.push('--no-opt-unused');
8
+
4
9
  let repl;
5
10
  try {
6
11
  // try importing node:repl
@@ -86,10 +91,21 @@ const run = async (source, _context, _filename, callback, run = true) => {
86
91
  lastPages = [...pages.keys()];
87
92
  }
88
93
 
89
- const ret = run ? exports.main() : undefined;
90
- callback(null, ret);
94
+ let ret = run ? exports.main() : undefined;
95
+ let value, type;
96
+ if (ret?.type != null) {
97
+ value = ret.value;
98
+ type = ret.type;
99
+ ret = ret.js;
100
+ }
101
+
102
+ console.log(util.inspect(ret, false, 2, true), (value != null ? `\x1B[34m\x1B[3m(value: ${value}, type: ${TYPE_NAMES[type]})\x1B[0m` : ''));
103
+
104
+ // callback(null, ret);
91
105
 
92
106
  prev = prev + ';\n' + source.trim();
107
+
108
+ callback();
93
109
  };
94
110
 
95
111
  const replServer = repl.start({ prompt: '> ', eval: run });