porffor 0.57.24 → 0.57.25

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,47 @@ 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
+ const _ = prop;
3588
+ if (!Prefs.ctHash || !prop ||
3589
+ prop.computed || prop.optional ||
3590
+ prop.property.type === 'PrivateIdentifier'
3591
+ ) return null;
3592
+
3593
+ prop = prop.property.name;
3594
+ if (!prop || prop === '__proto__' || !byteStringable(prop)) return null;
3589
3595
 
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;
3596
+ let i = 0;
3597
+ const len = prop.length;
3598
+ let hash = 374761393 + len;
3595
3599
 
3596
- prop = prop.property.name;
3600
+ const rotl = (n, k) => (n << k) | (n >>> (32 - k));
3601
+ const read = () => (prop.charCodeAt(i + 3) << 24 | prop.charCodeAt(i + 2) << 16 | prop.charCodeAt(i + 1) << 8 | prop.charCodeAt(i));
3602
+
3603
+ // hash in chunks of i32 (4 bytes)
3604
+ for (; i <= len - 4; i += 4) {
3605
+ hash = Math.imul(rotl(hash + Math.imul(read(), 3266489917), 17), 668265263);
3597
3606
  }
3598
3607
 
3608
+ // hash final bytes up to 4 via shift depending on bytes remaining
3609
+ hash = Math.imul(rotl(hash + Math.imul(read(), 3266489917), 17), 668265263);
3610
+
3611
+ // final avalanche
3612
+ hash = Math.imul(hash ^ (hash >>> 15), 2246822519);
3613
+ hash = Math.imul(hash ^ (hash >>> 13), 3266489917);
3614
+ return (hash ^ (hash >>> 16));
3615
+ };
3616
+
3617
+ // COCTC: cross-object compile-time (inline) cache
3618
+ const coctcOffset = prop => {
3619
+ if (!Prefs.coctc || !prop ||
3620
+ prop.computed || prop.optional ||
3621
+ prop.property.type === 'PrivateIdentifier'
3622
+ ) return 0;
3623
+
3624
+ prop = prop.property.name;
3625
+ if (!prop || ['prototype', 'size', 'description', 'byteLength', 'byteOffset', 'buffer', 'detached', 'resizable', 'growable', 'maxByteLength', 'name', 'message', 'constructor', 'length', '__proto__'].includes(prop)) return 0;
3626
+
3599
3627
  let offset = coctc.get(prop);
3600
3628
  if (offset == null) {
3601
3629
  offset = (coctc.lastOffset ?? Prefs.coctcOffset ?? (globalThis.pageSize - 128)) - 9;
@@ -3726,8 +3754,9 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
3726
3754
  // todo/perf: use i32 object (and prop?) locals
3727
3755
  const { objectTmp, propertyTmp, objectGet, propertyGet } = memberTmpNames(scope);
3728
3756
 
3729
- const useCoctc = coctcOffset(decl.left) > 0;
3730
- if (useCoctc) valueUnused = false;
3757
+ const hash = ctHash(decl.left);
3758
+ const coctc = coctcOffset(decl.left);
3759
+ if (coctc > 0) valueUnused = false;
3731
3760
 
3732
3761
  // opt: do not mark prototype funcs as referenced to optimize this in them
3733
3762
  if (object?.property?.name === 'prototype' && isFuncType(decl.right.type)) decl.right._doNotMarkFuncRef = true;
@@ -4004,12 +4033,24 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
4004
4033
  [ Opcodes.local_get, localTmp(scope, '#objset_property', Valtype.i32) ],
4005
4034
  [ Opcodes.local_get, localTmp(scope, '#objset_property_type', Valtype.i32) ],
4006
4035
 
4007
- [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_get').index ],
4036
+ ...(hash != null ? [
4037
+ number(hash, Valtype.i32),
4038
+ number(TYPES.number, Valtype.i32),
4039
+ [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_get_withHash').index ]
4040
+ ] : [
4041
+ [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_get').index ]
4042
+ ]),
4008
4043
  ...setLastType(scope)
4009
4044
  ], generate(scope, decl.right), getLastType(scope), getNodeType(scope, decl.right))),
4010
4045
  ...getNodeType(scope, decl),
4011
4046
 
4012
- [ Opcodes.call, includeBuiltin(scope, scope.strict ? '__Porffor_object_setStrict' : '__Porffor_object_set').index ],
4047
+ ...(hash != null ? [
4048
+ number(hash, Valtype.i32),
4049
+ number(TYPES.number, Valtype.i32),
4050
+ [ Opcodes.call, includeBuiltin(scope, scope.strict ? '__Porffor_object_setStrict_withHash' : '__Porffor_object_set_withHash').index ],
4051
+ ] : [
4052
+ [ Opcodes.call, includeBuiltin(scope, scope.strict ? '__Porffor_object_setStrict' : '__Porffor_object_set').index ],
4053
+ ]),
4013
4054
  [ Opcodes.drop ],
4014
4055
  ...(valueUnused ? [ [ Opcodes.drop ] ] : [])
4015
4056
  // ...setLastType(scope, getNodeType(scope, decl)),
@@ -4018,9 +4059,8 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
4018
4059
  ...optional(number(UNDEFINED), valueUnused)
4019
4060
  ];
4020
4061
 
4021
- if (useCoctc) {
4062
+ if (coctc > 0) {
4022
4063
  // set COCTC
4023
- const offset = coctcOffset(decl.left.property.name);
4024
4064
  const valueTmp = localTmp(scope, '#coctc_value');
4025
4065
  const objectTmp = localTmp(scope, '#coctc_object', Valtype.i32);
4026
4066
 
@@ -4030,11 +4070,11 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
4030
4070
 
4031
4071
  [ Opcodes.local_get, objectTmp ],
4032
4072
  [ Opcodes.local_get, valueTmp ],
4033
- [ Opcodes.f64_store, 0, ...unsignedLEB128(offset) ],
4073
+ [ Opcodes.f64_store, 0, ...unsignedLEB128(coctc) ],
4034
4074
 
4035
4075
  [ Opcodes.local_get, objectTmp ],
4036
4076
  ...getNodeType(scope, decl),
4037
- [ Opcodes.i32_store8, 0, ...unsignedLEB128(offset + 8) ]
4077
+ [ Opcodes.i32_store8, 0, ...unsignedLEB128(coctc + 8) ]
4038
4078
  );
4039
4079
  }
4040
4080
 
@@ -4222,8 +4262,8 @@ const generateUnary = (scope, decl) => {
4222
4262
  const property = getProperty(decl.argument);
4223
4263
  if (property.value === 'length' || property.value === 'name') scope.noFastFuncMembers = true;
4224
4264
 
4225
- const useCoctc = coctcOffset(decl.argument) > 0;
4226
- const objectTmp = useCoctc && localTmp(scope, '#coctc_object', Valtype.i32);
4265
+ const coctc = coctcOffset(decl.argument);
4266
+ const objectTmp = coctc > 0 && localTmp(scope, '#coctc_object', Valtype.i32);
4227
4267
 
4228
4268
  const out = [
4229
4269
  ...generate(scope, object),
@@ -4237,20 +4277,18 @@ const generateUnary = (scope, decl) => {
4237
4277
  Opcodes.i32_from_u
4238
4278
  ];
4239
4279
 
4240
- if (useCoctc) {
4280
+ if (coctc > 0) {
4241
4281
  // set COCTC
4242
- const offset = coctcOffset(decl.argument.property.name);
4243
-
4244
4282
  out.push(
4245
4283
  ...coctcSetup(scope, object, objectTmp, null, [ [ Opcodes.local_get, objectTmp ] ], false),
4246
4284
 
4247
4285
  [ Opcodes.local_get, objectTmp ],
4248
4286
  number(0),
4249
- [ Opcodes.f64_store, 0, ...unsignedLEB128(offset) ],
4287
+ [ Opcodes.f64_store, 0, ...unsignedLEB128(coctc) ],
4250
4288
 
4251
4289
  [ Opcodes.local_get, objectTmp ],
4252
4290
  number(0, Valtype.i32),
4253
- [ Opcodes.i32_store8, 0, ...unsignedLEB128(offset + 8) ]
4291
+ [ Opcodes.i32_store8, 0, ...unsignedLEB128(coctc + 8) ]
4254
4292
  );
4255
4293
  }
4256
4294
 
@@ -5860,8 +5898,9 @@ const generateMember = (scope, decl, _global, _name) => {
5860
5898
  if (known == null) extraBC = bc;
5861
5899
  }
5862
5900
 
5863
- const useCoctc = coctcOffset(decl) > 0;
5864
- const coctcObjTmp = useCoctc && localTmp(scope, '#coctc_obj' + uniqId(), Valtype.i32);
5901
+ const hash = ctHash(decl);
5902
+ const coctc = coctcOffset(decl);
5903
+ const coctcObjTmp = coctc > 0 && localTmp(scope, '#coctc_obj' + uniqId(), Valtype.i32);
5865
5904
 
5866
5905
  const out = typeSwitch(scope, type, {
5867
5906
  ...(decl.computed ? {
@@ -6057,7 +6096,7 @@ const generateMember = (scope, decl, _global, _name) => {
6057
6096
  [TYPES.undefined]: internalThrow(scope, 'TypeError', `Cannot read property of undefined`, true),
6058
6097
 
6059
6098
  default: () => [
6060
- ...(useCoctc && known === TYPES.object ? [
6099
+ ...(coctc > 0 && known === TYPES.object ? [
6061
6100
  [ Opcodes.local_get, coctcObjTmp ],
6062
6101
  number(TYPES.object, Valtype.i32)
6063
6102
  ] : [
@@ -6068,7 +6107,14 @@ const generateMember = (scope, decl, _global, _name) => {
6068
6107
 
6069
6108
  ...toPropertyKey(scope, [ propertyGet ], getNodeType(scope, property), decl.computed, true),
6070
6109
 
6071
- [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_get').index ],
6110
+ ...(hash != null ? [
6111
+ number(hash, Valtype.i32),
6112
+ number(TYPES.number, Valtype.i32),
6113
+ [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_get_withHash').index ]
6114
+ ] : [
6115
+ [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_get').index ]
6116
+ ]),
6117
+
6072
6118
  ...setLastType(scope)
6073
6119
  ],
6074
6120
 
@@ -6096,21 +6142,19 @@ const generateMember = (scope, decl, _global, _name) => {
6096
6142
  [ Opcodes.end ]
6097
6143
  );
6098
6144
  } else {
6099
- if (useCoctc) {
6145
+ if (coctc > 0) {
6100
6146
  // fast path: COCTC
6101
- const offset = coctcOffset(decl.property.name);
6102
-
6103
6147
  out.unshift(
6104
6148
  ...generate(scope, decl.object),
6105
6149
  [ Opcodes.local_set, objectTmp ],
6106
6150
  ...coctcSetup(scope, decl.object, coctcObjTmp, 'get', [ [ Opcodes.local_get, objectTmp ] ]),
6107
6151
 
6108
6152
  [ Opcodes.local_get, coctcObjTmp ],
6109
- [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(offset + 8) ],
6153
+ [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(coctc + 8) ],
6110
6154
  [ Opcodes.local_tee, localTmp(scope, '#coctc_tmp', Valtype.i32) ],
6111
6155
  [ Opcodes.if, Valtype.f64 ],
6112
6156
  [ Opcodes.local_get, coctcObjTmp ],
6113
- [ Opcodes.f64_load, 0, ...unsignedLEB128(offset) ],
6157
+ [ Opcodes.f64_load, 0, ...unsignedLEB128(coctc) ],
6114
6158
 
6115
6159
  ...setLastType(scope, [
6116
6160
  [ Opcodes.local_get, localTmp(scope, '#coctc_tmp', Valtype.i32) ],
@@ -6493,7 +6537,7 @@ const objectHack = node => {
6493
6537
  if (node.type === 'MemberExpression') {
6494
6538
  const out = (() => {
6495
6539
  const abortOut = { ...node, object: objectHack(node.object) };
6496
- if (node.computed || node.optional) return;
6540
+ if (node.computed || node.optional || node.property.type === 'PrivateIdentifier') return;
6497
6541
 
6498
6542
  // hack: block these properties as they can be accessed on functions
6499
6543
  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,4 +1,4 @@
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
 
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.25",
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.25';
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(""))