porffor 0.58.1 → 0.58.3

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/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
- };