porffor 0.14.0-f67c123a1 → 0.16.0-08983b6b1

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.
Files changed (45) hide show
  1. package/CONTRIBUTING.md +16 -10
  2. package/README.md +14 -30
  3. package/asur/index.js +1 -1
  4. package/compiler/2c.js +172 -59
  5. package/compiler/allocators.js +128 -0
  6. package/compiler/assemble.js +37 -5
  7. package/compiler/builtins/annexb_string.ts +1 -0
  8. package/compiler/builtins/array.ts +154 -7
  9. package/compiler/builtins/base64.ts +1 -0
  10. package/compiler/builtins/boolean.ts +3 -1
  11. package/compiler/builtins/console.ts +6 -0
  12. package/compiler/builtins/crypto.ts +1 -0
  13. package/compiler/builtins/date.ts +5 -30
  14. package/compiler/builtins/error.js +22 -0
  15. package/compiler/builtins/escape.ts +1 -2
  16. package/compiler/builtins/function.ts +2 -0
  17. package/compiler/builtins/int.ts +2 -0
  18. package/compiler/builtins/math.ts +410 -0
  19. package/compiler/builtins/number.ts +12 -21
  20. package/compiler/builtins/object.ts +2 -0
  21. package/compiler/builtins/porffor.d.ts +18 -0
  22. package/compiler/builtins/set.ts +22 -12
  23. package/compiler/builtins/string.ts +1 -0
  24. package/compiler/builtins/string_f64.ts +10 -0
  25. package/compiler/builtins/symbol.ts +62 -0
  26. package/compiler/builtins/z_ecma262.ts +62 -0
  27. package/compiler/builtins.js +50 -12
  28. package/compiler/codegen.js +826 -552
  29. package/compiler/cyclone.js +535 -0
  30. package/compiler/decompile.js +7 -1
  31. package/compiler/generated_builtins.js +635 -84
  32. package/compiler/havoc.js +93 -0
  33. package/compiler/index.js +108 -15
  34. package/compiler/opt.js +10 -44
  35. package/compiler/parse.js +3 -9
  36. package/compiler/pgo.js +212 -0
  37. package/compiler/precompile.js +17 -11
  38. package/compiler/prefs.js +13 -5
  39. package/compiler/prototype.js +200 -186
  40. package/compiler/wasmSpec.js +2 -2
  41. package/compiler/wrap.js +128 -44
  42. package/package.json +3 -5
  43. package/runner/index.js +31 -15
  44. package/runner/repl.js +18 -2
  45. /package/runner/{profiler.js → profile.js} +0 -0
@@ -1,6 +1,5 @@
1
1
  import { Opcodes, Blocktype, Valtype, ValtypeSize } from './wasmSpec.js';
2
2
  import { number } from './embedding.js';
3
- import { unsignedLEB128 } from './encoding.js';
4
3
  import { UNDEFINED } from './builtins.js';
5
4
  import { TYPES } from './types.js';
6
5
  import Prefs from './prefs.js';
@@ -16,7 +15,7 @@ export const PrototypeFuncs = function() {
16
15
 
17
16
  this[TYPES.array] = {
18
17
  // lX = local accessor of X ({ get, set }), iX = local index of X, wX = wasm ops of X
19
- at: (pointer, length, wIndex, iTmp) => [
18
+ at: (pointer, length, wIndex, wType, iTmp) => [
20
19
  ...wIndex,
21
20
  Opcodes.i32_to,
22
21
  [ Opcodes.local_tee, iTmp ],
@@ -47,31 +46,39 @@ export const PrototypeFuncs = function() {
47
46
  [ Opcodes.end ],
48
47
 
49
48
  [ Opcodes.local_get, iTmp ],
50
- ...number(ValtypeSize[valtype], Valtype.i32),
49
+ ...number(ValtypeSize[valtype] + 1, Valtype.i32),
51
50
  [ Opcodes.i32_mul ],
52
-
53
51
  ...pointer,
54
52
  [ Opcodes.i32_add ],
53
+ [ Opcodes.local_set, iTmp ],
55
54
 
56
55
  // read from memory
57
- [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
56
+ [ Opcodes.local_get, iTmp ],
57
+ [ Opcodes.load, 0, ValtypeSize.i32 ],
58
+
59
+ [ Opcodes.local_get, iTmp ],
60
+ [ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
58
61
  ],
59
62
 
60
63
  // todo: only for 1 argument
61
- push: (pointer, length, wNewMember, _1, _2, _3, unusedValue) => [
64
+ push: (pointer, length, wNewMember, wType, iTmp, _2, _3, unusedValue) => [
62
65
  // get memory offset of array at last index (length)
63
66
  ...length.getCachedI32(),
64
- ...number(ValtypeSize[valtype], Valtype.i32),
67
+ ...number(ValtypeSize[valtype] + 1, Valtype.i32),
65
68
  [ Opcodes.i32_mul ],
66
-
67
69
  ...pointer,
68
70
  [ Opcodes.i32_add ],
71
+ [ Opcodes.local_set, iTmp ],
69
72
 
70
- // generated wasm for new member
73
+ // store value
74
+ [ Opcodes.local_get, iTmp ],
71
75
  ...wNewMember,
76
+ [ Opcodes.store, 0, ValtypeSize.i32 ],
72
77
 
73
- // store in memory
74
- [ Opcodes.store, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
78
+ // store type
79
+ [ Opcodes.local_get, iTmp ],
80
+ ...wType,
81
+ [ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
75
82
 
76
83
  // bump array length by 1 and return it
77
84
  ...length.setI32([
@@ -93,7 +100,7 @@ export const PrototypeFuncs = function() {
93
100
  // ...length.get()
94
101
  ],
95
102
 
96
- pop: (pointer, length, _1, _2, _3, _4, unusedValue) => [
103
+ pop: (pointer, length, _1, _2, iTmp, _3, _4, unusedValue) => [
97
104
  // if length == 0, noop
98
105
  ...length.getCachedI32(),
99
106
  [ Opcodes.i32_eqz ],
@@ -121,13 +128,18 @@ export const PrototypeFuncs = function() {
121
128
  // load last element
122
129
  ...(unusedValue() ? [] : [
123
130
  ...length.getCachedI32(),
124
- ...number(ValtypeSize[valtype], Valtype.i32),
131
+ ...number(ValtypeSize[valtype] + 1, Valtype.i32),
125
132
  [ Opcodes.i32_mul ],
126
133
 
127
134
  ...pointer,
128
135
  [ Opcodes.i32_add ],
136
+ [ Opcodes.local_set, iTmp ],
129
137
 
130
- [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
138
+ [ Opcodes.local_get, iTmp ],
139
+ [ Opcodes.load, 0, ValtypeSize.i32 ],
140
+
141
+ [ Opcodes.local_get, iTmp ],
142
+ [ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
131
143
  ])
132
144
  ],
133
145
 
@@ -153,8 +165,12 @@ export const PrototypeFuncs = function() {
153
165
  ]),
154
166
 
155
167
  // load first element
168
+ // todo/perf: unusedValue opt
156
169
  ...pointer,
157
- [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
170
+ [ Opcodes.load, 0, ValtypeSize.i32 ],
171
+
172
+ ...pointer,
173
+ [ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
158
174
 
159
175
  // offset page by -1 ind
160
176
  // ...number(pointer + ValtypeSize.i32, Valtype.i32), // dst = base array index + length size
@@ -170,13 +186,13 @@ export const PrototypeFuncs = function() {
170
186
  [ Opcodes.i32_add ],
171
187
 
172
188
  // src = base array index + length size + an index
173
- ...number(ValtypeSize.i32 + ValtypeSize[valtype], Valtype.i32),
189
+ ...number(ValtypeSize.i32 + ValtypeSize[valtype] + 1, Valtype.i32),
174
190
  ...pointer,
175
191
  [ Opcodes.i32_add ],
176
192
 
177
193
  // size = new length * sizeof element
178
194
  ...length.getCachedI32(),
179
- ...number(ValtypeSize[valtype], Valtype.i32),
195
+ ...number(ValtypeSize[valtype] + 1, Valtype.i32),
180
196
  [ Opcodes.i32_mul ],
181
197
  [ ...Opcodes.memory_copy, 0x00, 0x00 ]
182
198
 
@@ -194,7 +210,7 @@ export const PrototypeFuncs = function() {
194
210
  // ]),
195
211
  ],
196
212
 
197
- fill: (pointer, length, wElement, iTmp) => [
213
+ fill: (pointer, length, wElement, wType, iTmp, iTmp2) => [
198
214
  ...wElement,
199
215
  [ Opcodes.local_set, iTmp ],
200
216
 
@@ -206,7 +222,7 @@ export const PrototypeFuncs = function() {
206
222
  [ Opcodes.i32_sub ],
207
223
 
208
224
  // * sizeof value
209
- ...number(ValtypeSize[valtype], Valtype.i32),
225
+ ...number(ValtypeSize[valtype] + 1, Valtype.i32),
210
226
  [ Opcodes.i32_mul ],
211
227
 
212
228
  ...length.setCachedI32(),
@@ -224,17 +240,25 @@ export const PrototypeFuncs = function() {
224
240
 
225
241
  [ Opcodes.loop, Blocktype.void ],
226
242
 
227
- // set element using pointer
243
+ // calculate offset
228
244
  ...length.getCachedI32(),
229
245
  ...pointer,
230
246
  [ Opcodes.i32_add ],
247
+ [ Opcodes.local_set, iTmp2 ],
231
248
 
249
+ // store value
250
+ [ Opcodes.local_get, iTmp2 ],
232
251
  [ Opcodes.local_get, iTmp ],
233
- [ Opcodes.store, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128( ValtypeSize.i32) ],
252
+ [ Opcodes.store, 0, ValtypeSize.i32 ],
253
+
254
+ // store type
255
+ [ Opcodes.local_get, iTmp2 ],
256
+ ...wType,
257
+ [ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
234
258
 
235
259
  // pointer - sizeof value
236
260
  ...length.getCachedI32(),
237
- ...number(ValtypeSize[valtype], Valtype.i32),
261
+ ...number(ValtypeSize[valtype] + 1, Valtype.i32),
238
262
  [ Opcodes.i32_sub ],
239
263
 
240
264
  ...length.setCachedI32(),
@@ -254,20 +278,21 @@ export const PrototypeFuncs = function() {
254
278
  };
255
279
 
256
280
  this[TYPES.array].at.local = Valtype.i32;
281
+ this[TYPES.array].push.returnType = TYPES.number;
257
282
  this[TYPES.array].push.noArgRetLength = true;
283
+ this[TYPES.array].push.local = Valtype.i32;
284
+ this[TYPES.array].pop.local = Valtype.i32;
258
285
  this[TYPES.array].fill.local = valtypeBinary;
286
+ this[TYPES.array].fill.local2 = Valtype.i32;
259
287
  this[TYPES.array].fill.returnType = TYPES.array;
260
288
 
261
289
  this[TYPES.string] = {
262
- at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
290
+ at: (pointer, length, wIndex, wType, iTmp, _, arrayShell) => {
263
291
  const [ newOut, newPointer ] = arrayShell(1, 'i16');
264
292
 
265
293
  return [
266
- // setup new/out array
294
+ // setup new/out array and use pointer for store
267
295
  ...newOut,
268
- [ Opcodes.drop ],
269
-
270
- ...number(0, Valtype.i32), // base 0 for store later
271
296
 
272
297
  ...wIndex,
273
298
  Opcodes.i32_to_u,
@@ -306,26 +331,24 @@ export const PrototypeFuncs = function() {
306
331
  [ Opcodes.i32_add ],
307
332
 
308
333
  // load current string ind {arg}
309
- [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
334
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
310
335
 
311
336
  // store to new string ind 0
312
- [ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
337
+ [ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
313
338
 
314
339
  // return new string (pointer)
315
- ...number(newPointer)
340
+ ...newPointer,
341
+ Opcodes.i32_from_u
316
342
  ];
317
343
  },
318
344
 
319
345
  // todo: out of bounds properly
320
- charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
346
+ charAt: (pointer, length, wIndex, wType, _1, _2, arrayShell) => {
321
347
  const [ newOut, newPointer ] = arrayShell(1, 'i16');
322
348
 
323
349
  return [
324
- // setup new/out array
350
+ // setup new/out array and use as pointer for store
325
351
  ...newOut,
326
- [ Opcodes.drop ],
327
-
328
- ...number(0, Valtype.i32), // base 0 for store later
329
352
 
330
353
  ...wIndex,
331
354
  Opcodes.i32_to,
@@ -337,137 +360,135 @@ export const PrototypeFuncs = function() {
337
360
  [ Opcodes.i32_add ],
338
361
 
339
362
  // load current string ind {arg}
340
- [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
363
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
341
364
 
342
365
  // store to new string ind 0
343
- [ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
366
+ [ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
344
367
 
345
368
  // return new string (page)
346
- ...number(newPointer)
369
+ ...newPointer,
370
+ Opcodes.i32_from_u
347
371
  ];
348
372
  },
349
373
 
350
- charCodeAt: (pointer, length, wIndex, iTmp) => {
351
- return [
352
- ...wIndex,
353
- Opcodes.i32_to,
354
-
355
- ...(zeroChecks.charcodeat ? [] : [
356
- [ Opcodes.local_set, iTmp ],
374
+ charCodeAt: (pointer, length, wIndex, wType, iTmp) => [
375
+ ...wIndex,
376
+ Opcodes.i32_to,
357
377
 
358
- // index < 0
359
- ...(noUnlikelyChecks ? [] : [
360
- [ Opcodes.local_get, iTmp ],
361
- ...number(0, Valtype.i32),
362
- [ Opcodes.i32_lt_s ],
363
- ]),
378
+ ...(zeroChecks.charcodeat ? [] : [
379
+ [ Opcodes.local_set, iTmp ],
364
380
 
365
- // index >= length
381
+ // index < 0
382
+ ...(noUnlikelyChecks ? [] : [
366
383
  [ Opcodes.local_get, iTmp ],
367
- ...length.getCachedI32(),
368
- [ Opcodes.i32_ge_s ],
384
+ ...number(0, Valtype.i32),
385
+ [ Opcodes.i32_lt_s ],
386
+ ]),
369
387
 
370
- ...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
371
- [ Opcodes.if, Blocktype.void ],
372
- ...number(valtype === 'i32' ? -1 : NaN),
373
- [ Opcodes.br, 1 ],
374
- [ Opcodes.end ],
388
+ // index >= length
389
+ [ Opcodes.local_get, iTmp ],
390
+ ...length.getCachedI32(),
391
+ [ Opcodes.i32_ge_s ],
375
392
 
376
- [ Opcodes.local_get, iTmp ],
377
- ]),
393
+ ...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
394
+ [ Opcodes.if, Blocktype.void ],
395
+ ...number(valtype === 'i32' ? -1 : NaN),
396
+ [ Opcodes.br, 1 ],
397
+ [ Opcodes.end ],
378
398
 
379
- ...number(ValtypeSize.i16, Valtype.i32),
380
- [ Opcodes.i32_mul ],
399
+ [ Opcodes.local_get, iTmp ],
400
+ ]),
381
401
 
382
- ...pointer,
383
- [ Opcodes.i32_add ],
402
+ ...number(ValtypeSize.i16, Valtype.i32),
403
+ [ Opcodes.i32_mul ],
384
404
 
385
- // load current string ind {arg}
386
- [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
387
- Opcodes.i32_from_u
388
- ];
389
- },
405
+ ...pointer,
406
+ [ Opcodes.i32_add ],
390
407
 
391
- isWellFormed: (pointer, length, wIndex, iTmp, iTmp2) => {
392
- return [
393
- // note: we cannot presume it begins as 0 in case it was used previously
394
- ...pointer,
395
- [ Opcodes.local_set, iTmp ],
408
+ // load current string ind {arg}
409
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
410
+ Opcodes.i32_from_u
411
+ ],
396
412
 
397
- // use cached length as end pointer
398
- ...length.getCachedI32(),
399
- ...number(ValtypeSize.i16, Valtype.i32),
400
- [ Opcodes.i32_mul ],
401
- ...pointer,
402
- [ Opcodes.i32_add ],
403
- ...length.setCachedI32(),
413
+ isWellFormed: (pointer, length, _1, _2, iTmp, iTmp2) => [
414
+ // note: we cannot presume it begins as 0 in case it was used previously
415
+ ...pointer,
416
+ [ Opcodes.local_set, iTmp ],
417
+
418
+ // use cached length as end pointer
419
+ ...length.getCachedI32(),
420
+ ...number(ValtypeSize.i16, Valtype.i32),
421
+ [ Opcodes.i32_mul ],
422
+ ...pointer,
423
+ [ Opcodes.i32_add ],
424
+ ...length.setCachedI32(),
404
425
 
405
- [ Opcodes.loop, Blocktype.void ],
426
+ [ Opcodes.loop, Blocktype.void ],
406
427
 
407
- [ Opcodes.block, Blocktype.void ],
428
+ [ Opcodes.block, Blocktype.void ],
408
429
 
409
- [ Opcodes.local_get, iTmp ],
410
- [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
411
- [ Opcodes.local_set, iTmp2 ],
412
-
413
- // if not surrogate, continue
414
- [ Opcodes.local_get, iTmp2 ],
415
- ...number(0xF800, Valtype.i32),
416
- [ Opcodes.i32_and ],
417
- ...number(0xD800, Valtype.i32),
418
- [ Opcodes.i32_ne ],
419
- [ Opcodes.br_if, 0 ],
420
-
421
- // if not leading surrogate, return false
422
- [ Opcodes.local_get, iTmp2 ],
423
- ...number(0xDC00, Valtype.i32),
424
- [ Opcodes.i32_ge_s ],
425
- [ Opcodes.if, Blocktype.void ],
426
- ...number(0),
427
- [ Opcodes.br, 3 ],
428
- [ Opcodes.end ],
430
+ [ Opcodes.local_get, iTmp ],
431
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
432
+ [ Opcodes.local_set, iTmp2 ],
433
+
434
+ // if not surrogate, continue
435
+ [ Opcodes.local_get, iTmp2 ],
436
+ ...number(0xF800, Valtype.i32),
437
+ [ Opcodes.i32_and ],
438
+ ...number(0xD800, Valtype.i32),
439
+ [ Opcodes.i32_ne ],
440
+ [ Opcodes.br_if, 0 ],
429
441
 
430
- // if not followed by trailing surrogate, return false
431
- [ Opcodes.local_get, iTmp ],
432
- [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32 + ValtypeSize.i16) ],
433
- ...number(0xFC00, Valtype.i32),
434
- [ Opcodes.i32_and ],
435
- ...number(0xDC00, Valtype.i32),
436
- [ Opcodes.i32_ne ],
437
- [ Opcodes.if, Blocktype.void ],
438
- ...number(0),
439
- [ Opcodes.br, 3 ],
440
- [ Opcodes.end ],
442
+ // if not leading surrogate, return false
443
+ [ Opcodes.local_get, iTmp2 ],
444
+ ...number(0xDC00, Valtype.i32),
445
+ [ Opcodes.i32_ge_s ],
446
+ [ Opcodes.if, Blocktype.void ],
447
+ ...number(0),
448
+ [ Opcodes.br, 3 ],
449
+ [ Opcodes.end ],
441
450
 
442
- // bump index again since gone through two valid chars
443
- [ Opcodes.local_get, iTmp ],
444
- ...number(ValtypeSize.i16, Valtype.i32),
445
- [ Opcodes.i32_add ],
446
- [ Opcodes.local_set, iTmp ],
451
+ // if not followed by trailing surrogate, return false
452
+ [ Opcodes.local_get, iTmp ],
453
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 + ValtypeSize.i16 ],
454
+ ...number(0xFC00, Valtype.i32),
455
+ [ Opcodes.i32_and ],
456
+ ...number(0xDC00, Valtype.i32),
457
+ [ Opcodes.i32_ne ],
458
+ [ Opcodes.if, Blocktype.void ],
459
+ ...number(0),
460
+ [ Opcodes.br, 3 ],
461
+ [ Opcodes.end ],
447
462
 
448
- [ Opcodes.end ],
463
+ // bump index again since gone through two valid chars
464
+ [ Opcodes.local_get, iTmp ],
465
+ ...number(ValtypeSize.i16, Valtype.i32),
466
+ [ Opcodes.i32_add ],
467
+ [ Opcodes.local_set, iTmp ],
449
468
 
450
- // bump pointer and loop if not at the end
451
- [ Opcodes.local_get, iTmp ],
452
- ...number(ValtypeSize.i16, Valtype.i32),
453
- [ Opcodes.i32_add ],
454
- [ Opcodes.local_tee, iTmp ],
469
+ [ Opcodes.end ],
455
470
 
456
- ...length.getCachedI32(), // end pointer
457
- [ Opcodes.i32_ne ],
458
- [ Opcodes.br_if, 0 ],
471
+ // bump pointer and loop if not at the end
472
+ [ Opcodes.local_get, iTmp ],
473
+ ...number(ValtypeSize.i16, Valtype.i32),
474
+ [ Opcodes.i32_add ],
475
+ [ Opcodes.local_tee, iTmp ],
459
476
 
460
- [ Opcodes.end ],
477
+ ...length.getCachedI32(), // end pointer
478
+ [ Opcodes.i32_ne ],
479
+ [ Opcodes.br_if, 0 ],
461
480
 
462
- // return true
463
- ...number(1)
464
- ]
465
- }
481
+ [ Opcodes.end ],
482
+
483
+ // return true
484
+ ...number(1)
485
+ ]
466
486
  };
467
487
 
468
488
  this[TYPES.string].at.local = Valtype.i32;
469
489
  this[TYPES.string].at.returnType = TYPES.string;
470
490
  this[TYPES.string].charAt.returnType = TYPES.string;
491
+ this[TYPES.string].charCodeAt.returnType = TYPES.number;
471
492
  this[TYPES.string].charCodeAt.local = Valtype.i32;
472
493
  this[TYPES.string].charCodeAt.noPointerCache = zeroChecks.charcodeat;
473
494
 
@@ -477,15 +498,12 @@ export const PrototypeFuncs = function() {
477
498
 
478
499
  if (Prefs.bytestring) {
479
500
  this[TYPES.bytestring] = {
480
- at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
501
+ at: (pointer, length, wIndex, wType, iTmp, _, arrayShell) => {
481
502
  const [ newOut, newPointer ] = arrayShell(1, 'i8');
482
503
 
483
504
  return [
484
- // setup new/out array
505
+ // setup new/out array and use pointer for store later
485
506
  ...newOut,
486
- [ Opcodes.drop ],
487
-
488
- ...number(0, Valtype.i32), // base 0 for store later
489
507
 
490
508
  ...wIndex,
491
509
  Opcodes.i32_to_u,
@@ -522,26 +540,24 @@ export const PrototypeFuncs = function() {
522
540
  [ Opcodes.i32_add ],
523
541
 
524
542
  // load current string ind {arg}
525
- [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
543
+ [ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
526
544
 
527
545
  // store to new string ind 0
528
- [ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
546
+ [ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
529
547
 
530
548
  // return new string (pointer)
531
- ...number(newPointer)
549
+ ...newPointer,
550
+ Opcodes.i32_from_u
532
551
  ];
533
552
  },
534
553
 
535
554
  // todo: out of bounds properly
536
- charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
555
+ charAt: (pointer, length, wIndex, wType, _1, _2, arrayShell) => {
537
556
  const [ newOut, newPointer ] = arrayShell(1, 'i8');
538
557
 
539
558
  return [
540
- // setup new/out array
559
+ // setup new/out array and use pointer for later
541
560
  ...newOut,
542
- [ Opcodes.drop ],
543
-
544
- ...number(0, Valtype.i32), // base 0 for store later
545
561
 
546
562
  ...wIndex,
547
563
  Opcodes.i32_to,
@@ -550,65 +566,63 @@ export const PrototypeFuncs = function() {
550
566
  [ Opcodes.i32_add ],
551
567
 
552
568
  // load current string ind {arg}
553
- [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
569
+ [ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
554
570
 
555
571
  // store to new string ind 0
556
- [ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
572
+ [ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
557
573
 
558
574
  // return new string (page)
559
- ...number(newPointer)
575
+ ...newPointer,
576
+ Opcodes.i32_from_u
560
577
  ];
561
578
  },
562
579
 
563
- charCodeAt: (pointer, length, wIndex, iTmp) => {
564
- return [
565
- ...wIndex,
566
- Opcodes.i32_to,
567
-
568
- ...(zeroChecks.charcodeat ? [] : [
569
- [ Opcodes.local_set, iTmp ],
580
+ charCodeAt: (pointer, length, wIndex, wType, iTmp) => [
581
+ ...wIndex,
582
+ Opcodes.i32_to,
570
583
 
571
- // index < 0
572
- ...(noUnlikelyChecks ? [] : [
573
- [ Opcodes.local_get, iTmp ],
574
- ...number(0, Valtype.i32),
575
- [ Opcodes.i32_lt_s ],
576
- ]),
584
+ ...(zeroChecks.charcodeat ? [] : [
585
+ [ Opcodes.local_set, iTmp ],
577
586
 
578
- // index >= length
587
+ // index < 0
588
+ ...(noUnlikelyChecks ? [] : [
579
589
  [ Opcodes.local_get, iTmp ],
580
- ...length.getCachedI32(),
581
- [ Opcodes.i32_ge_s ],
590
+ ...number(0, Valtype.i32),
591
+ [ Opcodes.i32_lt_s ],
592
+ ]),
582
593
 
583
- ...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
584
- [ Opcodes.if, Blocktype.void ],
585
- ...number(valtype === 'i32' ? -1 : NaN),
586
- [ Opcodes.br, 1 ],
587
- [ Opcodes.end ],
594
+ // index >= length
595
+ [ Opcodes.local_get, iTmp ],
596
+ ...length.getCachedI32(),
597
+ [ Opcodes.i32_ge_s ],
588
598
 
589
- [ Opcodes.local_get, iTmp ],
590
- ]),
599
+ ...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
600
+ [ Opcodes.if, Blocktype.void ],
601
+ ...number(valtype === 'i32' ? -1 : NaN),
602
+ [ Opcodes.br, 1 ],
603
+ [ Opcodes.end ],
591
604
 
592
- ...pointer,
593
- [ Opcodes.i32_add ],
605
+ [ Opcodes.local_get, iTmp ],
606
+ ]),
594
607
 
595
- // load current string ind {arg}
596
- [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
597
- Opcodes.i32_from_u
598
- ];
599
- },
608
+ ...pointer,
609
+ [ Opcodes.i32_add ],
600
610
 
601
- isWellFormed: () => {
602
- return [
603
- // we know it must be true as it is a bytestring lol
604
- ...number(1)
605
- ]
606
- }
611
+ // load current string ind {arg}
612
+ [ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
613
+ Opcodes.i32_from_u
614
+ ],
615
+
616
+ isWellFormed: () => [
617
+ // we know it must be true as it is a bytestring lol
618
+ ...number(1)
619
+ ]
607
620
  };
608
621
 
609
622
  this[TYPES.bytestring].at.local = Valtype.i32;
610
623
  this[TYPES.bytestring].at.returnType = TYPES.bytestring;
611
624
  this[TYPES.bytestring].charAt.returnType = TYPES.bytestring;
625
+ this[TYPES.bytestring].charCodeAt.returnType = TYPES.number;
612
626
  this[TYPES.bytestring].charCodeAt.local = Valtype.i32;
613
627
  this[TYPES.bytestring].charCodeAt.noPointerCache = zeroChecks.charcodeat;
614
628
 
@@ -191,6 +191,8 @@ export const Opcodes = {
191
191
  i32_trunc_sat_f64_s: [ 0xfc, 0x02 ],
192
192
  i32_trunc_sat_f64_u: [ 0xfc, 0x03 ],
193
193
 
194
+ memory_init: [ 0xfc, 0x08 ],
195
+ data_drop: [ 0xfc, 0x09 ],
194
196
  memory_copy: [ 0xfc, 0x0a ],
195
197
 
196
198
  // simd insts are 0xFD simdop: varuint32
@@ -209,8 +211,6 @@ export const Opcodes = {
209
211
  i32x4_add: [ 0xfd, 0xae, 0x01 ],
210
212
  i32x4_sub: [ 0xfd, 0xb1, 0x01 ],
211
213
  i32x4_mul: [ 0xfd, 0xb5, 0x01 ],
212
-
213
- i32x4_dot_i16x8_s: [ 0xfd, 0xba, 0x01 ],
214
214
  };
215
215
 
216
216
  export const FuncType = 0x60;