porffor 0.55.21 → 0.55.23

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.
@@ -1,30 +1,60 @@
1
1
  // @porf --valtype=i32
2
2
  import type {} from './porffor.d.ts';
3
3
 
4
- // todo: padding for memory alignment?
5
- // memory layout:
6
- // size (u32, 4)
7
- // root flags (u32, 1):
4
+ // __memory layout__
5
+ // per object (8):
6
+ // size (u16, 2)
7
+ // root flags (u8, 1):
8
8
  // inextensible - 0b0001
9
- // per entry (14):
9
+ // prototype type (u8, 1)
10
+ // prototype (u32, 4)
11
+ // per entry (18):
12
+ // key - hash (u32, 4)
10
13
  // key - value, type MSB encoded (u32, 4)
11
14
  // value - value (f64, 8)
12
- // value - type + obj flag (u16, 2)
13
- // flags:
15
+ // value - type + flags (u16, 2):
14
16
  // accessor - 0b0001
15
17
  // configurable - 0b0010
16
18
  // enumerable - 0b0100
17
19
  // writable - 0b1000
18
20
 
21
+ export const __Porffor_object_isObject = (arg: any): boolean => {
22
+ const t: i32 = Porffor.wasm`local.get ${arg+1}`;
23
+ return Porffor.fastAnd(
24
+ arg != 0, // null
25
+ t > 0x05,
26
+ t != Porffor.TYPES.string,
27
+ t != Porffor.TYPES.bytestring
28
+ );
29
+ };
30
+
31
+ export const __Porffor_object_isObjectOrNull = (arg: any): boolean => {
32
+ const t: i32 = Porffor.wasm`local.get ${arg+1}`;
33
+ return Porffor.fastAnd(
34
+ t > 0x05,
35
+ t != Porffor.TYPES.string,
36
+ t != Porffor.TYPES.bytestring
37
+ );
38
+ };
39
+
40
+ export const __Porffor_object_isObjectOrSymbol = (arg: any): boolean => {
41
+ const t: i32 = Porffor.wasm`local.get ${arg+1}`;
42
+ return Porffor.fastAnd(
43
+ arg != 0, // null
44
+ t > 0x04,
45
+ t != Porffor.TYPES.string,
46
+ t != Porffor.TYPES.bytestring
47
+ );
48
+ };
49
+
50
+
19
51
  export const __Porffor_object_preventExtensions = (obj: any): void => {
20
52
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
21
53
  obj = __Porffor_object_underlying(obj);
22
54
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return;
23
55
  }
24
56
 
25
- let rootFlags: i32 = Porffor.wasm.i32.load8_u(obj, 0, 4);
26
- rootFlags |= 0b0001;
27
- Porffor.wasm.i32.store8(obj, rootFlags, 0, 4);
57
+ Porffor.wasm.i32.store8(obj, Porffor.wasm.i32.load8_u(obj, 0, 2) | 0b0001, 0, 2);
28
58
  };
29
59
 
30
60
  export const __Porffor_object_isInextensible = (obj: any): boolean => {
@@ -33,8 +63,39 @@ export const __Porffor_object_isInextensible = (obj: any): boolean => {
33
63
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return false;
34
64
  }
35
65
 
36
- const out: boolean = Porffor.wasm.i32.load8_u(obj, 0, 4) & 0b0001;
37
- return out;
66
+ return (Porffor.wasm.i32.load8_u(obj, 0, 2) & 0b0001) as boolean;
67
+ };
68
+
69
+ export const __Porffor_object_setPrototype = (obj: any, proto: any): void => {
70
+ if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
71
+ obj = __Porffor_object_underlying(obj);
72
+ if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return;
73
+ }
74
+
75
+ if (__Porffor_object_isObjectOrNull(proto)) {
76
+ Porffor.wasm.i32.store(obj, proto, 0, 4);
77
+ Porffor.wasm.i32.store8(obj, Porffor.rawType(proto), 0, 3);
78
+ }
79
+ };
80
+
81
+ export const __Porffor_object_getPrototype = (obj: any): any => {
82
+ if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
83
+ obj = __Porffor_object_underlying(obj);
84
+ if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
85
+ // return empty
86
+ Porffor.wasm`
87
+ i32.const 0
88
+ i32.const 0
89
+ return`;
90
+ }
91
+ }
92
+
93
+ Porffor.wasm`
94
+ local.get ${obj}
95
+ i32.load 0 4
96
+ local.get ${obj}
97
+ i32.load8_u 0 3
98
+ return`;
38
99
  };
39
100
 
40
101
 
@@ -44,15 +105,15 @@ export const __Porffor_object_overrideAllFlags = (obj: any, overrideOr: i32, ove
44
105
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return;
45
106
  }
46
107
 
47
- let ptr: i32 = Porffor.wasm`local.get ${obj}` + 5;
108
+ let ptr: i32 = Porffor.wasm`local.get ${obj}`;
48
109
 
49
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
50
- const endPtr: i32 = ptr + size * 14;
110
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
111
+ const endPtr: i32 = ptr + size * 18;
51
112
 
52
- for (; ptr < endPtr; ptr += 14) {
53
- let flags: i32 = Porffor.wasm.i32.load8_u(ptr, 0, 12);
113
+ for (; ptr < endPtr; ptr += 18) {
114
+ let flags: i32 = Porffor.wasm.i32.load8_u(ptr, 0, 24);
54
115
  flags = (flags | overrideOr) & overrideAnd;
55
- Porffor.wasm.i32.store8(ptr, flags, 0, 12);
116
+ Porffor.wasm.i32.store8(ptr, flags, 0, 24);
56
117
  }
57
118
  };
58
119
 
@@ -62,13 +123,13 @@ export const __Porffor_object_checkAllFlags = (obj: any, dataAnd: i32, accessorA
62
123
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return false;
63
124
  }
64
125
 
65
- let ptr: i32 = Porffor.wasm`local.get ${obj}` + 5;
126
+ let ptr: i32 = Porffor.wasm`local.get ${obj}`;
66
127
 
67
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
68
- const endPtr: i32 = ptr + size * 14;
128
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
129
+ const endPtr: i32 = ptr + size * 18;
69
130
 
70
- for (; ptr < endPtr; ptr += 14) {
71
- const flags: i32 = Porffor.wasm.i32.load8_u(ptr, 0, 12);
131
+ for (; ptr < endPtr; ptr += 18) {
132
+ const flags: i32 = Porffor.wasm.i32.load8_u(ptr, 0, 24);
72
133
  if (flags & 0b0001) {
73
134
  // accessor
74
135
  if ((flags & accessorAnd) != accessorExpected) return false;
@@ -83,7 +144,7 @@ export const __Porffor_object_checkAllFlags = (obj: any, dataAnd: i32, accessorA
83
144
  };
84
145
 
85
146
  export const __Porffor_object_packAccessor = (get: any, set: any): f64 => {
86
- // pack i32s get & set into a single f64 (i64)
147
+ // pack i32s get & set into a single f64 (reinterpreted u64)
87
148
  Porffor.wasm`
88
149
  local.get ${set}
89
150
  i64.extend_i32_u
@@ -97,7 +158,7 @@ return`;
97
158
  };
98
159
 
99
160
  export const __Porffor_object_accessorGet = (entryPtr: i32): Function|undefined => {
100
- const out: Function = Porffor.wasm.i32.load(entryPtr, 0, 4);
161
+ const out: Function = Porffor.wasm.i32.load(entryPtr, 0, 8);
101
162
 
102
163
  // no getter, return undefined
103
164
  if (Porffor.wasm`local.get ${out}` == 0) {
@@ -108,7 +169,7 @@ export const __Porffor_object_accessorGet = (entryPtr: i32): Function|undefined
108
169
  };
109
170
 
110
171
  export const __Porffor_object_accessorSet = (entryPtr: i32): Function|undefined => {
111
- const out: Function = Porffor.wasm.i32.load(entryPtr, 0, 8);
172
+ const out: Function = Porffor.wasm.i32.load(entryPtr, 0, 12);
112
173
 
113
174
  // no setter, return undefined
114
175
  if (Porffor.wasm`local.get ${out}` == 0) {
@@ -119,49 +180,232 @@ export const __Porffor_object_accessorSet = (entryPtr: i32): Function|undefined
119
180
  };
120
181
 
121
182
 
122
- export const __Porffor_object_lookup = (obj: any, target: any): i32 => {
183
+ export const __Porffor_object_hash = (key: any): i32 => {
184
+ if (Porffor.wasm`local.get ${key+1}` == Porffor.TYPES.symbol) {
185
+ // symbol, hash is just the symbol
186
+ return key as number;
187
+ }
188
+
189
+ // bytestring or string, fnv-1a hash (custom variant)
190
+ // todo/opt: custom wasm simd variant?
191
+
192
+ let ptr: i32 = Porffor.wasm`local.get ${key}`;
193
+ const len: i32 = Porffor.wasm.i32.load(key, 0, 0);
194
+
195
+ let hash: i32 = (2166136261 ^ len) * 16777619;
196
+ if (Porffor.wasm`local.get ${key+1}` == Porffor.TYPES.bytestring) {
197
+ // chunks of 8 bytes via i64.load
198
+ const endPtr: i32 = ptr + len - 8;
199
+ for (; ptr <= endPtr; ptr += 8) {
200
+ Porffor.wasm`
201
+ local x i64
202
+ local.get ${ptr}
203
+ i64.load 0 4
204
+ local.set x
205
+
206
+ local.get ${hash}
207
+ local.get x
208
+ i64.const 32
209
+ i64.shr_u
210
+ i32.wrap_i64
211
+ i32.xor
212
+ i32.const 16777619
213
+ i32.mul
214
+
215
+ local.get x
216
+ i32.wrap_i64
217
+ i32.xor
218
+ i32.const 16777619
219
+ i32.mul
220
+
221
+ local.set ${hash}`;
222
+ }
223
+
224
+ // remaining 0-7 bytes via i64.load and bitwise
225
+ Porffor.wasm`
226
+ local.get ${ptr}
227
+ i64.load 0 4
228
+
229
+ local shift i64
230
+ local.get ${ptr}
231
+ local.get ${endPtr}
232
+ i32.sub
233
+ i32.const 8
234
+ i32.mul
235
+ i64.extend_i32_u
236
+ local.tee shift
237
+
238
+ i64.shl
239
+ local.get shift
240
+ i64.shr_u
241
+ local.set x
242
+
243
+ local.get ${hash}
244
+ local.get x
245
+ i64.const 32
246
+ i64.shr_u
247
+ i32.wrap_i64
248
+ i32.xor
249
+ i32.const 16777619
250
+ i32.mul
251
+
252
+ local.get x
253
+ i32.wrap_i64
254
+ i32.xor
255
+ i32.const 16777619
256
+ i32.mul
257
+
258
+ local.set ${hash}`;
259
+ } else {
260
+ // slow path: string, process like bytestring
261
+ // skips 1 byte per char but we want collisions (false positives) instead of lack there of
262
+ // 4x 16 chars (u64): 0x0012003400560078
263
+ // 4x 8 chars (u32): 0x12345678
264
+ // todo: this doesn't work?
265
+
266
+ const endPtr: i32 = ptr + len * 2 - 8;
267
+ for (; ptr <= endPtr; ptr += 8) {
268
+ Porffor.wasm`
269
+ local.get ${ptr}
270
+ i64.load 0 4
271
+ local.set x
272
+
273
+ local.get ${hash}
274
+ local.get x
275
+ i64.const 48
276
+ i64.shr_u
277
+ i64.const 255
278
+ i64.and
279
+ i64.const 24
280
+ i64.shl
281
+ local.get x
282
+ i64.const 32
283
+ i64.shr_u
284
+ i64.const 255
285
+ i64.and
286
+ i64.const 16
287
+ i64.shl
288
+ i64.or
289
+ local.get x
290
+ i64.const 16
291
+ i64.shr_u
292
+ i64.const 255
293
+ i64.and
294
+ i64.const 8
295
+ i64.shl
296
+ i64.or
297
+ local.get x
298
+ i64.const 255
299
+ i64.and
300
+ i64.or
301
+ i32.wrap_i64
302
+ i32.xor
303
+ i32.const 16777619
304
+ i32.mul
305
+ local.set ${hash}`;
306
+ }
307
+
308
+ // remaining 0-7 bytes via i64.load and bitwise
309
+ Porffor.wasm`
310
+ local.get ${ptr}
311
+ i64.load 0 4
312
+
313
+ local.get ${ptr}
314
+ local.get ${endPtr}
315
+ i32.sub
316
+ i32.const 8
317
+ i32.mul
318
+ i64.extend_i32_u
319
+ local.tee shift
320
+
321
+ i64.shl
322
+ local.get shift
323
+ i64.shr_u
324
+ local.set x
325
+
326
+ local.get ${hash}
327
+ local.get x
328
+ i64.const 48
329
+ i64.shr_u
330
+ i64.const 255
331
+ i64.and
332
+ i64.const 24
333
+ i64.shl
334
+ local.get x
335
+ i64.const 32
336
+ i64.shr_u
337
+ i64.const 255
338
+ i64.and
339
+ i64.const 16
340
+ i64.shl
341
+ i64.or
342
+ local.get x
343
+ i64.const 16
344
+ i64.shr_u
345
+ i64.const 255
346
+ i64.and
347
+ i64.const 8
348
+ i64.shl
349
+ i64.or
350
+ local.get x
351
+ i64.const 255
352
+ i64.and
353
+ i64.or
354
+ i32.wrap_i64
355
+ i32.xor
356
+ i32.const 16777619
357
+ i32.mul
358
+ local.set ${hash}`;
359
+ }
360
+
361
+ return hash;
362
+ };
363
+
364
+ export const __Porffor_object_lookup = (obj: any, target: any, targetHash: i32): i32 => {
123
365
  if (Porffor.wasm`local.get ${obj}` == 0) return -1;
124
366
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
125
367
  obj = __Porffor_object_underlying(obj);
126
368
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return -1;
127
369
  }
128
370
 
129
- const targetType: i32 = Porffor.wasm`local.get ${target+1}`;
130
-
131
- let ptr: i32 = Porffor.wasm`local.get ${obj}` + 5;
132
-
133
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
134
- const endPtr: i32 = ptr + size * 14;
371
+ let ptr: i32 = Porffor.wasm`local.get ${obj}` + 8;
372
+ const endPtr: i32 = ptr + Porffor.wasm.i32.load16_u(obj, 0, 0) * 18;
135
373
 
136
374
  let out: boolean = false;
137
- if (targetType == Porffor.TYPES.symbol) {
138
- for (; ptr < endPtr; ptr += 14) {
139
- const keyRaw: i32 = Porffor.wasm.i32.load(ptr, 0, 0);
140
- if (keyRaw == 0) {
375
+ if (Porffor.wasm`local.get ${target+1}` == Porffor.TYPES.symbol) {
376
+ for (; ptr < endPtr; ptr += 18) {
377
+ const key: i32 = Porffor.wasm.i32.load(ptr, 0, 4);
378
+ if (key == 0) {
141
379
  if (out) break; // ran out of keys
142
380
  out = true;
143
381
  }
144
382
 
145
- if (keyRaw >>> 30 == 3) { // MSB 1 and 2 set, symbol (unset MSB x2)
383
+ if ((key >>> 30) == 3) { // MSB 1 and 2 set, symbol (unset MSB x2)
146
384
  // todo: remove casts once weird bug which breaks unrelated things is fixed (https://github.com/CanadaHonk/porffor/commit/5747f0c1f3a4af95283ebef175cdacb21e332a52)
147
- if ((keyRaw & 0x3FFFFFFF) as symbol == target as symbol) return ptr;
385
+ if ((key & 0x3FFFFFFF) as symbol == target as symbol) return ptr;
148
386
  }
149
387
  }
150
388
  } else {
151
- for (; ptr < endPtr; ptr += 14) {
152
- const keyRaw: i32 = Porffor.wasm.i32.load(ptr, 0, 0);
153
- if (keyRaw == 0) {
389
+ if (targetHash == 0) targetHash = __Porffor_object_hash(target);
390
+ for (; ptr < endPtr; ptr += 18) {
391
+ const hash: i32 = Porffor.wasm.i32.load(ptr, 0, 0);
392
+
393
+ // todo: is below needed anymore?
394
+ if (hash == 0) {
154
395
  if (out) break; // ran out of keys
155
396
  out = true;
156
397
  }
157
398
 
158
- const msb: i32 = keyRaw >>> 30;
159
- if (msb == 0) {
160
- // bytestring
161
- if (Porffor.strcmp(keyRaw as bytestring, target)) return ptr;
162
- } else if (msb == 2) {
163
- // string (unset MSB)
164
- if (Porffor.strcmp((keyRaw & 0x7FFFFFFF) as string, target)) return ptr;
399
+ if (hash == targetHash) {
400
+ const key: i32 = Porffor.wasm.i32.load(ptr, 0, 4);
401
+ const msb: i32 = key >>> 30;
402
+ if (msb == 0) {
403
+ // bytestring
404
+ if (Porffor.strcmp(key as bytestring, target)) return ptr;
405
+ } else if (msb == 2) {
406
+ // string (unset MSB)
407
+ if (Porffor.strcmp((key & 0x7FFFFFFF) as string, target)) return ptr;
408
+ }
165
409
  }
166
410
  }
167
411
  }
@@ -172,9 +416,9 @@ export const __Porffor_object_lookup = (obj: any, target: any): i32 => {
172
416
  export const __Porffor_object_readValue = (entryPtr: i32): any => {
173
417
  Porffor.wasm`
174
418
  local.get ${entryPtr}
175
- f64.load 0 4
419
+ f64.load 0 8
176
420
  local.get ${entryPtr}
177
- i32.load8_u 0 13
421
+ i32.load8_u 0 17
178
422
  return`;
179
423
  };
180
424
 
@@ -184,83 +428,31 @@ export const __Porffor_object_get = (obj: any, key: any): any => {
184
428
 
185
429
  if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot get property of null');
186
430
 
187
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
431
+ const hash: i32 = __Porffor_object_hash(key);
432
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
188
433
  if (entryPtr == -1) {
189
434
  // check prototype chain
190
- const protoKey: bytestring = '__proto__';
191
- let lastProto: any = obj;
192
- if (key != protoKey) {
193
- while (true) {
194
- obj = __Porffor_object_get(obj, protoKey);
195
-
196
- if (Porffor.comptime.flag`hasFunc.#get___String_prototype`) {
197
- if (Porffor.fastOr(
198
- trueType == Porffor.TYPES.string,
199
- trueType == Porffor.TYPES.bytestring,
200
- trueType == Porffor.TYPES.stringobject
201
- )) {
202
- obj = __String_prototype;
203
- }
204
- }
205
-
206
- if (Porffor.comptime.flag`hasFunc.#get___Number_prototype`) {
207
- if (Porffor.fastOr(
208
- trueType == Porffor.TYPES.number,
209
- trueType == Porffor.TYPES.numberobject
210
- )) {
211
- obj = __Number_prototype;
212
- }
213
- }
214
-
215
- if (Porffor.comptime.flag`hasFunc.#get___Boolean_prototype`) {
216
- if (Porffor.fastOr(
217
- trueType == Porffor.TYPES.boolean,
218
- trueType == Porffor.TYPES.booleanobject
219
- )) {
220
- obj = __Boolean_prototype;
221
- }
222
- }
223
-
224
- if (Porffor.comptime.flag`hasFunc.#get___Function_prototype`) {
225
- if (trueType == Porffor.TYPES.function) {
226
- obj = __Function_prototype;
227
- }
228
- }
229
-
230
- if (Porffor.comptime.flag`hasFunc.#get___Array_prototype`) {
231
- if (trueType == Porffor.TYPES.array) {
232
- obj = __Array_prototype;
233
- }
234
- }
235
-
236
- if (Porffor.comptime.flag`hasFunc.#get___Date_prototype`) {
237
- if (trueType == Porffor.TYPES.date) {
238
- obj = __Date_prototype;
239
- }
240
- }
241
-
242
- if (Porffor.comptime.flag`hasFunc.#get___Error_prototype`) {
243
- if (trueType == Porffor.TYPES.error) {
244
- obj = __Error_prototype;
245
- }
246
- }
247
-
248
- if (Porffor.fastOr(obj == null, Porffor.wasm`local.get ${obj}` == Porffor.wasm`local.get ${lastProto}`)) break;
249
- lastProto = obj;
250
-
251
- if ((entryPtr = __Porffor_object_lookup(obj, key)) != -1) break;
252
- }
253
- } else {
254
- let proto: i32 = __Object_prototype;
255
- if (trueType == Porffor.TYPES.function) proto = __Function_prototype;
435
+ obj = __Porffor_object_getPrototypeWithHidden(obj, trueType);
256
436
 
437
+ // todo/opt: put this behind comptime flag if only __proto__ is used
438
+ if (hash == -406948493) if (key == '__proto__') {
439
+ // get prototype
257
440
  Porffor.wasm`
258
- local.get ${proto}
441
+ local.get ${obj}
259
442
  f64.convert_i32_u
260
- i32.const 7 ;; object type
443
+ local.get ${obj+1}
261
444
  return`;
262
445
  }
263
446
 
447
+ let lastProto: any = obj;
448
+ while (true) {
449
+ if ((entryPtr = __Porffor_object_lookup(obj, key, hash)) != -1) break;
450
+
451
+ obj = __Porffor_object_getPrototype(obj);
452
+ if (Porffor.fastOr(obj == null, Porffor.wasm`local.get ${obj}` == Porffor.wasm`local.get ${lastProto}`)) break;
453
+ lastProto = obj;
454
+ }
455
+
264
456
  if (entryPtr == -1) {
265
457
  Porffor.wasm`
266
458
  f64.const 0
@@ -269,8 +461,7 @@ return`;
269
461
  }
270
462
  }
271
463
 
272
- const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
273
-
464
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
274
465
  if (tail & 0b0001) {
275
466
  // accessor descriptor
276
467
  const get: Function = __Porffor_object_accessorGet(entryPtr);
@@ -289,14 +480,17 @@ return`;
289
480
  // data descriptor
290
481
  Porffor.wasm`
291
482
  local.get ${entryPtr}
292
- f64.load 0 4
483
+ f64.load 0 8
293
484
  local.get ${tail}
294
485
  i32.const 8
295
486
  i32.shr_u
296
487
  return`;
297
488
  };
298
489
 
299
- export const __Porffor_object_writeKey = (ptr: i32, key: any): void => {
490
+ export const __Porffor_object_writeKey = (ptr: i32, key: any, hash: i32 = __Porffor_object_hash(key)): void => {
491
+ // write hash to ptr
492
+ Porffor.wasm.i32.store(ptr, hash, 0, 0);
493
+
300
494
  // encode key type
301
495
  let keyEnc: i32 = Porffor.wasm`local.get ${key}`;
302
496
 
@@ -305,11 +499,10 @@ export const __Porffor_object_writeKey = (ptr: i32, key: any): void => {
305
499
  // set MSB 1&2 if symbol
306
500
  else if (Porffor.wasm`local.get ${key+1}` == Porffor.TYPES.symbol) keyEnc |= 0xc0000000;
307
501
 
308
- // write encoded key to ptr
309
- Porffor.wasm.i32.store(ptr, keyEnc, 0, 0);
502
+ // write encoded key to ptr + 4
503
+ Porffor.wasm.i32.store(ptr, keyEnc, 0, 4);
310
504
  };
311
505
 
312
- // todo: check prototype for setters
313
506
  export const __Porffor_object_set = (obj: any, key: any, value: any): any => {
314
507
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
315
508
  obj = __Porffor_object_underlying(obj);
@@ -318,9 +511,53 @@ export const __Porffor_object_set = (obj: any, key: any, value: any): any => {
318
511
 
319
512
  if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot set property of null');
320
513
 
321
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
514
+ const hash: i32 = __Porffor_object_hash(key);
515
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
322
516
  let flags: i32;
323
517
  if (entryPtr == -1) {
518
+ if (hash == -406948493) if (key == '__proto__') {
519
+ // set prototype
520
+ Porffor.wasm`
521
+ local.get ${obj}
522
+ local.get ${obj+1}
523
+ local.get ${value}
524
+ i32.trunc_sat_f64_u
525
+ local.get ${value+1}
526
+ call __Porffor_object_setPrototype`;
527
+ return value;
528
+ }
529
+
530
+ // todo/opt: skip if no setters used
531
+ // check prototype chain for setter
532
+ let proto: any = __Porffor_object_getPrototype(obj);
533
+ if (proto != null) {
534
+ let lastProto: any = proto;
535
+ while (true) {
536
+ if ((entryPtr = __Porffor_object_lookup(proto, key, hash)) != -1) break;
537
+
538
+ proto = __Porffor_object_getPrototype(proto);
539
+ if (Porffor.fastOr(proto == null, Porffor.wasm`local.get ${proto}` == Porffor.wasm`local.get ${lastProto}`)) break;
540
+ lastProto = proto;
541
+ }
542
+
543
+ if (entryPtr != -1) {
544
+ // found possible setter
545
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
546
+ if (tail & 0b0001) {
547
+ // accessor descriptor
548
+ const set: Function = __Porffor_object_accessorSet(entryPtr);
549
+
550
+ // no setter, return early
551
+ if (Porffor.wasm`local.get ${set}` == 0) {
552
+ return value;
553
+ }
554
+
555
+ set.call(obj, value);
556
+ return value;
557
+ }
558
+ }
559
+ }
560
+
324
561
  // add new entry
325
562
  // check if object is inextensible
326
563
  if (__Porffor_object_isInextensible(obj)) {
@@ -328,19 +565,19 @@ export const __Porffor_object_set = (obj: any, key: any, value: any): any => {
328
565
  }
329
566
 
330
567
  // bump size +1
331
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
332
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
568
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
569
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
333
570
 
334
571
  // entryPtr = current end of object
335
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
572
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
336
573
 
337
- __Porffor_object_writeKey(entryPtr, key);
574
+ __Porffor_object_writeKey(entryPtr, key, hash);
338
575
 
339
576
  // flags = writable, enumerable, configurable, not accessor
340
577
  flags = 0b1110;
341
578
  } else {
342
579
  // existing entry, modify it
343
- const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
580
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
344
581
 
345
582
  if (tail & 0b0001) {
346
583
  // accessor descriptor
@@ -365,13 +602,13 @@ export const __Porffor_object_set = (obj: any, key: any, value: any): any => {
365
602
  flags = tail & 0xff;
366
603
  }
367
604
 
368
- // write new value value (lol)
369
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
605
+ // write new value value
606
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
370
607
 
371
608
  // write new tail (value type + flags)
372
609
  Porffor.wasm.i32.store16(entryPtr,
373
610
  flags + (Porffor.wasm`local.get ${value+1}` << 8),
374
- 0, 12);
611
+ 0, 16);
375
612
 
376
613
  return value;
377
614
  };
@@ -384,9 +621,53 @@ export const __Porffor_object_setStrict = (obj: any, key: any, value: any): any
384
621
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return value;
385
622
  }
386
623
 
387
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
624
+ const hash: i32 = __Porffor_object_hash(key);
625
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
388
626
  let flags: i32;
389
627
  if (entryPtr == -1) {
628
+ if (hash == -406948493) if (key == '__proto__') {
629
+ // set prototype
630
+ Porffor.wasm`
631
+ local.get ${obj}
632
+ local.get ${obj+1}
633
+ local.get ${value}
634
+ i32.trunc_sat_f64_u
635
+ local.get ${value+1}
636
+ call __Porffor_object_setPrototype`;
637
+ return value;
638
+ }
639
+
640
+ // todo/opt: skip if no setters used
641
+ // check prototype chain for setter
642
+ let proto: any = __Porffor_object_getPrototype(obj);
643
+ if (proto != null) {
644
+ let lastProto: any = proto;
645
+ while (true) {
646
+ if ((entryPtr = __Porffor_object_lookup(proto, key, hash)) != -1) break;
647
+
648
+ proto = __Porffor_object_getPrototype(proto);
649
+ if (Porffor.fastOr(proto == null, Porffor.wasm`local.get ${proto}` == Porffor.wasm`local.get ${lastProto}`)) break;
650
+ lastProto = proto;
651
+ }
652
+
653
+ if (entryPtr != -1) {
654
+ // found possible setter
655
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
656
+ if (tail & 0b0001) {
657
+ // accessor descriptor
658
+ const set: Function = __Porffor_object_accessorSet(entryPtr);
659
+
660
+ // no setter, return early
661
+ if (Porffor.wasm`local.get ${set}` == 0) {
662
+ return value;
663
+ }
664
+
665
+ set.call(obj, value);
666
+ return value;
667
+ }
668
+ }
669
+ }
670
+
390
671
  // add new entry
391
672
  // check if object is inextensible
392
673
  if (__Porffor_object_isInextensible(obj)) {
@@ -394,19 +675,19 @@ export const __Porffor_object_setStrict = (obj: any, key: any, value: any): any
394
675
  }
395
676
 
396
677
  // bump size +1
397
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
398
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
678
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
679
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
399
680
 
400
681
  // entryPtr = current end of object
401
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
682
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
402
683
 
403
- __Porffor_object_writeKey(entryPtr, key);
684
+ __Porffor_object_writeKey(entryPtr, key, hash);
404
685
 
405
686
  // flags = writable, enumerable, configurable, not accessor
406
687
  flags = 0b1110;
407
688
  } else {
408
689
  // existing entry, modify it
409
- const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
690
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
410
691
 
411
692
  if (tail & 0b0001) {
412
693
  // accessor descriptor
@@ -432,12 +713,12 @@ export const __Porffor_object_setStrict = (obj: any, key: any, value: any): any
432
713
  }
433
714
 
434
715
  // write new value value (lol)
435
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
716
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
436
717
 
437
718
  // write new tail (value type + flags)
438
719
  Porffor.wasm.i32.store16(entryPtr,
439
720
  flags + (Porffor.wasm`local.get ${value+1}` << 8),
440
- 0, 12);
721
+ 0, 16);
441
722
 
442
723
  return value;
443
724
  };
@@ -448,7 +729,8 @@ export const __Porffor_object_define = (obj: any, key: any, value: any, flags: i
448
729
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return;
449
730
  }
450
731
 
451
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
732
+ const hash: i32 = __Porffor_object_hash(key);
733
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
452
734
  if (entryPtr == -1) {
453
735
  // add new entry
454
736
  // check if object is inextensible
@@ -457,16 +739,16 @@ export const __Porffor_object_define = (obj: any, key: any, value: any, flags: i
457
739
  }
458
740
 
459
741
  // bump size +1
460
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
461
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
742
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
743
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
462
744
 
463
745
  // entryPtr = current end of object
464
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
746
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
465
747
 
466
- __Porffor_object_writeKey(entryPtr, key);
748
+ __Porffor_object_writeKey(entryPtr, key, hash);
467
749
  } else {
468
750
  // existing entry, check and maybe modify it
469
- const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
751
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
470
752
 
471
753
  if ((tail & 0b0010) == 0) {
472
754
  // not already configurable, check to see if we can redefine
@@ -484,9 +766,9 @@ export const __Porffor_object_define = (obj: any, key: any, value: any, flags: i
484
766
  // if already non-writable, check value isn't being changed
485
767
  Porffor.wasm`
486
768
  local.get ${entryPtr}
487
- f64.load 0 4
769
+ f64.load 0 8
488
770
  local.get ${entryPtr}
489
- i32.load8_u 0 13
771
+ i32.load8_u 0 17
490
772
 
491
773
  local.get ${value}
492
774
  local.get ${value+1}
@@ -503,21 +785,20 @@ local.set ${err}`;
503
785
  }
504
786
 
505
787
  // write new value value (lol)
506
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
788
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
507
789
 
508
790
  // write new tail (value type + flags)
509
791
  Porffor.wasm.i32.store16(entryPtr,
510
792
  flags + (Porffor.wasm`local.get ${value+1}` << 8),
511
- 0, 12);
793
+ 0, 16);
512
794
  };
513
795
 
514
796
  export const __Porffor_object_delete = (obj: any, key: any): boolean => {
515
797
  if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot delete property of null');
516
798
 
517
- if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
518
- if (Porffor.rawType(obj) != Porffor.TYPES.object) {
519
- // todo: support non-pure objects
520
- return true;
799
+ if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
800
+ obj = __Porffor_object_underlying(obj);
801
+ if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return true;
521
802
  }
522
803
 
523
804
  const entryPtr: i32 = __Porffor_object_lookup(obj, key);
@@ -526,17 +807,17 @@ export const __Porffor_object_delete = (obj: any, key: any): boolean => {
526
807
  return true;
527
808
  }
528
809
 
529
- const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
810
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
530
811
  if (!(tail & 0b0010)) {
531
812
  // not configurable
532
813
  return false;
533
814
  }
534
815
 
535
- const ind: i32 = (entryPtr - Porffor.wasm`local.get ${obj}`) / 14;
816
+ const ind: i32 = (entryPtr - Porffor.wasm`local.get ${obj}`) / 18;
536
817
 
537
818
  // decrement size
538
- let size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
539
- Porffor.wasm.i32.store(obj, --size, 0, 0);
819
+ let size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
820
+ Porffor.wasm.i32.store16(obj, --size, 0, 0);
540
821
 
541
822
  if (size > ind) {
542
823
  // offset all elements after by -1 ind
@@ -544,16 +825,16 @@ export const __Porffor_object_delete = (obj: any, key: any): boolean => {
544
825
  ;; dst = entryPtr
545
826
  local.get ${entryPtr}
546
827
 
547
- ;; src = entryPtr + 14 (+ 1 entry)
828
+ ;; src = entryPtr + 18 (+ 1 entry)
548
829
  local.get ${entryPtr}
549
- i32.const 14
830
+ i32.const 18
550
831
  i32.add
551
832
 
552
- ;; size = (size - ind) * 14
833
+ ;; size = (size - ind) * 18
553
834
  local.get ${size}
554
835
  local.get ${ind}
555
836
  i32.sub
556
- i32.const 14
837
+ i32.const 18
557
838
  i32.mul
558
839
 
559
840
  memory.copy 0 0`;
@@ -565,10 +846,9 @@ memory.copy 0 0`;
565
846
  export const __Porffor_object_deleteStrict = (obj: any, key: any): boolean => {
566
847
  if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot delete property of null');
567
848
 
568
- if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
569
- if (Porffor.rawType(obj) != Porffor.TYPES.object) {
570
- // todo: support non-pure objects
571
- return true;
849
+ if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
850
+ obj = __Porffor_object_underlying(obj);
851
+ if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return true;
572
852
  }
573
853
 
574
854
  const entryPtr: i32 = __Porffor_object_lookup(obj, key);
@@ -577,17 +857,17 @@ export const __Porffor_object_deleteStrict = (obj: any, key: any): boolean => {
577
857
  return true;
578
858
  }
579
859
 
580
- const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
860
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
581
861
  if (!(tail & 0b0010)) {
582
862
  // not configurable
583
863
  throw new TypeError('Cannot delete non-configurable property of object');
584
864
  }
585
865
 
586
- const ind: i32 = (entryPtr - Porffor.wasm`local.get ${obj}`) / 14;
866
+ const ind: i32 = (entryPtr - Porffor.wasm`local.get ${obj}`) / 18;
587
867
 
588
868
  // decrement size
589
- let size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
590
- Porffor.wasm.i32.store(obj, --size, 0, 0);
869
+ let size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
870
+ Porffor.wasm.i32.store16(obj, --size, 0, 0);
591
871
 
592
872
  if (size > ind) {
593
873
  // offset all elements after by -1 ind
@@ -595,16 +875,16 @@ export const __Porffor_object_deleteStrict = (obj: any, key: any): boolean => {
595
875
  ;; dst = entryPtr
596
876
  local.get ${entryPtr}
597
877
 
598
- ;; src = entryPtr + 14 (+ 1 entry)
878
+ ;; src = entryPtr + 18 (+ 1 entry)
599
879
  local.get ${entryPtr}
600
- i32.const 14
880
+ i32.const 18
601
881
  i32.add
602
882
 
603
- ;; size = (size - ind) * 14
883
+ ;; size = (size - ind) * 18
604
884
  local.get ${size}
605
885
  local.get ${ind}
606
886
  i32.sub
607
- i32.const 14
887
+ i32.const 18
608
888
  i32.mul
609
889
 
610
890
  memory.copy 0 0`;
@@ -615,156 +895,155 @@ memory.copy 0 0`;
615
895
 
616
896
 
617
897
  export const __Porffor_object_isEnumerable = (entryPtr: i32): boolean => {
618
- const out: boolean = Porffor.wasm.i32.load8_u(entryPtr, 0, 12) & 0b0100;
619
- return out;
620
- };
621
-
622
-
623
- export const __Porffor_object_isObject = (arg: any): boolean => {
624
- const t: i32 = Porffor.wasm`local.get ${arg+1}`;
625
- return Porffor.fastAnd(
626
- arg != 0, // null
627
- t > 0x05,
628
- t != Porffor.TYPES.string,
629
- t != Porffor.TYPES.bytestring,
630
- );
631
- };
632
-
633
- export const __Porffor_object_isObjectOrNull = (arg: any): boolean => {
634
- const t: i32 = Porffor.wasm`local.get ${arg+1}`;
635
- return Porffor.fastAnd(
636
- t > 0x05,
637
- t != Porffor.TYPES.string,
638
- t != Porffor.TYPES.bytestring,
639
- );
640
- };
641
-
642
- export const __Porffor_object_isObjectOrSymbol = (arg: any): boolean => {
643
- const t: i32 = Porffor.wasm`local.get ${arg+1}`;
644
- return Porffor.fastAnd(
645
- arg != 0, // null
646
- t > 0x04,
647
- t != Porffor.TYPES.string,
648
- t != Porffor.TYPES.bytestring,
649
- );
898
+ return (Porffor.wasm.i32.load8_u(entryPtr, 0, 16) & 0b0100) as boolean;
650
899
  };
651
900
 
652
901
 
653
902
  // used for { foo: 5 }
654
903
  export const __Porffor_object_expr_init = (obj: any, key: any, value: any): void => {
655
904
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
656
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
905
+
906
+ const hash: i32 = __Porffor_object_hash(key);
907
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
657
908
  if (entryPtr == -1) {
909
+ if (key == '__proto__') {
910
+ // set prototype
911
+ Porffor.wasm`
912
+ local.get ${obj}
913
+ local.get ${obj+1}
914
+ local.get ${value}
915
+ i32.trunc_sat_f64_u
916
+ local.get ${value+1}
917
+ call __Porffor_object_setPrototype`;
918
+ return value;
919
+ }
920
+
658
921
  // add new entry
659
922
  // bump size +1
660
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
661
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
923
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
924
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
662
925
 
663
926
  // entryPtr = current end of object
664
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
665
-
666
- __Porffor_object_writeKey(entryPtr, key);
927
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
928
+ __Porffor_object_writeKey(entryPtr, key, hash);
667
929
  }
668
930
 
669
- // write new value value (lol)
670
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
931
+ // write new value value
932
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
671
933
 
672
934
  // write new tail (value type + flags)
673
935
  // flags = writable, enumerable, configurable, not accessor
674
936
  Porffor.wasm.i32.store16(entryPtr,
675
937
  0b1110 + (Porffor.wasm`local.get ${value+1}` << 8),
676
- 0, 12);
938
+ 0, 16);
677
939
  };
678
940
 
679
941
  export const __Porffor_object_expr_initWithFlags = (obj: any, key: any, value: any, flags: i32): void => {
680
942
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
681
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
943
+
944
+ const hash: i32 = __Porffor_object_hash(key);
945
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
682
946
  if (entryPtr == -1) {
947
+ if (key == '__proto__') {
948
+ // set prototype
949
+ Porffor.wasm`
950
+ local.get ${obj}
951
+ local.get ${obj+1}
952
+ local.get ${value}
953
+ i32.trunc_sat_f64_u
954
+ local.get ${value+1}
955
+ call __Porffor_object_setPrototype`;
956
+ return value;
957
+ }
958
+
683
959
  // add new entry
684
960
  // bump size +1
685
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
686
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
961
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
962
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
687
963
 
688
964
  // entryPtr = current end of object
689
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
690
-
691
- __Porffor_object_writeKey(entryPtr, key);
965
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
966
+ __Porffor_object_writeKey(entryPtr, key, hash);
692
967
  }
693
968
 
694
- // write new value value (lol)
695
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
969
+ // write new value value
970
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
696
971
 
697
972
  // write new tail (value type + flags)
698
973
  Porffor.wasm.i32.store16(entryPtr,
699
974
  flags + (Porffor.wasm`local.get ${value+1}` << 8),
700
- 0, 12);
975
+ 0, 16);
701
976
  };
702
977
 
703
978
  // used for { get foo() {} }
704
979
  export const __Porffor_object_expr_get = (obj: any, key: any, get: any): void => {
705
980
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
706
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
981
+
982
+ const hash: i32 = __Porffor_object_hash(key);
983
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
707
984
  let set: any = undefined;
708
985
  if (entryPtr == -1) {
709
986
  // add new entry
710
987
  // bump size +1
711
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
712
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
988
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
989
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
713
990
 
714
991
  // entryPtr = current end of object
715
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
716
-
717
- __Porffor_object_writeKey(entryPtr, key);
992
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
993
+ __Porffor_object_writeKey(entryPtr, key, hash);
718
994
  } else {
719
995
  // existing entry, keep set (if exists)
720
996
  set = __Porffor_object_accessorSet(entryPtr);
721
997
  }
722
998
 
723
- // write new value value (lol)
724
- Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 4);
999
+ // write new value value
1000
+ Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 8);
725
1001
 
726
1002
  // write new tail (value type + flags)
727
1003
  // flags = writable, enumerable, configurable, accessor
728
1004
  Porffor.wasm.i32.store16(entryPtr,
729
1005
  0b1111 + (Porffor.TYPES.number << 8),
730
- 0, 12);
1006
+ 0, 16);
731
1007
  };
732
1008
 
733
1009
  // used for { set foo(v) {} }
734
1010
  export const __Porffor_object_expr_set = (obj: any, key: any, set: any): void => {
735
1011
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
736
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
1012
+
1013
+ const hash: i32 = __Porffor_object_hash(key);
1014
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
737
1015
  let get: any = undefined;
738
1016
  if (entryPtr == -1) {
739
1017
  // add new entry
740
1018
  // bump size +1
741
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
742
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
1019
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
1020
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
743
1021
 
744
1022
  // entryPtr = current end of object
745
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
746
-
747
- __Porffor_object_writeKey(entryPtr, key);
1023
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
1024
+ __Porffor_object_writeKey(entryPtr, key, hash);
748
1025
  } else {
749
1026
  // existing entry, keep set (if exists)
750
1027
  get = __Porffor_object_accessorGet(entryPtr);
751
1028
  }
752
1029
 
753
- // write new value value (lol)
754
- Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 4);
1030
+ // write new value value
1031
+ Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 8);
755
1032
 
756
1033
  // write new tail (value type + flags)
757
1034
  // flags = writable, enumerable, configurable, accessor
758
1035
  Porffor.wasm.i32.store16(entryPtr,
759
1036
  0b1111 + (Porffor.TYPES.number << 8),
760
- 0, 12);
1037
+ 0, 16);
761
1038
  };
762
1039
 
763
1040
 
764
1041
  // used for { foo: 5 }
765
1042
  export const __Porffor_object_class_value = (obj: any, key: any, value: any): void => {
766
1043
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
767
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
1044
+
1045
+ const hash: i32 = __Porffor_object_hash(key);
1046
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
768
1047
  if (entryPtr == -1) {
769
1048
  // add new entry
770
1049
  // check if object is inextensible
@@ -773,29 +1052,30 @@ export const __Porffor_object_class_value = (obj: any, key: any, value: any): vo
773
1052
  }
774
1053
 
775
1054
  // bump size +1
776
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
777
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
1055
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
1056
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
778
1057
 
779
1058
  // entryPtr = current end of object
780
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
781
-
782
- __Porffor_object_writeKey(entryPtr, key);
1059
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
1060
+ __Porffor_object_writeKey(entryPtr, key, hash);
783
1061
  }
784
1062
 
785
- // write new value value (lol)
786
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
1063
+ // write new value value
1064
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
787
1065
 
788
1066
  // write new tail (value type + flags)
789
1067
  // flags = writable, enumerable, configurable, not accessor
790
1068
  Porffor.wasm.i32.store16(entryPtr,
791
1069
  0b1110 + (Porffor.wasm`local.get ${value+1}` << 8),
792
- 0, 12);
1070
+ 0, 16);
793
1071
  };
794
1072
 
795
1073
  // used for { foo() {} }
796
1074
  export const __Porffor_object_class_method = (obj: any, key: any, value: any): void => {
797
1075
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
798
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
1076
+
1077
+ const hash: i32 = __Porffor_object_hash(key);
1078
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
799
1079
  if (entryPtr == -1) {
800
1080
  // add new entry
801
1081
  // check if object is inextensible
@@ -804,29 +1084,30 @@ export const __Porffor_object_class_method = (obj: any, key: any, value: any): v
804
1084
  }
805
1085
 
806
1086
  // bump size +1
807
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
808
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
1087
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
1088
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
809
1089
 
810
1090
  // entryPtr = current end of object
811
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
812
-
813
- __Porffor_object_writeKey(entryPtr, key);
1091
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
1092
+ __Porffor_object_writeKey(entryPtr, key, hash);
814
1093
  }
815
1094
 
816
1095
  // write new value value (lol)
817
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
1096
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
818
1097
 
819
1098
  // write new tail (value type + flags)
820
1099
  // flags = writable, enumerable, configurable, not accessor
821
1100
  Porffor.wasm.i32.store16(entryPtr,
822
1101
  0b1010 + (Porffor.wasm`local.get ${value+1}` << 8),
823
- 0, 12);
1102
+ 0, 16);
824
1103
  };
825
1104
 
826
1105
  // used for { get foo() {} }
827
1106
  export const __Porffor_object_class_get = (obj: any, key: any, get: any): void => {
828
1107
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
829
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
1108
+
1109
+ const hash: i32 = __Porffor_object_hash(key);
1110
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
830
1111
  let set: any = undefined;
831
1112
  if (entryPtr == -1) {
832
1113
  // add new entry
@@ -836,32 +1117,33 @@ export const __Porffor_object_class_get = (obj: any, key: any, get: any): void =
836
1117
  }
837
1118
 
838
1119
  // bump size +1
839
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
840
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
1120
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
1121
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
841
1122
 
842
1123
  // entryPtr = current end of object
843
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
844
-
845
- __Porffor_object_writeKey(entryPtr, key);
1124
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
1125
+ __Porffor_object_writeKey(entryPtr, key, hash);
846
1126
  } else {
847
1127
  // existing entry, keep set (if exists)
848
1128
  set = __Porffor_object_accessorSet(entryPtr);
849
1129
  }
850
1130
 
851
1131
  // write new value value (lol)
852
- Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 4);
1132
+ Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 8);
853
1133
 
854
1134
  // write new tail (value type + flags)
855
1135
  // flags = writable, enumerable, configurable, accessor
856
1136
  Porffor.wasm.i32.store16(entryPtr,
857
1137
  0b1011 + (Porffor.TYPES.number << 8),
858
- 0, 12);
1138
+ 0, 16);
859
1139
  };
860
1140
 
861
1141
  // used for { set foo(v) {} }
862
1142
  export const __Porffor_object_class_set = (obj: any, key: any, set: any): void => {
863
1143
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
864
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
1144
+
1145
+ const hash: i32 = __Porffor_object_hash(key);
1146
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
865
1147
  let get: any = undefined;
866
1148
  if (entryPtr == -1) {
867
1149
  // add new entry
@@ -871,24 +1153,23 @@ export const __Porffor_object_class_set = (obj: any, key: any, set: any): void =
871
1153
  }
872
1154
 
873
1155
  // bump size +1
874
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
875
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
1156
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
1157
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
876
1158
 
877
1159
  // entryPtr = current end of object
878
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
879
-
880
- __Porffor_object_writeKey(entryPtr, key);
1160
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
1161
+ __Porffor_object_writeKey(entryPtr, key, hash);
881
1162
  } else {
882
1163
  // existing entry, keep set (if exists)
883
1164
  get = __Porffor_object_accessorGet(entryPtr);
884
1165
  }
885
1166
 
886
1167
  // write new value value (lol)
887
- Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 4);
1168
+ Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 8);
888
1169
 
889
1170
  // write new tail (value type + flags)
890
1171
  // flags = writable, enumerable, configurable, accessor
891
1172
  Porffor.wasm.i32.store16(entryPtr,
892
1173
  0b1011 + (Porffor.TYPES.number << 8),
893
- 0, 12);
1174
+ 0, 16);
894
1175
  };