porffor 0.16.0-1a6e16aae → 0.16.0-30af62694
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/CONTRIBUTING.md +1 -1
- package/compiler/codegen.js +162 -46
- package/compiler/cyclone.js +11 -11
- package/compiler/parse.js +1 -1
- package/compiler/precompile.js +1 -3
- package/compiler/prefs.js +1 -1
- package/compiler/wrap.js +1 -1
- package/package.json +4 -2
- package/runner/index.js +3 -8
- package/compiler/allocators/chunk.js +0 -0
- package/compiler/allocators/solo.js +0 -0
- package/compiler/allocators/static.js +0 -41
package/CONTRIBUTING.md
CHANGED
@@ -26,7 +26,7 @@ You can also swap out `node` in the alias to use another runtime like Deno (`den
|
|
26
26
|
|
27
27
|
### Precompile
|
28
28
|
|
29
|
-
**If you update any file inside `compiler/builtins` you will need to do this for it to update inside Porffor otherwise your changes will have no effect.** Run
|
29
|
+
**If you update any file inside `compiler/builtins` you will need to do this for it to update inside Porffor otherwise your changes will have no effect.** Run `node compiler/precompile.js` to precompile. It may error during this, if so, you might have an error in your code or there could be a compiler error with Porffor (feel free to ask for help as soon as you encounter any errors with it).
|
30
30
|
|
31
31
|
<br>
|
32
32
|
|
package/compiler/codegen.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Blocktype, Opcodes, Valtype, ValtypeSize } from './wasmSpec.js';
|
1
|
+
import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from './wasmSpec.js';
|
2
2
|
import { ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector } from './encoding.js';
|
3
3
|
import { operatorOpcode } from './expression.js';
|
4
4
|
import { BuiltinFuncs, BuiltinVars, importedFuncs, NULL, UNDEFINED } from './builtins.js';
|
@@ -181,6 +181,12 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
181
181
|
continue;
|
182
182
|
}
|
183
183
|
|
184
|
+
if (asm[0] === 'memory') {
|
185
|
+
allocPage(scope, 'asm instrinsic');
|
186
|
+
// todo: add to store/load offset insts
|
187
|
+
continue;
|
188
|
+
}
|
189
|
+
|
184
190
|
let inst = Opcodes[asm[0].replace('.', '_')];
|
185
191
|
if (inst == null) throw new Error(`inline asm: inst ${asm[0]} not found`);
|
186
192
|
|
@@ -427,6 +433,57 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
427
433
|
const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
|
428
434
|
const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
|
429
435
|
|
436
|
+
if (assign && Prefs.aotPointerOpt) {
|
437
|
+
const pointer = scope.arrays?.get(name ?? '$undeclared');
|
438
|
+
|
439
|
+
return [
|
440
|
+
// setup right
|
441
|
+
...right,
|
442
|
+
Opcodes.i32_to_u,
|
443
|
+
[ Opcodes.local_set, rightPointer ],
|
444
|
+
|
445
|
+
// calculate length
|
446
|
+
...number(0, Valtype.i32), // base 0 for store later
|
447
|
+
|
448
|
+
...number(pointer, Valtype.i32),
|
449
|
+
[ Opcodes.i32_load, 0, ...unsignedLEB128(0) ],
|
450
|
+
[ Opcodes.local_tee, leftLength ],
|
451
|
+
|
452
|
+
[ Opcodes.local_get, rightPointer ],
|
453
|
+
[ Opcodes.i32_load, 0, ...unsignedLEB128(0) ],
|
454
|
+
[ Opcodes.local_tee, rightLength ],
|
455
|
+
|
456
|
+
[ Opcodes.i32_add ],
|
457
|
+
|
458
|
+
// store length
|
459
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(pointer) ],
|
460
|
+
|
461
|
+
// copy right
|
462
|
+
// dst = out pointer + length size + current length * sizeof valtype
|
463
|
+
...number(pointer + ValtypeSize.i32, Valtype.i32),
|
464
|
+
|
465
|
+
[ Opcodes.local_get, leftLength ],
|
466
|
+
...number(bytestrings ? ValtypeSize.i8 : ValtypeSize.i16, Valtype.i32),
|
467
|
+
[ Opcodes.i32_mul ],
|
468
|
+
[ Opcodes.i32_add ],
|
469
|
+
|
470
|
+
// src = right pointer + length size
|
471
|
+
[ Opcodes.local_get, rightPointer ],
|
472
|
+
...number(ValtypeSize.i32, Valtype.i32),
|
473
|
+
[ Opcodes.i32_add ],
|
474
|
+
|
475
|
+
// size = right length * sizeof valtype
|
476
|
+
[ Opcodes.local_get, rightLength ],
|
477
|
+
...number(bytestrings ? ValtypeSize.i8 : ValtypeSize.i16, Valtype.i32),
|
478
|
+
[ Opcodes.i32_mul ],
|
479
|
+
|
480
|
+
[ ...Opcodes.memory_copy, 0x00, 0x00 ],
|
481
|
+
|
482
|
+
// return new string (page)
|
483
|
+
...number(pointer)
|
484
|
+
];
|
485
|
+
}
|
486
|
+
|
430
487
|
const leftPointer = localTmp(scope, 'concat_left_pointer', Valtype.i32);
|
431
488
|
|
432
489
|
// alloc/assign array
|
@@ -2058,6 +2115,7 @@ const brTable = (input, bc, returns) => {
|
|
2058
2115
|
}
|
2059
2116
|
|
2060
2117
|
for (let i = 0; i < count; i++) {
|
2118
|
+
// if (i === 0) out.push([ Opcodes.block, returns, 'br table start' ]);
|
2061
2119
|
if (i === 0) out.push([ Opcodes.block, returns ]);
|
2062
2120
|
else out.push([ Opcodes.block, Blocktype.void ]);
|
2063
2121
|
}
|
@@ -2091,8 +2149,10 @@ const brTable = (input, bc, returns) => {
|
|
2091
2149
|
[ Opcodes.br_table, ...encodeVector(table), 0 ]
|
2092
2150
|
);
|
2093
2151
|
|
2094
|
-
// sort the wrong way and then reverse
|
2095
|
-
//
|
2152
|
+
// if you can guess why we sort the wrong way and then reverse
|
2153
|
+
// (instead of just sorting the correct way)
|
2154
|
+
// dm me and if you are correct and the first person
|
2155
|
+
// I will somehow shout you out or something
|
2096
2156
|
const orderedBc = keys.sort((a, b) => b - a).reverse();
|
2097
2157
|
|
2098
2158
|
br = count - 1;
|
@@ -2118,7 +2178,7 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
|
2118
2178
|
return bc[known] ?? bc.default;
|
2119
2179
|
}
|
2120
2180
|
|
2121
|
-
if (Prefs.
|
2181
|
+
if (Prefs.typeswitchUseBrtable)
|
2122
2182
|
return brTable(type, bc, returns);
|
2123
2183
|
|
2124
2184
|
const tmp = localTmp(scope, '#typeswitch_tmp' + (Prefs.typeswitchUniqueTmp ? randId() : ''), Valtype.i32);
|
@@ -2339,12 +2399,19 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2339
2399
|
|
2340
2400
|
// hack: .length setter
|
2341
2401
|
if (decl.left.type === 'MemberExpression' && decl.left.property.name === 'length') {
|
2402
|
+
const name = decl.left.object.name;
|
2403
|
+
const pointer = scope.arrays?.get(name);
|
2404
|
+
|
2405
|
+
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2406
|
+
|
2342
2407
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
2343
2408
|
const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2344
2409
|
|
2345
2410
|
return [
|
2346
|
-
...
|
2347
|
-
|
2411
|
+
...(aotPointer ? number(0, Valtype.i32) : [
|
2412
|
+
...generate(scope, decl.left.object),
|
2413
|
+
Opcodes.i32_to_u
|
2414
|
+
]),
|
2348
2415
|
...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2349
2416
|
|
2350
2417
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
@@ -2355,7 +2422,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2355
2422
|
[ Opcodes.local_tee, newValueTmp ],
|
2356
2423
|
|
2357
2424
|
Opcodes.i32_to_u,
|
2358
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
2425
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
|
2359
2426
|
|
2360
2427
|
[ Opcodes.local_get, newValueTmp ]
|
2361
2428
|
];
|
@@ -2363,14 +2430,21 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2363
2430
|
|
2364
2431
|
// arr[i]
|
2365
2432
|
if (decl.left.type === 'MemberExpression' && decl.left.computed) {
|
2433
|
+
const name = decl.left.object.name;
|
2434
|
+
const pointer = scope.arrays?.get(name);
|
2435
|
+
|
2436
|
+
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2437
|
+
|
2366
2438
|
const newValueTmp = localTmp(scope, '__member_setter_val_tmp');
|
2367
2439
|
const pointerTmp = op === '=' ? -1 : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2368
2440
|
|
2369
2441
|
return [
|
2370
2442
|
...typeSwitch(scope, getNodeType(scope, decl.left.object), {
|
2371
2443
|
[TYPES.array]: [
|
2372
|
-
...
|
2373
|
-
|
2444
|
+
...(aotPointer ? [] : [
|
2445
|
+
...generate(scope, decl.left.object),
|
2446
|
+
Opcodes.i32_to_u
|
2447
|
+
]),
|
2374
2448
|
|
2375
2449
|
// get index as valtype
|
2376
2450
|
...generate(scope, decl.left.property),
|
@@ -2379,22 +2453,39 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2379
2453
|
// turn into byte offset by * valtypeSize (4 for i32, 8 for i64/f64)
|
2380
2454
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
2381
2455
|
[ Opcodes.i32_mul ],
|
2382
|
-
[ Opcodes.i32_add ],
|
2456
|
+
...(aotPointer ? [] : [ [ Opcodes.i32_add ] ]),
|
2383
2457
|
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2384
2458
|
|
2385
2459
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2386
2460
|
[ Opcodes.local_get, pointerTmp ],
|
2387
|
-
[ Opcodes.load, 0, ValtypeSize.i32 ]
|
2461
|
+
[ Opcodes.load, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2388
2462
|
], generate(scope, decl.right), [
|
2389
2463
|
[ Opcodes.local_get, pointerTmp ],
|
2390
|
-
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2464
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32 + ValtypeSize[valtype]) ]
|
2391
2465
|
], getNodeType(scope, decl.right), false, name, true)),
|
2392
2466
|
[ Opcodes.local_tee, newValueTmp ],
|
2393
2467
|
|
2394
|
-
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2468
|
+
[ Opcodes.store, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2395
2469
|
],
|
2396
2470
|
|
2397
2471
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2472
|
+
|
2473
|
+
// [TYPES.string]: [
|
2474
|
+
// // turn into byte offset by * sizeof i16
|
2475
|
+
// ...number(ValtypeSize.i16, Valtype.i32),
|
2476
|
+
// [ Opcodes.i32_mul ],
|
2477
|
+
// ...(aotPointer ? [] : [ [ Opcodes.i32_add ] ]),
|
2478
|
+
// ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2479
|
+
|
2480
|
+
// ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2481
|
+
// [ Opcodes.local_get, pointerTmp ],
|
2482
|
+
// [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2483
|
+
// ], generate(scope, decl.right), number(TYPES.string, Valtype.i32), getNodeType(scope, decl.right))),
|
2484
|
+
// [ Opcodes.local_tee, newValueTmp ],
|
2485
|
+
|
2486
|
+
// Opcodes.i32_to_u,
|
2487
|
+
// [ StoreOps.i16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2488
|
+
// ]
|
2398
2489
|
}, Blocktype.void),
|
2399
2490
|
|
2400
2491
|
[ Opcodes.local_get, newValueTmp ]
|
@@ -3116,6 +3207,16 @@ const allocPage = (scope, reason, type) => {
|
|
3116
3207
|
return ind;
|
3117
3208
|
};
|
3118
3209
|
|
3210
|
+
// todo: add scope.pages
|
3211
|
+
const freePage = reason => {
|
3212
|
+
const { ind } = pages.get(reason);
|
3213
|
+
pages.delete(reason);
|
3214
|
+
|
3215
|
+
if (Prefs.allocLog) log('alloc', `freed page of memory (${ind}) | ${reason}`);
|
3216
|
+
|
3217
|
+
return ind;
|
3218
|
+
};
|
3219
|
+
|
3119
3220
|
const itemTypeToValtype = {
|
3120
3221
|
i32: 'i32',
|
3121
3222
|
i64: 'i64',
|
@@ -3190,7 +3291,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3190
3291
|
const valtype = itemTypeToValtype[itemType];
|
3191
3292
|
const length = elements.length;
|
3192
3293
|
|
3193
|
-
if (
|
3294
|
+
if (firstAssign && useRawElements && !Prefs.noData) {
|
3194
3295
|
// if length is 0 memory/data will just be 0000... anyway
|
3195
3296
|
if (length !== 0) {
|
3196
3297
|
let bytes = compileBytes(length, 'i32');
|
@@ -3258,7 +3359,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3258
3359
|
return [ out, pointer ];
|
3259
3360
|
};
|
3260
3361
|
|
3261
|
-
const storeArray = (scope, array, index, element) => {
|
3362
|
+
const storeArray = (scope, array, index, element, aotPointer = null) => {
|
3262
3363
|
if (!Array.isArray(element)) element = generate(scope, element);
|
3263
3364
|
if (typeof index === 'number') index = number(index);
|
3264
3365
|
|
@@ -3270,25 +3371,26 @@ const storeArray = (scope, array, index, element) => {
|
|
3270
3371
|
Opcodes.i32_to_u,
|
3271
3372
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3272
3373
|
[ Opcodes.i32_mul ],
|
3273
|
-
|
3274
|
-
|
3275
|
-
|
3276
|
-
|
3374
|
+
...(aotPointer ? [] : [
|
3375
|
+
...array,
|
3376
|
+
Opcodes.i32_to_u,
|
3377
|
+
[ Opcodes.i32_add ],
|
3378
|
+
]),
|
3277
3379
|
[ Opcodes.local_set, offset ],
|
3278
3380
|
|
3279
3381
|
// store value
|
3280
3382
|
[ Opcodes.local_get, offset ],
|
3281
3383
|
...generate(scope, element),
|
3282
|
-
[ Opcodes.store, 0, ValtypeSize.i32 ],
|
3384
|
+
[ Opcodes.store, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ],
|
3283
3385
|
|
3284
3386
|
// store type
|
3285
3387
|
[ Opcodes.local_get, offset ],
|
3286
3388
|
...getNodeType(scope, element),
|
3287
|
-
[ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3389
|
+
[ Opcodes.i32_store8, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32 + ValtypeSize[valtype]) ]
|
3288
3390
|
];
|
3289
3391
|
};
|
3290
3392
|
|
3291
|
-
const loadArray = (scope, array, index) => {
|
3393
|
+
const loadArray = (scope, array, index, aotPointer = null) => {
|
3292
3394
|
if (typeof index === 'number') index = number(index);
|
3293
3395
|
|
3294
3396
|
const offset = localTmp(scope, '#loadArray_offset', Valtype.i32);
|
@@ -3299,19 +3401,20 @@ const loadArray = (scope, array, index) => {
|
|
3299
3401
|
Opcodes.i32_to_u,
|
3300
3402
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3301
3403
|
[ Opcodes.i32_mul ],
|
3302
|
-
|
3303
|
-
|
3304
|
-
|
3305
|
-
|
3404
|
+
...(aotPointer ? [] : [
|
3405
|
+
...array,
|
3406
|
+
Opcodes.i32_to_u,
|
3407
|
+
[ Opcodes.i32_add ],
|
3408
|
+
]),
|
3306
3409
|
[ Opcodes.local_set, offset ],
|
3307
3410
|
|
3308
3411
|
// load value
|
3309
3412
|
[ Opcodes.local_get, offset ],
|
3310
|
-
[ Opcodes.load, 0, ValtypeSize.i32 ],
|
3413
|
+
[ Opcodes.load, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ],
|
3311
3414
|
|
3312
3415
|
// load type
|
3313
3416
|
[ Opcodes.local_get, offset ],
|
3314
|
-
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3417
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32 + ValtypeSize[valtype]) ]
|
3315
3418
|
];
|
3316
3419
|
};
|
3317
3420
|
|
@@ -3362,6 +3465,9 @@ const withType = (scope, wasm, type) => [
|
|
3362
3465
|
|
3363
3466
|
const generateMember = (scope, decl, _global, _name) => {
|
3364
3467
|
const name = decl.object.name;
|
3468
|
+
const pointer = scope.arrays?.get(name);
|
3469
|
+
|
3470
|
+
const aotPointer = Prefs.aotPointerOpt && pointer;
|
3365
3471
|
|
3366
3472
|
// hack: .name
|
3367
3473
|
if (decl.property.name === 'name') {
|
@@ -3402,10 +3508,12 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3402
3508
|
if (Prefs.fastLength) {
|
3403
3509
|
// presume valid length object
|
3404
3510
|
return [
|
3405
|
-
...
|
3406
|
-
|
3511
|
+
...(aotPointer ? number(0, Valtype.i32) : [
|
3512
|
+
...generate(scope, decl.object),
|
3513
|
+
Opcodes.i32_to_u
|
3514
|
+
]),
|
3407
3515
|
|
3408
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3516
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
|
3409
3517
|
Opcodes.i32_from_u
|
3410
3518
|
];
|
3411
3519
|
}
|
@@ -3414,10 +3522,12 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3414
3522
|
const known = knownType(scope, type);
|
3415
3523
|
if (known != null) {
|
3416
3524
|
if ([ TYPES.string, TYPES.bytestring, TYPES.array ].includes(known)) return [
|
3417
|
-
...
|
3418
|
-
|
3525
|
+
...(aotPointer ? number(0, Valtype.i32) : [
|
3526
|
+
...generate(scope, decl.object),
|
3527
|
+
Opcodes.i32_to_u
|
3528
|
+
]),
|
3419
3529
|
|
3420
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3530
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
|
3421
3531
|
Opcodes.i32_from_u
|
3422
3532
|
];
|
3423
3533
|
|
@@ -3427,10 +3537,12 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3427
3537
|
return [
|
3428
3538
|
...typeIsOneOf(getNodeType(scope, decl.object), [ TYPES.string, TYPES.bytestring, TYPES.array ]),
|
3429
3539
|
[ Opcodes.if, valtypeBinary ],
|
3430
|
-
...
|
3431
|
-
|
3540
|
+
...(aotPointer ? number(0, Valtype.i32) : [
|
3541
|
+
...generate(scope, decl.object),
|
3542
|
+
Opcodes.i32_to_u
|
3543
|
+
]),
|
3432
3544
|
|
3433
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3545
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
|
3434
3546
|
Opcodes.i32_from_u,
|
3435
3547
|
|
3436
3548
|
...setLastType(scope, TYPES.number),
|
@@ -3482,7 +3594,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3482
3594
|
|
3483
3595
|
return typeSwitch(scope, getNodeType(scope, decl.object), {
|
3484
3596
|
[TYPES.array]: [
|
3485
|
-
...loadArray(scope, object, property),
|
3597
|
+
...loadArray(scope, object, property, aotPointer),
|
3486
3598
|
...setLastType(scope)
|
3487
3599
|
],
|
3488
3600
|
|
@@ -3499,12 +3611,14 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3499
3611
|
...number(ValtypeSize.i16, Valtype.i32),
|
3500
3612
|
[ Opcodes.i32_mul ],
|
3501
3613
|
|
3502
|
-
...
|
3503
|
-
|
3504
|
-
|
3614
|
+
...(aotPointer ? [] : [
|
3615
|
+
...object,
|
3616
|
+
Opcodes.i32_to_u,
|
3617
|
+
[ Opcodes.i32_add ]
|
3618
|
+
]),
|
3505
3619
|
|
3506
3620
|
// load current string ind {arg}
|
3507
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
3621
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ],
|
3508
3622
|
|
3509
3623
|
// store to new string ind 0
|
3510
3624
|
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
@@ -3523,12 +3637,14 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3523
3637
|
...property,
|
3524
3638
|
Opcodes.i32_to_u,
|
3525
3639
|
|
3526
|
-
...
|
3527
|
-
|
3528
|
-
|
3640
|
+
...(aotPointer ? [] : [
|
3641
|
+
...object,
|
3642
|
+
Opcodes.i32_to_u,
|
3643
|
+
[ Opcodes.i32_add ]
|
3644
|
+
]),
|
3529
3645
|
|
3530
3646
|
// load current string ind {arg}
|
3531
|
-
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
3647
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ],
|
3532
3648
|
|
3533
3649
|
// store to new string ind 0
|
3534
3650
|
[ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
package/compiler/cyclone.js
CHANGED
@@ -246,7 +246,7 @@ export default wasm => {
|
|
246
246
|
const [ b, a ] = pop2();
|
247
247
|
const v = bool(a === b);
|
248
248
|
|
249
|
-
replaceVal(v, Valtype.
|
249
|
+
replaceVal(v, Valtype.f64);
|
250
250
|
push(v);
|
251
251
|
break;
|
252
252
|
}
|
@@ -255,7 +255,7 @@ export default wasm => {
|
|
255
255
|
const [ b, a ] = pop2();
|
256
256
|
const v = bool(a !== b);
|
257
257
|
|
258
|
-
replaceVal(v, Valtype.
|
258
|
+
replaceVal(v, Valtype.f64);
|
259
259
|
push(v);
|
260
260
|
break;
|
261
261
|
}
|
@@ -264,7 +264,7 @@ export default wasm => {
|
|
264
264
|
const [ b, a ] = pop2();
|
265
265
|
const v = bool(a < b);
|
266
266
|
|
267
|
-
replaceVal(v, Valtype.
|
267
|
+
replaceVal(v, Valtype.f64);
|
268
268
|
push(v);
|
269
269
|
break;
|
270
270
|
}
|
@@ -273,7 +273,7 @@ export default wasm => {
|
|
273
273
|
const [ b, a ] = pop2();
|
274
274
|
const v = bool(a <= b);
|
275
275
|
|
276
|
-
replaceVal(v, Valtype.
|
276
|
+
replaceVal(v, Valtype.f64);
|
277
277
|
push(v);
|
278
278
|
break;
|
279
279
|
}
|
@@ -282,7 +282,7 @@ export default wasm => {
|
|
282
282
|
const [ b, a ] = pop2();
|
283
283
|
const v = bool(a > b);
|
284
284
|
|
285
|
-
replaceVal(v, Valtype.
|
285
|
+
replaceVal(v, Valtype.f64);
|
286
286
|
push(v);
|
287
287
|
break;
|
288
288
|
}
|
@@ -291,7 +291,7 @@ export default wasm => {
|
|
291
291
|
const [ b, a ] = pop2();
|
292
292
|
const v = bool(a >= b);
|
293
293
|
|
294
|
-
replaceVal(v, Valtype.
|
294
|
+
replaceVal(v, Valtype.f64);
|
295
295
|
push(v);
|
296
296
|
break;
|
297
297
|
}
|
@@ -404,7 +404,7 @@ export default wasm => {
|
|
404
404
|
case Opcodes.f64_max: {
|
405
405
|
if (stack.length < 2) { empty(); break; };
|
406
406
|
const [ b, a ] = pop2();
|
407
|
-
const v =
|
407
|
+
const v = a + b;
|
408
408
|
|
409
409
|
replaceVal(v, Valtype.f64);
|
410
410
|
push(v);
|
@@ -467,9 +467,9 @@ export default wasm => {
|
|
467
467
|
// i32.const 1
|
468
468
|
// i32.add
|
469
469
|
// local.set 7 ;; $i (i32)
|
470
|
-
if (
|
471
|
-
(
|
472
|
-
(opcode >= 0x61 && opcode <= 0x66)
|
470
|
+
if (
|
471
|
+
(opcode >= 0xa0 && opcode <= 0xa3) || // main f64 math op
|
472
|
+
(opcode >= 0x61 && opcode <= 0x66) // main f64 eq op
|
473
473
|
) {
|
474
474
|
const o2 = wasm[i - 1][0];
|
475
475
|
if (o2 === Opcodes.f64_const) { // f64.const
|
@@ -500,7 +500,7 @@ export default wasm => {
|
|
500
500
|
}
|
501
501
|
}
|
502
502
|
|
503
|
-
if ((opcode === 0xfc02 || opcode === 0xfc03) && i
|
503
|
+
if ((opcode === 0xfc02 || opcode === 0xfc03) && i > 3) { // i32.trunc_sat_f64_s/u
|
504
504
|
const o2 = wasm[i - 1][0];
|
505
505
|
if (
|
506
506
|
(o2 >= 0xa0 && o2 <= 0xa3) || // main f64 math op
|
package/compiler/parse.js
CHANGED
@@ -43,7 +43,7 @@ export default (input, flags) => {
|
|
43
43
|
webcompat: true,
|
44
44
|
|
45
45
|
// babel
|
46
|
-
plugins: types
|
46
|
+
plugins: types ? ['estree', 'typescript'] : ['estree'],
|
47
47
|
|
48
48
|
// multiple
|
49
49
|
sourceType: flags.includes('module') ? 'module' : 'script',
|
package/compiler/precompile.js
CHANGED
@@ -26,7 +26,7 @@ const compile = async (file, [ _funcs, _globals ]) => {
|
|
26
26
|
|
27
27
|
const porfCompile = (await import(`./index.js?_=${Date.now()}`)).default;
|
28
28
|
|
29
|
-
let { funcs, globals, data, exceptions } = porfCompile(source, ['module'
|
29
|
+
let { funcs, globals, data, exceptions } = porfCompile(source, ['module']);
|
30
30
|
|
31
31
|
const allocated = new Set();
|
32
32
|
|
@@ -87,8 +87,6 @@ const compile = async (file, [ _funcs, _globals ]) => {
|
|
87
87
|
};
|
88
88
|
|
89
89
|
const precompile = async () => {
|
90
|
-
if (globalThis._porf_loadParser) await globalThis._porf_loadParser('@babel/parser');
|
91
|
-
|
92
90
|
const dir = join(__dirname, 'builtins');
|
93
91
|
|
94
92
|
let funcs = [], globals = [];
|
package/compiler/prefs.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
const onByDefault = [ 'bytestring', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls', 'optUnused'
|
1
|
+
const onByDefault = [ 'bytestring', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls', 'optUnused' ];
|
2
2
|
|
3
3
|
let cache = {};
|
4
4
|
const obj = new Proxy({}, {
|
package/compiler/wrap.js
CHANGED
@@ -128,7 +128,7 @@ export default (source, flags = [ 'module' ], customImports = {}, print = str =>
|
|
128
128
|
|
129
129
|
if (source.includes?.('export ')) flags.push('module');
|
130
130
|
|
131
|
-
|
131
|
+
fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
132
132
|
|
133
133
|
times.push(performance.now() - t1);
|
134
134
|
if (Prefs.profileCompiler) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
|
package/package.json
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "porffor",
|
3
3
|
"description": "a basic experimental wip aot optimizing js -> wasm engine/compiler/runtime in js",
|
4
|
-
"version": "0.16.0-
|
4
|
+
"version": "0.16.0-30af62694",
|
5
5
|
"author": "CanadaHonk",
|
6
6
|
"license": "MIT",
|
7
|
-
"scripts": {
|
7
|
+
"scripts": {
|
8
|
+
"precompile": "node ./compiler/precompile.js"
|
9
|
+
},
|
8
10
|
"dependencies": {
|
9
11
|
"acorn": "^8.11.3",
|
10
12
|
"node-repl-polyfill": "^0.1.1"
|
package/runner/index.js
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
+
|
3
|
+
import compile from '../compiler/wrap.js';
|
2
4
|
import fs from 'node:fs';
|
3
5
|
|
4
6
|
const start = performance.now();
|
@@ -57,15 +59,10 @@ if (process.argv.includes('--help')) {
|
|
57
59
|
}
|
58
60
|
|
59
61
|
let file = process.argv.slice(2).find(x => x[0] !== '-');
|
60
|
-
if (['
|
62
|
+
if (['run', 'wasm', 'native', 'c', 'profile', 'debug', 'debug-wasm'].includes(file)) {
|
61
63
|
// remove this arg
|
62
64
|
process.argv.splice(process.argv.indexOf(file), 1);
|
63
65
|
|
64
|
-
if (file === 'precompile') {
|
65
|
-
await import('../compiler/precompile.js');
|
66
|
-
await new Promise(() => {}); // do nothing for the rest of this file
|
67
|
-
}
|
68
|
-
|
69
66
|
if (file === 'profile') {
|
70
67
|
await import('./profile.js');
|
71
68
|
await new Promise(() => {}); // do nothing for the rest of this file
|
@@ -108,8 +105,6 @@ if (!file) {
|
|
108
105
|
|
109
106
|
const source = fs.readFileSync(file, 'utf8');
|
110
107
|
|
111
|
-
const compile = (await import('../compiler/wrap.js')).default;
|
112
|
-
|
113
108
|
let cache = '';
|
114
109
|
const print = str => {
|
115
110
|
/* cache += str;
|
File without changes
|
File without changes
|
@@ -1,41 +0,0 @@
|
|
1
|
-
import { Valtype } from '../wasmSpec.js';
|
2
|
-
import { number } from './embedding.js';
|
3
|
-
import { log } from './log.js';
|
4
|
-
import Prefs from './prefs.js';
|
5
|
-
|
6
|
-
let pages = new Set();
|
7
|
-
export const setup = () => {
|
8
|
-
pages = new Set();
|
9
|
-
};
|
10
|
-
|
11
|
-
const getAllocType = itemType => {
|
12
|
-
switch (itemType) {
|
13
|
-
case 'i8': return 'bytestring';
|
14
|
-
case 'i16': return 'string';
|
15
|
-
|
16
|
-
default: return 'array';
|
17
|
-
}
|
18
|
-
};
|
19
|
-
|
20
|
-
export const alloc = ({ scope }, name, itemType) => {
|
21
|
-
const reason = Prefs.scopedPageNames ? `${getAllocType(itemType)}: ${scope.name}/${name}` : `${getAllocType(itemType)}: ${name}`;
|
22
|
-
|
23
|
-
if (pages.has(reason)) return number(pages.get(reason).ind, Valtype.i32);
|
24
|
-
|
25
|
-
if (reason.startsWith('array:')) pages.hasArray = true;
|
26
|
-
if (reason.startsWith('string:')) pages.hasString = true;
|
27
|
-
if (reason.startsWith('bytestring:')) pages.hasByteString = true;
|
28
|
-
if (reason.includes('string:')) pages.hasAnyString = true;
|
29
|
-
|
30
|
-
const ind = pages.size;
|
31
|
-
pages.set(reason, { ind, type });
|
32
|
-
|
33
|
-
scope.pages ??= new Map();
|
34
|
-
scope.pages.set(reason, { ind, type });
|
35
|
-
|
36
|
-
if (Prefs.allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason} (type: ${type})`);
|
37
|
-
|
38
|
-
return number(ind, Valtype.i32);
|
39
|
-
};
|
40
|
-
|
41
|
-
export const getStaticPages = () => pages;
|