porffor 0.58.1 → 0.58.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/README.md +6 -6
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/runtime/index.js +5 -5
- package/asur/README.md +0 -2
- package/asur/index.js +0 -1262
- package/regex_notes.md +0 -74
- package/richards_direct.js +0 -558
package/asur/index.js
DELETED
@@ -1,1262 +0,0 @@
|
|
1
|
-
let offset = 0, input;
|
2
|
-
|
3
|
-
const read = () => input[offset++];
|
4
|
-
|
5
|
-
const signedLEB128 = () => {
|
6
|
-
let result = 0, shift = 0;
|
7
|
-
|
8
|
-
while (true) {
|
9
|
-
const byte = read();
|
10
|
-
result |= (byte & 0x7f) << shift;
|
11
|
-
|
12
|
-
shift += 7;
|
13
|
-
|
14
|
-
if ((0x80 & byte) == 0) { // final byte
|
15
|
-
if (shift < 32 && (byte & 0x40) != 0) {
|
16
|
-
return result | (-1 << shift);
|
17
|
-
}
|
18
|
-
|
19
|
-
return result;
|
20
|
-
}
|
21
|
-
}
|
22
|
-
};
|
23
|
-
|
24
|
-
const unsignedLEB128 = () => {
|
25
|
-
let result = 0, shift = 0;
|
26
|
-
|
27
|
-
while (true) {
|
28
|
-
const byte = read();
|
29
|
-
result |= (byte & 0x7f) << shift;
|
30
|
-
|
31
|
-
shift += 7;
|
32
|
-
|
33
|
-
if ((0x80 & byte) == 0) { // final byte
|
34
|
-
return result;
|
35
|
-
}
|
36
|
-
}
|
37
|
-
};
|
38
|
-
|
39
|
-
const ieee754 = () => new Float64Array(new Uint8Array([ read(), read(), read(), read(), read(), read(), read(), read() ]).buffer)[0];
|
40
|
-
|
41
|
-
const string = () => {
|
42
|
-
let out = '';
|
43
|
-
|
44
|
-
const len = unsignedLEB128();
|
45
|
-
for (let i = 0; i < len; i++) {
|
46
|
-
out += String.fromCharCode(read());
|
47
|
-
}
|
48
|
-
|
49
|
-
return out;
|
50
|
-
};
|
51
|
-
|
52
|
-
const wasmToBC = (code, { types, funcs, imports }) => {
|
53
|
-
const _input = input;
|
54
|
-
const _offset = offset;
|
55
|
-
|
56
|
-
input = code;
|
57
|
-
offset = 0;
|
58
|
-
|
59
|
-
const top = { body: [] };
|
60
|
-
|
61
|
-
let parents = [ top ];
|
62
|
-
let parent = top;
|
63
|
-
|
64
|
-
let depth = 0;
|
65
|
-
|
66
|
-
read: while (offset < input.length) {
|
67
|
-
let opcode = read();
|
68
|
-
// console.log(invOpcodes[opcode], depth, invOpcodes[parent.opcode]);
|
69
|
-
|
70
|
-
if (opcode === 0xfc) { // multibyte op
|
71
|
-
opcode = (opcode << 8) + read();
|
72
|
-
}
|
73
|
-
|
74
|
-
switch (opcode) {
|
75
|
-
case 0x01: { // nop
|
76
|
-
break;
|
77
|
-
}
|
78
|
-
|
79
|
-
case 0x02: // block
|
80
|
-
case 0x03: // loop
|
81
|
-
case 0x04: { // if
|
82
|
-
const ret = read();
|
83
|
-
const obj = { opcode, returns: ret, doesReturn: ret !== 0x40, body: [] };
|
84
|
-
parent.body.push(obj);
|
85
|
-
|
86
|
-
parent = obj;
|
87
|
-
parents.push(obj);
|
88
|
-
|
89
|
-
depth++;
|
90
|
-
|
91
|
-
break;
|
92
|
-
}
|
93
|
-
|
94
|
-
case 0x05: { // else
|
95
|
-
const obj = [];
|
96
|
-
parent.else = obj;
|
97
|
-
parent = { body: obj }; // mock parent obj for else branch
|
98
|
-
|
99
|
-
break;
|
100
|
-
}
|
101
|
-
|
102
|
-
case 0x0b: { // end
|
103
|
-
parents.pop();
|
104
|
-
parent = parents[parents.length - 1];
|
105
|
-
|
106
|
-
depth--;
|
107
|
-
|
108
|
-
// if (depth === -1) break read;
|
109
|
-
|
110
|
-
break;
|
111
|
-
}
|
112
|
-
|
113
|
-
case 0x0c: // br
|
114
|
-
case 0x0d: { // br_if
|
115
|
-
parent.body.push({ opcode, goto: read() });
|
116
|
-
break;
|
117
|
-
}
|
118
|
-
|
119
|
-
case 0x10: { // call
|
120
|
-
const func = read(); // unsignedLEB128();
|
121
|
-
const obj = { opcode, func };
|
122
|
-
|
123
|
-
if (func < imports.length) {
|
124
|
-
const mod = imports[func].module;
|
125
|
-
const name = imports[func].name;
|
126
|
-
|
127
|
-
obj.import = { mod, name };
|
128
|
-
|
129
|
-
const type = types[imports[func].typeIdx];
|
130
|
-
obj.type = type;
|
131
|
-
|
132
|
-
obj.paramCount = type.params.length;
|
133
|
-
obj.returnCount = type.returns.length;
|
134
|
-
|
135
|
-
parent.body.push(obj);
|
136
|
-
break;
|
137
|
-
}
|
138
|
-
|
139
|
-
const type = types[funcs[func - imports.length]];
|
140
|
-
obj.type = type;
|
141
|
-
|
142
|
-
obj.paramCount = type.params.length;
|
143
|
-
obj.returnCount = type.returns.length;
|
144
|
-
|
145
|
-
parent.body.push(obj);
|
146
|
-
break;
|
147
|
-
}
|
148
|
-
|
149
|
-
case 0x20: // local.get
|
150
|
-
case 0x21: // local.set
|
151
|
-
case 0x22: // local.tee
|
152
|
-
case 0x23: // global.get
|
153
|
-
case 0x24: { // global.set
|
154
|
-
parent.body.push({ opcode, idx: read() });
|
155
|
-
break;
|
156
|
-
}
|
157
|
-
|
158
|
-
case 0x41: { // i32.const
|
159
|
-
parent.body.push({ opcode, val: signedLEB128() });
|
160
|
-
break;
|
161
|
-
}
|
162
|
-
case 0x42: { // i64.const
|
163
|
-
parent.body.push({ opcode, val: signedLEB128() });
|
164
|
-
break;
|
165
|
-
}
|
166
|
-
case 0x44: { // f64.const
|
167
|
-
parent.body.push({ opcode, val: ieee754() });
|
168
|
-
break;
|
169
|
-
}
|
170
|
-
|
171
|
-
default: {
|
172
|
-
parent.body.push({ opcode });
|
173
|
-
break;
|
174
|
-
}
|
175
|
-
}
|
176
|
-
}
|
177
|
-
|
178
|
-
input = _input;
|
179
|
-
offset = _offset;
|
180
|
-
|
181
|
-
if (parents.length > 1) {
|
182
|
-
// console.log(parents);
|
183
|
-
// console.log(stringifyOp({ types, funcs, imports }, top));
|
184
|
-
throw new Error('wasmToBC failed');
|
185
|
-
}
|
186
|
-
|
187
|
-
return top;
|
188
|
-
};
|
189
|
-
|
190
|
-
const parse = (binary) => {
|
191
|
-
offset = 0;
|
192
|
-
input = binary;
|
193
|
-
|
194
|
-
if (
|
195
|
-
read() != 0x00 ||
|
196
|
-
read() != 0x61 ||
|
197
|
-
read() != 0x73 ||
|
198
|
-
read() != 0x6d
|
199
|
-
) throw new Error('invalid magic');
|
200
|
-
|
201
|
-
if (
|
202
|
-
read() != 0x01 ||
|
203
|
-
read() != 0x00 ||
|
204
|
-
read() != 0x00 ||
|
205
|
-
read() != 0x00
|
206
|
-
) throw new Error('invalid version');
|
207
|
-
|
208
|
-
let types = [],
|
209
|
-
imports = [],
|
210
|
-
funcs = [],
|
211
|
-
memories = [],
|
212
|
-
tags = [],
|
213
|
-
exports = [],
|
214
|
-
globals = [],
|
215
|
-
codes = [],
|
216
|
-
datas = [];
|
217
|
-
|
218
|
-
const len = input.length;
|
219
|
-
while (offset < len) {
|
220
|
-
const section = read();
|
221
|
-
const bytes = unsignedLEB128();
|
222
|
-
|
223
|
-
if (section === 1) { // type
|
224
|
-
const typesLength = unsignedLEB128();
|
225
|
-
types = new Array(typesLength);
|
226
|
-
|
227
|
-
for (let i = 0; i < typesLength; i++) {
|
228
|
-
const type = read();
|
229
|
-
|
230
|
-
const paramsLength = unsignedLEB128();
|
231
|
-
const params = new Array(paramsLength);
|
232
|
-
for (let j = 0; j < paramsLength; j++) params[j] = read();
|
233
|
-
|
234
|
-
const returnsLength = unsignedLEB128();
|
235
|
-
const returns = new Array(returnsLength);
|
236
|
-
for (let j = 0; j < returnsLength; j++) returns[j] = read();
|
237
|
-
|
238
|
-
types[i] = { type, params, returns };
|
239
|
-
}
|
240
|
-
|
241
|
-
continue;
|
242
|
-
}
|
243
|
-
|
244
|
-
if (section === 2) { // import
|
245
|
-
const importsLength = unsignedLEB128();
|
246
|
-
imports = new Array(importsLength);
|
247
|
-
|
248
|
-
for (let i = 0; i < importsLength; i++) {
|
249
|
-
const module = string();
|
250
|
-
const name = string();
|
251
|
-
|
252
|
-
const type = read();
|
253
|
-
|
254
|
-
const typeIdx = unsignedLEB128();
|
255
|
-
|
256
|
-
imports[i] = { module, name, type, typeIdx };
|
257
|
-
}
|
258
|
-
|
259
|
-
continue;
|
260
|
-
}
|
261
|
-
|
262
|
-
if (section === 3) { // func
|
263
|
-
const funcsLength = unsignedLEB128();
|
264
|
-
funcs = new Array(funcsLength);
|
265
|
-
|
266
|
-
for (let i = 0; i < funcsLength; i++) {
|
267
|
-
funcs[i] = unsignedLEB128();
|
268
|
-
}
|
269
|
-
|
270
|
-
continue;
|
271
|
-
}
|
272
|
-
|
273
|
-
if (section === 5) { // memory
|
274
|
-
const memoriesLength = unsignedLEB128();
|
275
|
-
memories = new Array(memoriesLength);
|
276
|
-
|
277
|
-
for (let i = 0; i < memoriesLength; i++) {
|
278
|
-
const flag = read();
|
279
|
-
|
280
|
-
let min = null, max = null;
|
281
|
-
switch (flag) {
|
282
|
-
case 0x00:
|
283
|
-
min = unsignedLEB128();
|
284
|
-
break;
|
285
|
-
|
286
|
-
case 0x01:
|
287
|
-
min = unsignedLEB128();
|
288
|
-
max = unsignedLEB128();
|
289
|
-
break;
|
290
|
-
}
|
291
|
-
|
292
|
-
memories[i] = { min, max };
|
293
|
-
}
|
294
|
-
}
|
295
|
-
|
296
|
-
if (section === 13) { // tag
|
297
|
-
const tagsLength = unsignedLEB128();
|
298
|
-
tags = new Array(tagsLength);
|
299
|
-
|
300
|
-
for (let i = 0; i < tagsLength; i++) {
|
301
|
-
const attr = read();
|
302
|
-
const type = unsignedLEB128();
|
303
|
-
|
304
|
-
tags[i] = { attr, type };
|
305
|
-
}
|
306
|
-
}
|
307
|
-
|
308
|
-
if (section === 6) { // global
|
309
|
-
const globalsLength = unsignedLEB128();
|
310
|
-
globals = new Array(globalsLength);
|
311
|
-
|
312
|
-
for (let i = 0; i < globalsLength; i++) {
|
313
|
-
const valtype = read();
|
314
|
-
const mutable = read() === 0x01;
|
315
|
-
|
316
|
-
let init = [];
|
317
|
-
while (true) {
|
318
|
-
const byte = read();
|
319
|
-
init.push(byte);
|
320
|
-
|
321
|
-
if (byte === 0x0b) break; // end
|
322
|
-
}
|
323
|
-
|
324
|
-
const bc = wasmToBC(init, { types, funcs, imports });
|
325
|
-
|
326
|
-
globals[i] = { valtype, mutable, init, bc };
|
327
|
-
if (globalThis.porfDebugInfo) {
|
328
|
-
for (const x in globalThis.porfDebugInfo.globals) {
|
329
|
-
if (globalThis.porfDebugInfo.globals[x].idx === i) globals[i].porfGlobalName = x;
|
330
|
-
}
|
331
|
-
}
|
332
|
-
}
|
333
|
-
|
334
|
-
continue;
|
335
|
-
}
|
336
|
-
|
337
|
-
if (section === 7) { // export
|
338
|
-
const exportsLength = unsignedLEB128();
|
339
|
-
exports = new Array(exportsLength);
|
340
|
-
|
341
|
-
for (let i = 0; i < exportsLength; i++) {
|
342
|
-
const name = string();
|
343
|
-
|
344
|
-
const type = read();
|
345
|
-
|
346
|
-
const index = unsignedLEB128();
|
347
|
-
|
348
|
-
exports[i] = { name, type, index };
|
349
|
-
}
|
350
|
-
|
351
|
-
continue;
|
352
|
-
}
|
353
|
-
|
354
|
-
if (section === 10) { // code
|
355
|
-
const codesLength = unsignedLEB128();
|
356
|
-
codes = new Array(codesLength);
|
357
|
-
|
358
|
-
for (let i = 0; i < codesLength; i++) {
|
359
|
-
const size = unsignedLEB128();
|
360
|
-
const end = offset + size;
|
361
|
-
|
362
|
-
const locals = types[funcs[i]].params.slice();
|
363
|
-
|
364
|
-
const localsLength = unsignedLEB128();
|
365
|
-
for (let j = 0; j < localsLength; j++) {
|
366
|
-
const count = unsignedLEB128();
|
367
|
-
const type = read();
|
368
|
-
|
369
|
-
for (let k = 0; k < count; k++) locals.push(type);
|
370
|
-
}
|
371
|
-
|
372
|
-
const bytesLeft = end - offset;
|
373
|
-
const wasm = new Array(bytesLeft);
|
374
|
-
for (let j = 0; j < bytesLeft; j++) wasm[j] = read();
|
375
|
-
|
376
|
-
const bc = wasmToBC(wasm, { types, funcs, imports });
|
377
|
-
bc.codeIdx = i;
|
378
|
-
bc.wasmType = types[funcs[i]];
|
379
|
-
if (globalThis.porfDebugInfo) bc.porfFunc = globalThis.porfDebugInfo.funcs[i];
|
380
|
-
|
381
|
-
codes[i] = { locals, wasm, bc };
|
382
|
-
}
|
383
|
-
|
384
|
-
continue;
|
385
|
-
}
|
386
|
-
|
387
|
-
if (section === 11) { // data
|
388
|
-
const datasLength = unsignedLEB128();
|
389
|
-
datas = new Array(datasLength);
|
390
|
-
|
391
|
-
for (let i = 0; i < datasLength; i++) {
|
392
|
-
const mode = read();
|
393
|
-
|
394
|
-
let offset = 0;
|
395
|
-
switch (mode) {
|
396
|
-
case 0:
|
397
|
-
let init = [];
|
398
|
-
while (true) {
|
399
|
-
const byte = read();
|
400
|
-
init.push(byte);
|
401
|
-
|
402
|
-
if (byte === 0x0b) break; // end
|
403
|
-
}
|
404
|
-
|
405
|
-
offset = runExpr(init);
|
406
|
-
|
407
|
-
break;
|
408
|
-
|
409
|
-
default:
|
410
|
-
throw new Error('todo');
|
411
|
-
}
|
412
|
-
|
413
|
-
const bytesLength = unsignedLEB128();
|
414
|
-
const bytes = new Array(bytesLength);
|
415
|
-
|
416
|
-
for (let j = 0; j < bytesLength; j++) bytes[j] = read();
|
417
|
-
|
418
|
-
datas[i] = { offset, bytes };
|
419
|
-
}
|
420
|
-
}
|
421
|
-
|
422
|
-
if (section === 12) { // data count
|
423
|
-
datas.dataCount = unsignedLEB128();
|
424
|
-
}
|
425
|
-
}
|
426
|
-
|
427
|
-
return { types, imports, funcs, memories, tags, globals, exports, codes, datas };
|
428
|
-
};
|
429
|
-
|
430
|
-
const inv = (obj, keyMap = x => x) => Object.keys(obj).reduce((acc, x) => {
|
431
|
-
const k = keyMap(obj[x]);
|
432
|
-
if (acc[k] == null) acc[k] = x;
|
433
|
-
return acc;
|
434
|
-
}, {});
|
435
|
-
|
436
|
-
// const { Opcodes, Valtype } = (await import('../compiler/wasmSpec.js'));
|
437
|
-
// const invOpcodes = inv(Opcodes, x => {
|
438
|
-
// if (typeof x === 'number') return x;
|
439
|
-
// return (x[0] << 8) + x[1];
|
440
|
-
// });
|
441
|
-
// const invValtype = inv(Valtype);
|
442
|
-
|
443
|
-
let times = {};
|
444
|
-
let amounts = {};
|
445
|
-
|
446
|
-
const vm = ({ types, imports, funcs, globals, exports, codes }, importImpls, startFunc) => {
|
447
|
-
const run = (bc, locals = []) => {
|
448
|
-
let stack = [];
|
449
|
-
|
450
|
-
let parents = [ bc ];
|
451
|
-
let parent = bc;
|
452
|
-
|
453
|
-
parent.pc = 0;
|
454
|
-
|
455
|
-
while (true) {
|
456
|
-
// const start = performance.now();
|
457
|
-
const op = parent.body[parent.pc++];
|
458
|
-
// if (bc.name === '__console_log') console.log(invOpcodes[op?.opcode], invOpcodes[parent?.opcode], parent.pc - 1, parent.body.length - 1, parents.length - 1);
|
459
|
-
if (!op) {
|
460
|
-
// presume end of op body
|
461
|
-
parents.pop();
|
462
|
-
parent = parents[parents.length - 1];
|
463
|
-
|
464
|
-
if (!parent) {
|
465
|
-
// presume end of func
|
466
|
-
return stack;
|
467
|
-
}
|
468
|
-
|
469
|
-
continue;
|
470
|
-
}
|
471
|
-
|
472
|
-
const br = n => {
|
473
|
-
const ind = parents.length - n - 1;
|
474
|
-
const target = parents[ind];
|
475
|
-
|
476
|
-
// console.log(n, parents.map(x => invOpcodes[x.opcode]), target);
|
477
|
-
if (target.opcode === 0x03) { // loop
|
478
|
-
parents = parents.slice(0, ind + 1);
|
479
|
-
parent = parents[parents.length - 1];
|
480
|
-
parent.pc = 0;
|
481
|
-
} else {
|
482
|
-
parents = parents.slice(0, ind);
|
483
|
-
parent = parents[parents.length - 1];
|
484
|
-
}
|
485
|
-
};
|
486
|
-
|
487
|
-
switch (op.opcode) {
|
488
|
-
case 0x00: { // unreachable
|
489
|
-
throw new Error('unreachable');
|
490
|
-
}
|
491
|
-
|
492
|
-
case 0x01: { // nop
|
493
|
-
break;
|
494
|
-
}
|
495
|
-
|
496
|
-
case 0x02: { // block
|
497
|
-
parents.push(op);
|
498
|
-
parent = op;
|
499
|
-
parent.pc = 0;
|
500
|
-
|
501
|
-
break;
|
502
|
-
}
|
503
|
-
|
504
|
-
case 0x03: { // loop
|
505
|
-
parents.push(op);
|
506
|
-
parent = op;
|
507
|
-
parent.pc = 0;
|
508
|
-
|
509
|
-
break;
|
510
|
-
}
|
511
|
-
|
512
|
-
case 0x04: { // if
|
513
|
-
const cond = stack.pop();
|
514
|
-
if (cond) { // true cond
|
515
|
-
parent = op;
|
516
|
-
parents.push(op);
|
517
|
-
parent.pc = 0;
|
518
|
-
} else if (op.else) { // false cond, else branch exists
|
519
|
-
parent = { body: op.else }; // mock parent for else branch
|
520
|
-
parents.push(op);
|
521
|
-
parent.pc = 0;
|
522
|
-
} else { // false cond, no else branch
|
523
|
-
// do nothing to just skip this op
|
524
|
-
}
|
525
|
-
|
526
|
-
break;
|
527
|
-
}
|
528
|
-
|
529
|
-
case 0x0c: { // br
|
530
|
-
br(op.goto);
|
531
|
-
break;
|
532
|
-
}
|
533
|
-
|
534
|
-
case 0x0d: { // br_if
|
535
|
-
if (stack.pop()) br(op.goto);
|
536
|
-
break;
|
537
|
-
}
|
538
|
-
|
539
|
-
case 0x0f: { // return
|
540
|
-
return stack;
|
541
|
-
}
|
542
|
-
|
543
|
-
case 0x10: { // call
|
544
|
-
const paramCount = op.paramCount;
|
545
|
-
|
546
|
-
if (op.import) {
|
547
|
-
const params = new Array(paramCount);
|
548
|
-
|
549
|
-
if (paramCount === 0) {}
|
550
|
-
else if (paramCount === 1) params[0] = stack.pop();
|
551
|
-
else if (paramCount === 2) { params[1] = stack.pop(); params[0] = stack.pop(); }
|
552
|
-
else for (let i = paramCount - 1; i >= 0; i--) params[i] = stack.pop();
|
553
|
-
|
554
|
-
const ret = importImpls[op.import.mod][op.import.name](...params);
|
555
|
-
|
556
|
-
if (type.returns.length > 0) stack.push(ret);
|
557
|
-
|
558
|
-
break;
|
559
|
-
}
|
560
|
-
|
561
|
-
const code = codes[op.func - imports.length];
|
562
|
-
|
563
|
-
// console.log(bc.name, '->', code.bc.name);
|
564
|
-
|
565
|
-
const callBC = code.bc;
|
566
|
-
const locals = new Array(code.locals.length).fill(0);
|
567
|
-
|
568
|
-
if (paramCount === 0) {}
|
569
|
-
else if (paramCount === 1) locals[0] = stack.pop();
|
570
|
-
else if (paramCount === 2) { locals[1] = stack.pop(); locals[0] = stack.pop(); }
|
571
|
-
else for (let i = paramCount - 1; i >= 0; i--) locals[i] = stack.pop();
|
572
|
-
|
573
|
-
const outStack = run(callBC, locals);
|
574
|
-
stack.push(...outStack);
|
575
|
-
|
576
|
-
// console.log(bc.name, '<-', code.bc.name);
|
577
|
-
|
578
|
-
break;
|
579
|
-
}
|
580
|
-
|
581
|
-
case 0x1a: { // drop
|
582
|
-
stack.pop();
|
583
|
-
break;
|
584
|
-
}
|
585
|
-
|
586
|
-
case 0x20: { // local.get
|
587
|
-
stack.push(locals[op.idx]);
|
588
|
-
break;
|
589
|
-
}
|
590
|
-
|
591
|
-
case 0x21: { // local.set
|
592
|
-
locals[op.idx] = stack.pop();
|
593
|
-
break;
|
594
|
-
}
|
595
|
-
|
596
|
-
case 0x22: { // local.tee
|
597
|
-
stack.push(locals[op.idx] = stack.pop());
|
598
|
-
break;
|
599
|
-
}
|
600
|
-
|
601
|
-
case 0x23: { // global.get
|
602
|
-
// lazily evaluate global init exprs
|
603
|
-
const idx = op.idx;
|
604
|
-
if (globals[idx].value == null) {
|
605
|
-
globals[idx].value = run(globals[idx].bc, [], false)[0];
|
606
|
-
}
|
607
|
-
|
608
|
-
stack.push(globals[idx].value);
|
609
|
-
break;
|
610
|
-
}
|
611
|
-
|
612
|
-
case 0x24: { // global.set
|
613
|
-
globals[op.idx].value = stack.pop();
|
614
|
-
break;
|
615
|
-
}
|
616
|
-
|
617
|
-
case 0x41: { // i32.const
|
618
|
-
stack.push(op.val);
|
619
|
-
break;
|
620
|
-
}
|
621
|
-
case 0x42: { // i64.const
|
622
|
-
stack.push(op.val);
|
623
|
-
break;
|
624
|
-
}
|
625
|
-
case 0x44: { // f64.const
|
626
|
-
stack.push(op.val);
|
627
|
-
break;
|
628
|
-
}
|
629
|
-
|
630
|
-
case 0x45: { // i32_eqz
|
631
|
-
stack.push(stack.pop() === 0);
|
632
|
-
break;
|
633
|
-
}
|
634
|
-
case 0x46: { // i32_eq
|
635
|
-
stack.push(stack.pop() === stack.pop());
|
636
|
-
break;
|
637
|
-
}
|
638
|
-
case 0x47: { // i32_ne
|
639
|
-
stack.push(stack.pop() !== stack.pop());
|
640
|
-
break;
|
641
|
-
}
|
642
|
-
case 0x48: { // i32.lt_s
|
643
|
-
const b = stack.pop();
|
644
|
-
const a = stack.pop();
|
645
|
-
stack.push(a < b);
|
646
|
-
break;
|
647
|
-
}
|
648
|
-
case 0x4c: { // i32.le_s
|
649
|
-
const b = stack.pop();
|
650
|
-
const a = stack.pop();
|
651
|
-
stack.push(a <= b);
|
652
|
-
break;
|
653
|
-
}
|
654
|
-
case 0x4a: { // i32.gt_s
|
655
|
-
const b = stack.pop();
|
656
|
-
const a = stack.pop();
|
657
|
-
stack.push(a > b);
|
658
|
-
break;
|
659
|
-
}
|
660
|
-
case 0x4e: { // i32_ge_s
|
661
|
-
const b = stack.pop();
|
662
|
-
const a = stack.pop();
|
663
|
-
stack.push(a >= b);
|
664
|
-
break;
|
665
|
-
}
|
666
|
-
|
667
|
-
case 0x6a: { // i32_add
|
668
|
-
const b = stack.pop();
|
669
|
-
const a = stack.pop();
|
670
|
-
stack.push(a + b);
|
671
|
-
break;
|
672
|
-
}
|
673
|
-
case 0x6b: { // i32_sub
|
674
|
-
const b = stack.pop();
|
675
|
-
const a = stack.pop();
|
676
|
-
stack.push(a - b);
|
677
|
-
break;
|
678
|
-
}
|
679
|
-
case 0x6c: { // i32_mul
|
680
|
-
const b = stack.pop();
|
681
|
-
const a = stack.pop();
|
682
|
-
stack.push(a * b);
|
683
|
-
break;
|
684
|
-
}
|
685
|
-
case 0x6d: { // i32_div_s
|
686
|
-
const b = stack.pop();
|
687
|
-
const a = stack.pop();
|
688
|
-
stack.push(a / b);
|
689
|
-
break;
|
690
|
-
}
|
691
|
-
case 0x6f: { // i32_rem_s
|
692
|
-
const b = stack.pop();
|
693
|
-
const a = stack.pop();
|
694
|
-
stack.push(a % b);
|
695
|
-
break;
|
696
|
-
}
|
697
|
-
|
698
|
-
case 0x71: { // i32_and
|
699
|
-
const b = stack.pop();
|
700
|
-
const a = stack.pop();
|
701
|
-
stack.push(a & b);
|
702
|
-
break;
|
703
|
-
}
|
704
|
-
case 0x72: { // i32_or
|
705
|
-
const b = stack.pop();
|
706
|
-
const a = stack.pop();
|
707
|
-
stack.push(a | b);
|
708
|
-
break;
|
709
|
-
}
|
710
|
-
case 0x73: { // i32_xor
|
711
|
-
const b = stack.pop();
|
712
|
-
const a = stack.pop();
|
713
|
-
stack.push(a ^ b);
|
714
|
-
break;
|
715
|
-
}
|
716
|
-
case 0x74: { // i32_shl
|
717
|
-
const b = stack.pop();
|
718
|
-
const a = stack.pop();
|
719
|
-
stack.push(a << b);
|
720
|
-
break;
|
721
|
-
}
|
722
|
-
case 0x75: { // i32_shr_s
|
723
|
-
const b = stack.pop();
|
724
|
-
const a = stack.pop();
|
725
|
-
stack.push(a >> b);
|
726
|
-
break;
|
727
|
-
}
|
728
|
-
case 0x76: { // i32_shr_u
|
729
|
-
const b = stack.pop();
|
730
|
-
const a = stack.pop();
|
731
|
-
stack.push(a >>> b);
|
732
|
-
break;
|
733
|
-
}
|
734
|
-
|
735
|
-
// case 0x50: { // i64_eqz
|
736
|
-
// break;
|
737
|
-
// }
|
738
|
-
// case 0x51: { // i64_eq
|
739
|
-
// break;
|
740
|
-
// }
|
741
|
-
// case 0x52: { // i64_ne
|
742
|
-
// break;
|
743
|
-
// }
|
744
|
-
|
745
|
-
// case 0x53: { // i64_lt_s
|
746
|
-
// break;
|
747
|
-
// }
|
748
|
-
// case 0x57: { // i64_le_s
|
749
|
-
// break;
|
750
|
-
// }
|
751
|
-
// case 0x55: { // i64_gt_s
|
752
|
-
// break;
|
753
|
-
// }
|
754
|
-
// case 0x59: { // i64_ge_s
|
755
|
-
// break;
|
756
|
-
// }
|
757
|
-
|
758
|
-
// case 0x7c: { // i64_add
|
759
|
-
// break;
|
760
|
-
// }
|
761
|
-
// case 0x7d: { // i64_sub
|
762
|
-
// break;
|
763
|
-
// }
|
764
|
-
// case 0x7e: { // i64_mul
|
765
|
-
// break;
|
766
|
-
// }
|
767
|
-
// case 0x7f: { // i64_div_s
|
768
|
-
// break;
|
769
|
-
// }
|
770
|
-
// case 0x81: { // i64_rem_s
|
771
|
-
// break;
|
772
|
-
// }
|
773
|
-
|
774
|
-
// case 0x83: { // i64_and
|
775
|
-
// break;
|
776
|
-
// }
|
777
|
-
// case 0x84: { // i64_or
|
778
|
-
// break;
|
779
|
-
// }
|
780
|
-
// case 0x85: { // i64_xor
|
781
|
-
// break;
|
782
|
-
// }
|
783
|
-
// case 0x86: { // i64_shl
|
784
|
-
// break;
|
785
|
-
// }
|
786
|
-
// case 0x87: { // i64_shr_s
|
787
|
-
// break;
|
788
|
-
// }
|
789
|
-
// case 0x88: { // i64_shr_u
|
790
|
-
// break;
|
791
|
-
// }
|
792
|
-
|
793
|
-
case 0x61: { // f64_eq
|
794
|
-
stack.push(stack.pop() === stack.pop());
|
795
|
-
break;
|
796
|
-
}
|
797
|
-
case 0x62: { // f64_ne
|
798
|
-
stack.push(stack.pop() !== stack.pop());
|
799
|
-
break;
|
800
|
-
}
|
801
|
-
|
802
|
-
case 0x63: { // f64_lt
|
803
|
-
const b = stack.pop();
|
804
|
-
const a = stack.pop();
|
805
|
-
stack.push(a < b);
|
806
|
-
break;
|
807
|
-
}
|
808
|
-
case 0x65: { // f64_le
|
809
|
-
const b = stack.pop();
|
810
|
-
const a = stack.pop();
|
811
|
-
stack.push(a <= b);
|
812
|
-
break;
|
813
|
-
}
|
814
|
-
case 0x64: { // f64_gt
|
815
|
-
const b = stack.pop();
|
816
|
-
const a = stack.pop();
|
817
|
-
stack.push(a > b);
|
818
|
-
break;
|
819
|
-
}
|
820
|
-
case 0x66: { // f64_ge
|
821
|
-
const b = stack.pop();
|
822
|
-
const a = stack.pop();
|
823
|
-
stack.push(a >= b);
|
824
|
-
break;
|
825
|
-
}
|
826
|
-
|
827
|
-
case 0x99: { // f64_abs
|
828
|
-
stack.push(Math.abs(stack.pop()));
|
829
|
-
break;
|
830
|
-
}
|
831
|
-
case 0x9a: { // f64_neg
|
832
|
-
stack.push(stack.pop() * -1);
|
833
|
-
break;
|
834
|
-
}
|
835
|
-
|
836
|
-
case 0x9b: { // f64_ceil
|
837
|
-
stack.push(Math.ceil(stack.pop()));
|
838
|
-
break;
|
839
|
-
}
|
840
|
-
case 0x9c: { // f64_floor
|
841
|
-
stack.push(Math.floor(stack.pop()));
|
842
|
-
break;
|
843
|
-
}
|
844
|
-
case 0x9d: { // f64_trunc
|
845
|
-
stack.push(stack.pop() | 0);
|
846
|
-
break;
|
847
|
-
}
|
848
|
-
case 0x9e: { // f64_nearest
|
849
|
-
stack.push(Math.round(stack.pop()));
|
850
|
-
break;
|
851
|
-
}
|
852
|
-
|
853
|
-
case 0x9f: { // f64_sqrt
|
854
|
-
stack.push(Math.sqrt(stack.pop()));
|
855
|
-
break;
|
856
|
-
}
|
857
|
-
case 0xa0: { // f64_add
|
858
|
-
const b = stack.pop();
|
859
|
-
const a = stack.pop();
|
860
|
-
stack.push(a + b);
|
861
|
-
break;
|
862
|
-
}
|
863
|
-
case 0xa1: { // f64_sub
|
864
|
-
const b = stack.pop();
|
865
|
-
const a = stack.pop();
|
866
|
-
stack.push(a - b);
|
867
|
-
break;
|
868
|
-
}
|
869
|
-
case 0xa2: { // f64_mul
|
870
|
-
const b = stack.pop();
|
871
|
-
const a = stack.pop();
|
872
|
-
stack.push(a * b);
|
873
|
-
break;
|
874
|
-
}
|
875
|
-
case 0xa3: { // f64_div
|
876
|
-
const b = stack.pop();
|
877
|
-
const a = stack.pop();
|
878
|
-
stack.push(a / b);
|
879
|
-
break;
|
880
|
-
}
|
881
|
-
case 0xa4: { // f64_min
|
882
|
-
const b = stack.pop();
|
883
|
-
const a = stack.pop();
|
884
|
-
stack.push(a > b ? b : a);
|
885
|
-
break;
|
886
|
-
}
|
887
|
-
case 0xa5: { // f64_max
|
888
|
-
const b = stack.pop();
|
889
|
-
const a = stack.pop();
|
890
|
-
stack.push(a > b ? a : b);
|
891
|
-
break;
|
892
|
-
}
|
893
|
-
|
894
|
-
case 0xa7: { // i32_wrap_i64
|
895
|
-
break;
|
896
|
-
}
|
897
|
-
case 0xac: { // i64_extend_i32_s
|
898
|
-
break;
|
899
|
-
}
|
900
|
-
case 0xad: { // i64_extend_i32_u
|
901
|
-
break;
|
902
|
-
}
|
903
|
-
|
904
|
-
case 0xb6: { // f32_demote_f64
|
905
|
-
break;
|
906
|
-
}
|
907
|
-
case 0xbb: { // f64_promote_f32
|
908
|
-
break;
|
909
|
-
}
|
910
|
-
|
911
|
-
case 0xb7: { // f64_convert_i32_s
|
912
|
-
break;
|
913
|
-
}
|
914
|
-
case 0xb8: { // f64_convert_i32_u
|
915
|
-
break;
|
916
|
-
}
|
917
|
-
case 0xb9: { // f64_convert_i64_s
|
918
|
-
break;
|
919
|
-
}
|
920
|
-
case 0xba: { // f64_convert_i64_u
|
921
|
-
break;
|
922
|
-
}
|
923
|
-
|
924
|
-
case 0xfc02: { // i32_trunc_sat_f64_s
|
925
|
-
break;
|
926
|
-
}
|
927
|
-
|
928
|
-
case 0xfc03: { // i32_trunc_sat_f64_u
|
929
|
-
break;
|
930
|
-
}
|
931
|
-
|
932
|
-
default: {
|
933
|
-
console.log(activeFunc, offset, input.length, parents.length - 1);
|
934
|
-
throw new Error(`unimplemented op: 0x${op.opcode?.toString(16)}`);
|
935
|
-
}
|
936
|
-
}
|
937
|
-
|
938
|
-
// const t = performance.now() - start;
|
939
|
-
// times[invOpcodes[op.opcode]] = (times[invOpcodes[op.opcode]] ?? 0) + t;
|
940
|
-
// amounts[invOpcodes[op.opcode]] = (amounts[invOpcodes[op.opcode]] ?? 0) + 1;
|
941
|
-
}
|
942
|
-
};
|
943
|
-
|
944
|
-
const type = types[funcs[startFunc - imports.length]];
|
945
|
-
const code = codes[startFunc - imports.length];
|
946
|
-
|
947
|
-
return (...args) => {
|
948
|
-
const locals = new Array(code.locals.length).fill(0);
|
949
|
-
|
950
|
-
for (let i = 0; i < type.params.length; i++) locals[i] = args[i];
|
951
|
-
|
952
|
-
return run(code.bc, locals);
|
953
|
-
|
954
|
-
// times = {};
|
955
|
-
// const ret = run(code.bc, args);
|
956
|
-
// console.log('\n\n' + Object.keys(times).map(x => `${x}: ${((times[x] * 1000) / amounts[x]).toFixed(5)}s/op avg`).join('\n'));
|
957
|
-
// return ret;
|
958
|
-
};
|
959
|
-
};
|
960
|
-
|
961
|
-
const runExpr = wasm => vm({
|
962
|
-
types: [ { params: [] } ],
|
963
|
-
imports: [],
|
964
|
-
funcs: [ 0 ],
|
965
|
-
globals: [],
|
966
|
-
exports: [],
|
967
|
-
codes: [ { wasm, bc: wasmToBC(wasm, {}) } ]
|
968
|
-
}, {}, 0)();
|
969
|
-
|
970
|
-
const stringifyOp = ({ types, funcs, codes, imports, globals }, op, porfFunc = op.porfFunc, depth = 0) => {
|
971
|
-
const noHighlight = x => [...x].join('');
|
972
|
-
|
973
|
-
let str = ' '.repeat(depth * 2) + (op.opcode ?
|
974
|
-
invOpcodes[op.opcode].replace('_', '.').replace('return.', 'return_').replace('call.', 'call_').replace('br.', 'br_').replace('catch.', 'catch_') :
|
975
|
-
((op.porfFunc?.name ? `${noHighlight(op.porfFunc.name)} ` : '') + (op.wasmType?.params ? `(${op.wasmType.params.map(x => invValtype[x]).join(', ')}) -> (${op.wasmType.returns.map(x => invValtype[x]).join(', ')})` : ''))
|
976
|
-
);
|
977
|
-
|
978
|
-
// if (op.returns && op.returns !== 0x40) str += ` ${invValtype[op.returns]}`;
|
979
|
-
if (op.goto != null) str += ` ${op.goto}`;
|
980
|
-
if (op.func != null) str += ` ${op.func}`;
|
981
|
-
if (op.idx != null) str += ` ${op.idx}`;
|
982
|
-
if (op.val != null) str += ` ${op.val}`;
|
983
|
-
|
984
|
-
if (porfFunc) {
|
985
|
-
if (!porfFunc.invLocals) porfFunc.invLocals = inv(porfFunc.locals, x => x.idx);
|
986
|
-
|
987
|
-
if (op.func != null) {
|
988
|
-
str += ` \x1b[90m${op.func >= imports.length ? `${noHighlight(codes[op.func - imports.length].bc.porfFunc.name)}` : `${({ p: 'print', c: 'printChar', t: 'time', u: 'timeOrigin', y: 'profile1', z: 'profile2' })[imports[op.func].name]}`}`;
|
989
|
-
const type = types[op.func >= imports.length ? funcs[op.func - imports.length] : imports[op.func].typeIdx];
|
990
|
-
str += ` (${type.params.map(x => noHighlight(invValtype[x])).join(', ')}) -> (${type.returns.map(x => noHighlight(invValtype[x])).join(', ')})`;
|
991
|
-
str += '\x1b[0m';
|
992
|
-
}
|
993
|
-
|
994
|
-
if (op.opcode >= 0x20 && op.opcode <= 0x22) str += ` \x1b[90m${noHighlight(porfFunc.invLocals[op.idx] ?? '')}\x1b[0m`;
|
995
|
-
if (op.opcode >= 0x23 && op.opcode <= 0x24) str += ` \x1b[90m${noHighlight(globals[op.idx].porfGlobalName ?? '')}\x1b[0m`;
|
996
|
-
}
|
997
|
-
|
998
|
-
if (op.body) {
|
999
|
-
str += ':\n';
|
1000
|
-
for (const x of op.body) {
|
1001
|
-
str += stringifyOp({ types, funcs, codes, imports, globals }, x, porfFunc, depth + 1) + '\n';
|
1002
|
-
}
|
1003
|
-
|
1004
|
-
if (op.else) {
|
1005
|
-
str += ' '.repeat(depth * 2) + 'else:\n';
|
1006
|
-
for (const x of op.else) {
|
1007
|
-
str += stringifyOp({ types, funcs, codes, imports, globals }, x, porfFunc, depth + 1) + '\n';
|
1008
|
-
}
|
1009
|
-
}
|
1010
|
-
|
1011
|
-
str = str.slice(0, -1);
|
1012
|
-
// str += ' '.repeat(depth * 2) + 'end';
|
1013
|
-
}
|
1014
|
-
|
1015
|
-
const highlightAsm = asm => asm
|
1016
|
-
.replace(/(local|global|memory)\.[^\s]*/g, _ => `\x1B[31m${_}\x1B[0m`)
|
1017
|
-
.replace(/(i(8|16|32|64)x[0-9]+|v128)(\.[^\s]*)?/g, _ => `\x1B[34m${_}\x1B[0m`)
|
1018
|
-
.replace(/(i32|i64|f32|f64|drop)(\.[^\s]*)?/g, _ => `\x1B[36m${_}\x1B[0m`)
|
1019
|
-
.replace(/(return_call|call|br_if|br|return|rethrow|throw)/g, _ => `\x1B[35m${_}\x1B[0m`)
|
1020
|
-
.replace(/(block|loop|if|end|else|try|catch_all|catch|delegate):?/g, _ => `\x1B[95m${_}\x1B[0m`)
|
1021
|
-
.replace(/unreachable/g, _ => `\x1B[91m${_}\x1B[0m`)
|
1022
|
-
.replace(/ \-?[0-9\.]+/g, _ => ` \x1B[93m${_.slice(1)}\x1B[0m`)
|
1023
|
-
.replace(/ ;;.*$/gm, _ => `\x1B[90m${_.replaceAll(/\x1B\[[0-9]+m/g, '')}\x1B[0m`);
|
1024
|
-
|
1025
|
-
return highlightAsm(str);
|
1026
|
-
};
|
1027
|
-
|
1028
|
-
let Byg, invOpcodes, invValtype;
|
1029
|
-
|
1030
|
-
// setup a debug variant by self modifying code to avoid overhead when not debugging
|
1031
|
-
let _wasmDebugVm;
|
1032
|
-
const wasmDebugVm = (async () => {
|
1033
|
-
if (_wasmDebugVm) return _wasmDebugVm;
|
1034
|
-
|
1035
|
-
// imports only for debug
|
1036
|
-
const { Opcodes, Valtype } = (await import('../compiler/wasmSpec.js'));
|
1037
|
-
invOpcodes = inv(Opcodes, x => {
|
1038
|
-
if (typeof x === 'number') return x;
|
1039
|
-
return (x[0] << 8) + x[1];
|
1040
|
-
});
|
1041
|
-
invValtype = inv(Valtype);
|
1042
|
-
|
1043
|
-
Byg = (await import('../byg/index.js')).default;
|
1044
|
-
|
1045
|
-
|
1046
|
-
let str = vm.toString();
|
1047
|
-
|
1048
|
-
// add to start of vm()
|
1049
|
-
// make lines
|
1050
|
-
str = `({ types, imports, funcs, globals, exports, codes }, importImpls, startFunc) => {
|
1051
|
-
let paused = true;
|
1052
|
-
let stepIn = false, stepOut = false;
|
1053
|
-
const lines = codes.map(x => stringifyOp({ types, funcs, codes, imports, globals }, x.bc)).join('\\n\\n').split('\\n');
|
1054
|
-
const funcLines = new Array(codes.length);
|
1055
|
-
let j = 0;
|
1056
|
-
for (let i = 0; i < lines.length; i++) {
|
1057
|
-
const x = lines[i];
|
1058
|
-
if (x[0] !== ' ' && x !== '\\x1B[95mend\\x1B[0m' && x !== '') funcLines[j++] = i;
|
1059
|
-
}
|
1060
|
-
|
1061
|
-
let callStack = [];
|
1062
|
-
const byg = Byg({
|
1063
|
-
lines,
|
1064
|
-
pause: () => { paused = true; },
|
1065
|
-
breakpoint: (line, breakpoint) => {
|
1066
|
-
// it's (not) very effishient
|
1067
|
-
const funcOffset = funcLines.slice().reverse().find(x => line > x);
|
1068
|
-
const func = funcLines.indexOf(funcOffset);
|
1069
|
-
const totalOpIdx = line - funcOffset;
|
1070
|
-
|
1071
|
-
let op = 0;
|
1072
|
-
const iter = bc => {
|
1073
|
-
for (const x of bc) {
|
1074
|
-
op++;
|
1075
|
-
if (op === totalOpIdx) {
|
1076
|
-
op = x;
|
1077
|
-
return true;
|
1078
|
-
}
|
1079
|
-
|
1080
|
-
if (x.body) {
|
1081
|
-
if (iter(x.body)) return true;
|
1082
|
-
}
|
1083
|
-
|
1084
|
-
if (x.else) {
|
1085
|
-
op++;
|
1086
|
-
if (iter(x.else)) return true;
|
1087
|
-
}
|
1088
|
-
}
|
1089
|
-
};
|
1090
|
-
iter(codes[func].bc.body);
|
1091
|
-
|
1092
|
-
op.breakpoint = breakpoint;
|
1093
|
-
}
|
1094
|
-
});
|
1095
|
-
` + str.slice(str.indexOf('=>') + 4);
|
1096
|
-
|
1097
|
-
// add to start of run()
|
1098
|
-
str = str.replace('const run = (bc, locals = []) => {', `const run = (bc, locals = []) => {
|
1099
|
-
if (bc.porfFunc) callStack.push(bc.porfFunc.name);
|
1100
|
-
let lastDebugLocals = null, lastDebugGlobals = null;
|
1101
|
-
`);
|
1102
|
-
|
1103
|
-
// add to start of returns
|
1104
|
-
str = str.replaceAll('return stack;', `if (bc.porfFunc) callStack.pop();
|
1105
|
-
return stack;`);
|
1106
|
-
|
1107
|
-
// add to vm loop
|
1108
|
-
str = str.replace('const op = parent.body[parent.pc++];', `const op = parent.body[parent.pc++];
|
1109
|
-
if (op && op.breakpoint) paused = true;
|
1110
|
-
if (bc.porfFunc && paused && op) {
|
1111
|
-
stepIn = false; stepOut = false;
|
1112
|
-
|
1113
|
-
const currentFunc = bc.codeIdx;
|
1114
|
-
|
1115
|
-
let currentLine = 0;
|
1116
|
-
const addBodyLines = x => {
|
1117
|
-
currentLine += x.length;
|
1118
|
-
for (const y of x) {
|
1119
|
-
if (y.body) addBodyLines(y.body);
|
1120
|
-
if (y.else) addBodyLines(y.else);
|
1121
|
-
}
|
1122
|
-
};
|
1123
|
-
|
1124
|
-
for (let i = 0; i < parents.length; i++) {
|
1125
|
-
const x = parents[i];
|
1126
|
-
currentLine += x.pc;
|
1127
|
-
|
1128
|
-
for (let j = 0; j < x.pc - 1; j++) {
|
1129
|
-
if (x.body[j].body) addBodyLines(x.body[j].body);
|
1130
|
-
if (x.body[j].else) addBodyLines(x.body[j].else);
|
1131
|
-
}
|
1132
|
-
}
|
1133
|
-
|
1134
|
-
let localsChanged = new Array(locals.length);
|
1135
|
-
if (lastDebugLocals) {
|
1136
|
-
localsChanged = locals.map((x, i) => x !== lastDebugLocals[i]);
|
1137
|
-
}
|
1138
|
-
|
1139
|
-
let globalsChanged = new Array(globals.length);
|
1140
|
-
if (lastDebugGlobals) {
|
1141
|
-
globalsChanged = globals.map((x, i) => x.value !== lastDebugGlobals[i]);
|
1142
|
-
}
|
1143
|
-
|
1144
|
-
const longestLocal = Math.max(0, ...Object.values(bc.porfFunc.invLocals).map((x, i) => \`\${x} (\${i})\`.length));
|
1145
|
-
const localsWidth = longestLocal + 2 + 8 + 1;
|
1146
|
-
|
1147
|
-
const longestGlobal = Math.max(0, ...globals.map((x, i) => \`\${x.porfGlobalName} (\${i})\`.length));
|
1148
|
-
const globalsWidth = longestGlobal + 2 + 8 + 1;
|
1149
|
-
|
1150
|
-
const width = Math.max(localsWidth, globalsWidth);
|
1151
|
-
|
1152
|
-
// const longestStack = Math.max(5, ...stack.map(x => (+x).toString().length));
|
1153
|
-
// const stackWidth = longestStack + 2;
|
1154
|
-
|
1155
|
-
switch (byg(
|
1156
|
-
paused,
|
1157
|
-
funcLines[currentFunc] + currentLine,
|
1158
|
-
'\x1b[1masur debugger\x1b[22m: ' + callStack.join(' -> ') + (parents.length > 1 ? \` | \${parents.slice(1).map(x => invOpcodes[x.opcode]).join(' -> ')}\` : ''),
|
1159
|
-
[
|
1160
|
-
{
|
1161
|
-
x: termWidth - 1 - width - 6,
|
1162
|
-
y: () => termHeight - Math.max(1, locals.length) - 1 - 4 - 3 - Math.max(1, stack.length) - (globals.length > 0 ? (globals.length + 4) : 0),
|
1163
|
-
width,
|
1164
|
-
height: Math.max(1, stack.length),
|
1165
|
-
title: 'stack',
|
1166
|
-
content: stack.map((x, i) => {
|
1167
|
-
const str = (+x).toString();
|
1168
|
-
return \`\\x1b[93m\${' '.repeat((width - str.length) / 2 | 0)}\${str}\`;
|
1169
|
-
})
|
1170
|
-
},
|
1171
|
-
{
|
1172
|
-
x: termWidth - 1 - width - 6,
|
1173
|
-
// x: termWidth / 3 | 0,
|
1174
|
-
y: () => termHeight - Math.max(1, locals.length) - 1 - 4 - (globals.length > 0 ? (globals.length + 4) : 0),
|
1175
|
-
// y: ({ currentLinePos }) => currentLinePos + locals.length + 4 > termHeight ? currentLinePos - locals.length - 2 : currentLinePos + 1,
|
1176
|
-
width,
|
1177
|
-
height: Math.max(1, locals.length),
|
1178
|
-
title: 'locals',
|
1179
|
-
content: locals.map((x, i) => {
|
1180
|
-
const changed = localsChanged[i];
|
1181
|
-
const valueLen = changed ? \`\${lastDebugLocals[i]} -> \${x}\`.length : x.toString().length;
|
1182
|
-
if (changed) x = \`\\x1b[30m\${lastDebugLocals[i]}\\x1b[90m -> \\x1b[31m\${x}\`;
|
1183
|
-
return \`\${changed ? '\\x1b[107m\\x1b[30m' : '\\x1b[100m\\x1b[37m\\x1b[1m'}\${bc.porfFunc.invLocals[i]}\${changed ? '\\x1b[90m' : '\\x1b[22m'} (\${i}) \${' '.repeat((width - 2 - 8 - 1 - \`\${bc.porfFunc.invLocals[i]} (\${i})\`.length) + 2 + (8 - valueLen))}\${changed ? '' : '\\x1b[93m'}\${x}\`;
|
1184
|
-
})
|
1185
|
-
},
|
1186
|
-
...(globals.length > 0 ? [{
|
1187
|
-
x: termWidth - 1 - width - 6,
|
1188
|
-
// x: termWidth / 3 | 0,
|
1189
|
-
y: () => termHeight - globals.length - 1 - 4,
|
1190
|
-
width,
|
1191
|
-
height: globals.length,
|
1192
|
-
title: 'globals',
|
1193
|
-
content: globals.map((x, i) => {
|
1194
|
-
if (x.value == null) {
|
1195
|
-
x.value = run(x.bc, [], false)[0];
|
1196
|
-
}
|
1197
|
-
|
1198
|
-
const changed = globalsChanged[i];
|
1199
|
-
const valueLen = changed ? \`\${lastDebugGlobals[i]} -> \${x.value}\`.length : x.value.toString().length;
|
1200
|
-
let display = x.value;
|
1201
|
-
if (changed) display = \`\\x1b[30m\${lastDebugGlobals[i]}\\x1b[90m -> \\x1b[31m\${x.value}\`;
|
1202
|
-
return \`\${changed ? '\\x1b[107m\\x1b[30m' : '\\x1b[100m\\x1b[37m\\x1b[1m'}\${x.porfGlobalName}\${changed ? '\\x1b[90m' : '\\x1b[22m'} (\${i}) \${' '.repeat((width - 2 - 8 - 1 - \`\${x.porfGlobalName} (\${i})\`.length) + 2 + (8 - valueLen))}\${changed ? '' : '\\x1b[93m'}\${display}\`;
|
1203
|
-
})
|
1204
|
-
}] : [])
|
1205
|
-
]
|
1206
|
-
)) {
|
1207
|
-
case 'resume': {
|
1208
|
-
paused = false;
|
1209
|
-
break;
|
1210
|
-
}
|
1211
|
-
|
1212
|
-
case 'stepOver': {
|
1213
|
-
break;
|
1214
|
-
}
|
1215
|
-
|
1216
|
-
case 'stepIn': {
|
1217
|
-
stepIn = true;
|
1218
|
-
// paused = false;
|
1219
|
-
break;
|
1220
|
-
}
|
1221
|
-
|
1222
|
-
case 'stepOut': {
|
1223
|
-
stepOut = true;
|
1224
|
-
paused = false;
|
1225
|
-
break;
|
1226
|
-
}
|
1227
|
-
}
|
1228
|
-
|
1229
|
-
lastDebugLocals = locals.slice();
|
1230
|
-
lastDebugGlobals = globals.map(x => x.value).slice();
|
1231
|
-
}`);
|
1232
|
-
|
1233
|
-
str = str.replace('const outStack = run(callBC, locals);', `
|
1234
|
-
const _paused = paused;
|
1235
|
-
if (!stepIn) paused = false;
|
1236
|
-
else paused = true;
|
1237
|
-
|
1238
|
-
const outStack = run(callBC, locals);
|
1239
|
-
|
1240
|
-
paused = _paused;`);
|
1241
|
-
|
1242
|
-
// (await import('fs')).writeFileSync('t.js', str);
|
1243
|
-
return _wasmDebugVm = eval(str);
|
1244
|
-
});
|
1245
|
-
|
1246
|
-
export const instantiate = async (binary, importImpls) => {
|
1247
|
-
const _vm = process?.argv?.includes('--wasm-debug') ? await wasmDebugVm() : vm;
|
1248
|
-
|
1249
|
-
const parsed = parse(binary);
|
1250
|
-
const exports = {};
|
1251
|
-
for (const { name, type, index } of parsed.exports) {
|
1252
|
-
if (type === 0x00) exports[name] = _vm(parsed, importImpls, index);
|
1253
|
-
}
|
1254
|
-
|
1255
|
-
// console.log(parsed);
|
1256
|
-
|
1257
|
-
return {
|
1258
|
-
instance: {
|
1259
|
-
exports
|
1260
|
-
}
|
1261
|
-
};
|
1262
|
-
};
|