porffor 0.57.24 → 0.57.26

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.
@@ -3583,19 +3583,43 @@ const memberTmpNames = scope => {
3583
3583
  };
3584
3584
  };
3585
3585
 
3586
- // COCTC: cross-object compile-time cache
3587
- const coctcOffset = prop => {
3588
- if (!Prefs.coctc) return 0;
3586
+ const ctHash = prop => {
3587
+ if (!Prefs.ctHash || !prop ||
3588
+ prop.computed || prop.optional ||
3589
+ prop.property.type === 'PrivateIdentifier'
3590
+ ) return null;
3591
+
3592
+ prop = prop.property.name;
3593
+ if (!prop || prop === '__proto__' || !byteStringable(prop)) return null;
3594
+
3595
+ let i = 0;
3596
+ const len = prop.length;
3597
+ let hash = 374761393 + len;
3589
3598
 
3590
- if (typeof prop === 'object') {
3591
- if (
3592
- prop.computed || prop.optional ||
3593
- ['prototype', 'size', 'description', 'byteLength', 'byteOffset', 'buffer', 'detached', 'resizable', 'growable', 'maxByteLength', 'name', 'message', 'constructor', 'length', '__proto__'].includes(prop.property.name)
3594
- ) return 0;
3599
+ const rotl = (n, k) => (n << k) | (n >>> (32 - k));
3600
+ const read = () => (prop.charCodeAt(i + 3) << 24 | prop.charCodeAt(i + 2) << 16 | prop.charCodeAt(i + 1) << 8 | prop.charCodeAt(i));
3595
3601
 
3596
- prop = prop.property.name;
3602
+ // hash in chunks of i32 (4 bytes)
3603
+ for (; i <= len; i += 4) {
3604
+ hash = Math.imul(rotl(hash + Math.imul(read(), 3266489917), 17), 668265263);
3597
3605
  }
3598
3606
 
3607
+ // final avalanche
3608
+ hash = Math.imul(hash ^ (hash >>> 15), 2246822519);
3609
+ hash = Math.imul(hash ^ (hash >>> 13), 3266489917);
3610
+ return (hash ^ (hash >>> 16));
3611
+ };
3612
+
3613
+ // COCTC: cross-object compile-time (inline) cache
3614
+ const coctcOffset = prop => {
3615
+ if (!Prefs.coctc || !prop ||
3616
+ prop.computed || prop.optional ||
3617
+ prop.property.type === 'PrivateIdentifier'
3618
+ ) return 0;
3619
+
3620
+ prop = prop.property.name;
3621
+ if (!prop || ['prototype', 'size', 'description', 'byteLength', 'byteOffset', 'buffer', 'detached', 'resizable', 'growable', 'maxByteLength', 'name', 'message', 'constructor', 'length', '__proto__'].includes(prop)) return 0;
3622
+
3599
3623
  let offset = coctc.get(prop);
3600
3624
  if (offset == null) {
3601
3625
  offset = (coctc.lastOffset ?? Prefs.coctcOffset ?? (globalThis.pageSize - 128)) - 9;
@@ -3726,8 +3750,9 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
3726
3750
  // todo/perf: use i32 object (and prop?) locals
3727
3751
  const { objectTmp, propertyTmp, objectGet, propertyGet } = memberTmpNames(scope);
3728
3752
 
3729
- const useCoctc = coctcOffset(decl.left) > 0;
3730
- if (useCoctc) valueUnused = false;
3753
+ const hash = ctHash(decl.left);
3754
+ const coctc = coctcOffset(decl.left);
3755
+ if (coctc > 0) valueUnused = false;
3731
3756
 
3732
3757
  // opt: do not mark prototype funcs as referenced to optimize this in them
3733
3758
  if (object?.property?.name === 'prototype' && isFuncType(decl.right.type)) decl.right._doNotMarkFuncRef = true;
@@ -4004,12 +4029,24 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
4004
4029
  [ Opcodes.local_get, localTmp(scope, '#objset_property', Valtype.i32) ],
4005
4030
  [ Opcodes.local_get, localTmp(scope, '#objset_property_type', Valtype.i32) ],
4006
4031
 
4007
- [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_get').index ],
4032
+ ...(hash != null ? [
4033
+ number(hash, Valtype.i32),
4034
+ number(TYPES.number, Valtype.i32),
4035
+ [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_get_withHash').index ]
4036
+ ] : [
4037
+ [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_get').index ]
4038
+ ]),
4008
4039
  ...setLastType(scope)
4009
4040
  ], generate(scope, decl.right), getLastType(scope), getNodeType(scope, decl.right))),
4010
4041
  ...getNodeType(scope, decl),
4011
4042
 
4012
- [ Opcodes.call, includeBuiltin(scope, scope.strict ? '__Porffor_object_setStrict' : '__Porffor_object_set').index ],
4043
+ ...(hash != null ? [
4044
+ number(hash, Valtype.i32),
4045
+ number(TYPES.number, Valtype.i32),
4046
+ [ Opcodes.call, includeBuiltin(scope, scope.strict ? '__Porffor_object_setStrict_withHash' : '__Porffor_object_set_withHash').index ],
4047
+ ] : [
4048
+ [ Opcodes.call, includeBuiltin(scope, scope.strict ? '__Porffor_object_setStrict' : '__Porffor_object_set').index ],
4049
+ ]),
4013
4050
  [ Opcodes.drop ],
4014
4051
  ...(valueUnused ? [ [ Opcodes.drop ] ] : [])
4015
4052
  // ...setLastType(scope, getNodeType(scope, decl)),
@@ -4018,9 +4055,8 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
4018
4055
  ...optional(number(UNDEFINED), valueUnused)
4019
4056
  ];
4020
4057
 
4021
- if (useCoctc) {
4058
+ if (coctc > 0) {
4022
4059
  // set COCTC
4023
- const offset = coctcOffset(decl.left.property.name);
4024
4060
  const valueTmp = localTmp(scope, '#coctc_value');
4025
4061
  const objectTmp = localTmp(scope, '#coctc_object', Valtype.i32);
4026
4062
 
@@ -4030,11 +4066,11 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
4030
4066
 
4031
4067
  [ Opcodes.local_get, objectTmp ],
4032
4068
  [ Opcodes.local_get, valueTmp ],
4033
- [ Opcodes.f64_store, 0, ...unsignedLEB128(offset) ],
4069
+ [ Opcodes.f64_store, 0, ...unsignedLEB128(coctc) ],
4034
4070
 
4035
4071
  [ Opcodes.local_get, objectTmp ],
4036
4072
  ...getNodeType(scope, decl),
4037
- [ Opcodes.i32_store8, 0, ...unsignedLEB128(offset + 8) ]
4073
+ [ Opcodes.i32_store8, 0, ...unsignedLEB128(coctc + 8) ]
4038
4074
  );
4039
4075
  }
4040
4076
 
@@ -4222,8 +4258,8 @@ const generateUnary = (scope, decl) => {
4222
4258
  const property = getProperty(decl.argument);
4223
4259
  if (property.value === 'length' || property.value === 'name') scope.noFastFuncMembers = true;
4224
4260
 
4225
- const useCoctc = coctcOffset(decl.argument) > 0;
4226
- const objectTmp = useCoctc && localTmp(scope, '#coctc_object', Valtype.i32);
4261
+ const coctc = coctcOffset(decl.argument);
4262
+ const objectTmp = coctc > 0 && localTmp(scope, '#coctc_object', Valtype.i32);
4227
4263
 
4228
4264
  const out = [
4229
4265
  ...generate(scope, object),
@@ -4237,20 +4273,18 @@ const generateUnary = (scope, decl) => {
4237
4273
  Opcodes.i32_from_u
4238
4274
  ];
4239
4275
 
4240
- if (useCoctc) {
4276
+ if (coctc > 0) {
4241
4277
  // set COCTC
4242
- const offset = coctcOffset(decl.argument.property.name);
4243
-
4244
4278
  out.push(
4245
4279
  ...coctcSetup(scope, object, objectTmp, null, [ [ Opcodes.local_get, objectTmp ] ], false),
4246
4280
 
4247
4281
  [ Opcodes.local_get, objectTmp ],
4248
4282
  number(0),
4249
- [ Opcodes.f64_store, 0, ...unsignedLEB128(offset) ],
4283
+ [ Opcodes.f64_store, 0, ...unsignedLEB128(coctc) ],
4250
4284
 
4251
4285
  [ Opcodes.local_get, objectTmp ],
4252
4286
  number(0, Valtype.i32),
4253
- [ Opcodes.i32_store8, 0, ...unsignedLEB128(offset + 8) ]
4287
+ [ Opcodes.i32_store8, 0, ...unsignedLEB128(coctc + 8) ]
4254
4288
  );
4255
4289
  }
4256
4290
 
@@ -5860,8 +5894,9 @@ const generateMember = (scope, decl, _global, _name) => {
5860
5894
  if (known == null) extraBC = bc;
5861
5895
  }
5862
5896
 
5863
- const useCoctc = coctcOffset(decl) > 0;
5864
- const coctcObjTmp = useCoctc && localTmp(scope, '#coctc_obj' + uniqId(), Valtype.i32);
5897
+ const hash = ctHash(decl);
5898
+ const coctc = coctcOffset(decl);
5899
+ const coctcObjTmp = coctc > 0 && localTmp(scope, '#coctc_obj' + uniqId(), Valtype.i32);
5865
5900
 
5866
5901
  const out = typeSwitch(scope, type, {
5867
5902
  ...(decl.computed ? {
@@ -6057,7 +6092,7 @@ const generateMember = (scope, decl, _global, _name) => {
6057
6092
  [TYPES.undefined]: internalThrow(scope, 'TypeError', `Cannot read property of undefined`, true),
6058
6093
 
6059
6094
  default: () => [
6060
- ...(useCoctc && known === TYPES.object ? [
6095
+ ...(coctc > 0 && known === TYPES.object ? [
6061
6096
  [ Opcodes.local_get, coctcObjTmp ],
6062
6097
  number(TYPES.object, Valtype.i32)
6063
6098
  ] : [
@@ -6068,7 +6103,14 @@ const generateMember = (scope, decl, _global, _name) => {
6068
6103
 
6069
6104
  ...toPropertyKey(scope, [ propertyGet ], getNodeType(scope, property), decl.computed, true),
6070
6105
 
6071
- [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_get').index ],
6106
+ ...(hash != null ? [
6107
+ number(hash, Valtype.i32),
6108
+ number(TYPES.number, Valtype.i32),
6109
+ [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_get_withHash').index ]
6110
+ ] : [
6111
+ [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_get').index ]
6112
+ ]),
6113
+
6072
6114
  ...setLastType(scope)
6073
6115
  ],
6074
6116
 
@@ -6096,21 +6138,19 @@ const generateMember = (scope, decl, _global, _name) => {
6096
6138
  [ Opcodes.end ]
6097
6139
  );
6098
6140
  } else {
6099
- if (useCoctc) {
6141
+ if (coctc > 0) {
6100
6142
  // fast path: COCTC
6101
- const offset = coctcOffset(decl.property.name);
6102
-
6103
6143
  out.unshift(
6104
6144
  ...generate(scope, decl.object),
6105
6145
  [ Opcodes.local_set, objectTmp ],
6106
6146
  ...coctcSetup(scope, decl.object, coctcObjTmp, 'get', [ [ Opcodes.local_get, objectTmp ] ]),
6107
6147
 
6108
6148
  [ Opcodes.local_get, coctcObjTmp ],
6109
- [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(offset + 8) ],
6149
+ [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(coctc + 8) ],
6110
6150
  [ Opcodes.local_tee, localTmp(scope, '#coctc_tmp', Valtype.i32) ],
6111
6151
  [ Opcodes.if, Valtype.f64 ],
6112
6152
  [ Opcodes.local_get, coctcObjTmp ],
6113
- [ Opcodes.f64_load, 0, ...unsignedLEB128(offset) ],
6153
+ [ Opcodes.f64_load, 0, ...unsignedLEB128(coctc) ],
6114
6154
 
6115
6155
  ...setLastType(scope, [
6116
6156
  [ Opcodes.local_get, localTmp(scope, '#coctc_tmp', Valtype.i32) ],
@@ -6493,7 +6533,7 @@ const objectHack = node => {
6493
6533
  if (node.type === 'MemberExpression') {
6494
6534
  const out = (() => {
6495
6535
  const abortOut = { ...node, object: objectHack(node.object) };
6496
- if (node.computed || node.optional) return;
6536
+ if (node.computed || node.optional || node.property.type === 'PrivateIdentifier') return;
6497
6537
 
6498
6538
  // hack: block these properties as they can be accessed on functions
6499
6539
  if (node.object.name !== 'Porffor' && (node.property.name === 'length' || node.property.name === 'name' || node.property.name === 'call')) return abortOut;
@@ -23,14 +23,19 @@ globalThis.precompile = true;
23
23
  globalThis.valtypeOverrides = {
24
24
  returns: {
25
25
  __Porffor_object_get: [ Valtype.f64, Valtype.i32 ],
26
+ __Porffor_object_get_withHash: [ Valtype.f64, Valtype.i32 ],
26
27
  __Porffor_object_readValue: [ Valtype.f64, Valtype.i32 ],
27
28
  __Porffor_object_set: [ Valtype.f64, Valtype.i32 ],
29
+ __Porffor_object_set_withHash: [ Valtype.f64, Valtype.i32 ],
28
30
  __Porffor_object_setStrict: [ Valtype.f64, Valtype.i32 ],
31
+ __Porffor_object_setStrict_withHash: [ Valtype.f64, Valtype.i32 ],
29
32
  __Porffor_object_packAccessor: [ Valtype.f64 ]
30
33
  },
31
34
  params: {
32
35
  __Porffor_object_set: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32 ],
36
+ __Porffor_object_set_withHash: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32, Valtype.i32, Valtype.i32 ],
33
37
  __Porffor_object_setStrict: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32 ],
38
+ __Porffor_object_setStrict_withHash: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32, Valtype.i32, Valtype.i32 ],
34
39
  __Porffor_object_expr_init: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32 ],
35
40
  __Porffor_object_fastAdd: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32, Valtype.i32, Valtype.i32 ],
36
41
  __Porffor_object_class_value: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32 ],
package/compiler/prefs.js CHANGED
@@ -1,10 +1,9 @@
1
- const onByDefault = [ 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls', 'optUnused', 'data', 'passiveData', 'rmUnusedTypes', 'optTypes', 'coctc' ];
1
+ const onByDefault = [ 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls', 'optUnused', 'data', 'passiveData', 'rmUnusedTypes', 'optTypes', 'coctc', 'ctHash' ];
2
2
 
3
3
  const nameToKey = x => x.replace(/[a-z]\-[a-z]/g, y => `${y[0]}${y[2].toUpperCase()}`);
4
4
 
5
- let prefs = {};
6
5
  const getPrefs = () => {
7
- prefs = {};
6
+ const prefs = globalThis.Prefs = {};
8
7
  for (const x of onByDefault) prefs[x] = true;
9
8
 
10
9
  for (const x of process.argv) {
@@ -18,12 +17,8 @@ const getPrefs = () => {
18
17
  prefs[nameToKey(name)] = value ?? true;
19
18
  }
20
19
  }
21
-
22
- globalThis.Prefs = prefs;
23
20
  };
24
21
  getPrefs();
25
22
 
26
- // export default prefs;
27
-
28
23
  export const uncache = () => getPrefs();
29
24
  globalThis.argvChanged = uncache;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "porffor",
3
3
  "description": "An ahead-of-time JavaScript compiler",
4
- "version": "0.57.24",
4
+ "version": "0.57.26",
5
5
  "author": "Oliver Medhurst <honk@goose.icu>",
6
6
  "license": "MIT",
7
7
  "scripts": {},
package/runtime/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs';
3
- globalThis.version = '0.57.24';
3
+ globalThis.version = '0.57.26';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {
package/foo.js DELETED
@@ -1 +0,0 @@
1
- console.log(await Promise.resolve(5));
package/foo.ts DELETED
@@ -1,12 +0,0 @@
1
- // namespace wasm {
2
- // export declare function imported_wasm_func(a: number): void;
3
- // }
4
-
5
- // wasm.imported_wasm_func(1337);
6
-
7
- class Vector {
8
- foo(x: number): number
9
- }
10
-
11
- const foo = new Vector()
12
- console.log(foo.foo(""))