porffor 0.55.22 → 0.55.24

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,234 @@ 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 unused so just return 0
186
+ return 0;
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) {
154
- if (out) break; // ran out of keys
155
- out = true;
156
- }
157
-
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;
389
+ for (; ptr < endPtr; ptr += 18) {
390
+ if (Porffor.wasm.i32.load(ptr, 0, 0) == targetHash) {
391
+ const key: i32 = Porffor.wasm.i32.load(ptr, 0, 4);
392
+ Porffor.wasm`
393
+ local.get ${key}
394
+ i32.const 2147483647
395
+ i32.and
396
+
397
+ i32.const 67 ;; bytestring
398
+ i32.const 195 ;; string
399
+ local.get ${key}
400
+ i32.const 30
401
+ i32.shr_u
402
+ select
403
+
404
+ local.get ${target}
405
+ local.get ${target+1}
406
+ call __Porffor_strcmp
407
+ if 64
408
+ local.get ${ptr}
409
+ return
410
+ end`;
165
411
  }
166
412
  }
167
413
  }
@@ -172,9 +418,9 @@ export const __Porffor_object_lookup = (obj: any, target: any): i32 => {
172
418
  export const __Porffor_object_readValue = (entryPtr: i32): any => {
173
419
  Porffor.wasm`
174
420
  local.get ${entryPtr}
175
- f64.load 0 4
421
+ f64.load 0 8
176
422
  local.get ${entryPtr}
177
- i32.load8_u 0 13
423
+ i32.load8_u 0 17
178
424
  return`;
179
425
  };
180
426
 
@@ -184,83 +430,31 @@ export const __Porffor_object_get = (obj: any, key: any): any => {
184
430
 
185
431
  if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot get property of null');
186
432
 
187
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
433
+ const hash: i32 = __Porffor_object_hash(key);
434
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
188
435
  if (entryPtr == -1) {
189
436
  // 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;
437
+ obj = __Porffor_object_getPrototypeWithHidden(obj, trueType);
256
438
 
439
+ // todo/opt: put this behind comptime flag if only __proto__ is used
440
+ if (hash == -406948493) if (key == '__proto__') {
441
+ // get prototype
257
442
  Porffor.wasm`
258
- local.get ${proto}
443
+ local.get ${obj}
259
444
  f64.convert_i32_u
260
- i32.const 7 ;; object type
445
+ local.get ${obj+1}
261
446
  return`;
262
447
  }
263
448
 
449
+ let lastProto: any = obj;
450
+ while (true) {
451
+ if ((entryPtr = __Porffor_object_lookup(obj, key, hash)) != -1) break;
452
+
453
+ obj = __Porffor_object_getPrototype(obj);
454
+ if (Porffor.fastOr(obj == null, Porffor.wasm`local.get ${obj}` == Porffor.wasm`local.get ${lastProto}`)) break;
455
+ lastProto = obj;
456
+ }
457
+
264
458
  if (entryPtr == -1) {
265
459
  Porffor.wasm`
266
460
  f64.const 0
@@ -269,8 +463,7 @@ return`;
269
463
  }
270
464
  }
271
465
 
272
- const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
273
-
466
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
274
467
  if (tail & 0b0001) {
275
468
  // accessor descriptor
276
469
  const get: Function = __Porffor_object_accessorGet(entryPtr);
@@ -289,14 +482,17 @@ return`;
289
482
  // data descriptor
290
483
  Porffor.wasm`
291
484
  local.get ${entryPtr}
292
- f64.load 0 4
485
+ f64.load 0 8
293
486
  local.get ${tail}
294
487
  i32.const 8
295
488
  i32.shr_u
296
489
  return`;
297
490
  };
298
491
 
299
- export const __Porffor_object_writeKey = (ptr: i32, key: any): void => {
492
+ export const __Porffor_object_writeKey = (ptr: i32, key: any, hash: i32 = __Porffor_object_hash(key)): void => {
493
+ // write hash to ptr
494
+ Porffor.wasm.i32.store(ptr, hash, 0, 0);
495
+
300
496
  // encode key type
301
497
  let keyEnc: i32 = Porffor.wasm`local.get ${key}`;
302
498
 
@@ -305,11 +501,10 @@ export const __Porffor_object_writeKey = (ptr: i32, key: any): void => {
305
501
  // set MSB 1&2 if symbol
306
502
  else if (Porffor.wasm`local.get ${key+1}` == Porffor.TYPES.symbol) keyEnc |= 0xc0000000;
307
503
 
308
- // write encoded key to ptr
309
- Porffor.wasm.i32.store(ptr, keyEnc, 0, 0);
504
+ // write encoded key to ptr + 4
505
+ Porffor.wasm.i32.store(ptr, keyEnc, 0, 4);
310
506
  };
311
507
 
312
- // todo: check prototype for setters
313
508
  export const __Porffor_object_set = (obj: any, key: any, value: any): any => {
314
509
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
315
510
  obj = __Porffor_object_underlying(obj);
@@ -318,9 +513,53 @@ export const __Porffor_object_set = (obj: any, key: any, value: any): any => {
318
513
 
319
514
  if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot set property of null');
320
515
 
321
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
516
+ const hash: i32 = __Porffor_object_hash(key);
517
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
322
518
  let flags: i32;
323
519
  if (entryPtr == -1) {
520
+ if (hash == -406948493) if (key == '__proto__') {
521
+ // set prototype
522
+ Porffor.wasm`
523
+ local.get ${obj}
524
+ local.get ${obj+1}
525
+ local.get ${value}
526
+ i32.trunc_sat_f64_u
527
+ local.get ${value+1}
528
+ call __Porffor_object_setPrototype`;
529
+ return value;
530
+ }
531
+
532
+ // todo/opt: skip if no setters used
533
+ // check prototype chain for setter
534
+ let proto: any = __Porffor_object_getPrototype(obj);
535
+ if (proto != null) {
536
+ let lastProto: any = proto;
537
+ while (true) {
538
+ if ((entryPtr = __Porffor_object_lookup(proto, key, hash)) != -1) break;
539
+
540
+ proto = __Porffor_object_getPrototype(proto);
541
+ if (Porffor.fastOr(proto == null, Porffor.wasm`local.get ${proto}` == Porffor.wasm`local.get ${lastProto}`)) break;
542
+ lastProto = proto;
543
+ }
544
+
545
+ if (entryPtr != -1) {
546
+ // found possible setter
547
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
548
+ if (tail & 0b0001) {
549
+ // accessor descriptor
550
+ const set: Function = __Porffor_object_accessorSet(entryPtr);
551
+
552
+ // no setter, return early
553
+ if (Porffor.wasm`local.get ${set}` == 0) {
554
+ return value;
555
+ }
556
+
557
+ set.call(obj, value);
558
+ return value;
559
+ }
560
+ }
561
+ }
562
+
324
563
  // add new entry
325
564
  // check if object is inextensible
326
565
  if (__Porffor_object_isInextensible(obj)) {
@@ -328,19 +567,19 @@ export const __Porffor_object_set = (obj: any, key: any, value: any): any => {
328
567
  }
329
568
 
330
569
  // bump size +1
331
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
332
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
570
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
571
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
333
572
 
334
573
  // entryPtr = current end of object
335
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
574
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
336
575
 
337
- __Porffor_object_writeKey(entryPtr, key);
576
+ __Porffor_object_writeKey(entryPtr, key, hash);
338
577
 
339
578
  // flags = writable, enumerable, configurable, not accessor
340
579
  flags = 0b1110;
341
580
  } else {
342
581
  // existing entry, modify it
343
- const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
582
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
344
583
 
345
584
  if (tail & 0b0001) {
346
585
  // accessor descriptor
@@ -365,13 +604,13 @@ export const __Porffor_object_set = (obj: any, key: any, value: any): any => {
365
604
  flags = tail & 0xff;
366
605
  }
367
606
 
368
- // write new value value (lol)
369
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
607
+ // write new value value
608
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
370
609
 
371
610
  // write new tail (value type + flags)
372
611
  Porffor.wasm.i32.store16(entryPtr,
373
612
  flags + (Porffor.wasm`local.get ${value+1}` << 8),
374
- 0, 12);
613
+ 0, 16);
375
614
 
376
615
  return value;
377
616
  };
@@ -384,9 +623,53 @@ export const __Porffor_object_setStrict = (obj: any, key: any, value: any): any
384
623
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return value;
385
624
  }
386
625
 
387
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
626
+ const hash: i32 = __Porffor_object_hash(key);
627
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
388
628
  let flags: i32;
389
629
  if (entryPtr == -1) {
630
+ if (hash == -406948493) if (key == '__proto__') {
631
+ // set prototype
632
+ Porffor.wasm`
633
+ local.get ${obj}
634
+ local.get ${obj+1}
635
+ local.get ${value}
636
+ i32.trunc_sat_f64_u
637
+ local.get ${value+1}
638
+ call __Porffor_object_setPrototype`;
639
+ return value;
640
+ }
641
+
642
+ // todo/opt: skip if no setters used
643
+ // check prototype chain for setter
644
+ let proto: any = __Porffor_object_getPrototype(obj);
645
+ if (proto != null) {
646
+ let lastProto: any = proto;
647
+ while (true) {
648
+ if ((entryPtr = __Porffor_object_lookup(proto, key, hash)) != -1) break;
649
+
650
+ proto = __Porffor_object_getPrototype(proto);
651
+ if (Porffor.fastOr(proto == null, Porffor.wasm`local.get ${proto}` == Porffor.wasm`local.get ${lastProto}`)) break;
652
+ lastProto = proto;
653
+ }
654
+
655
+ if (entryPtr != -1) {
656
+ // found possible setter
657
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
658
+ if (tail & 0b0001) {
659
+ // accessor descriptor
660
+ const set: Function = __Porffor_object_accessorSet(entryPtr);
661
+
662
+ // no setter, return early
663
+ if (Porffor.wasm`local.get ${set}` == 0) {
664
+ return value;
665
+ }
666
+
667
+ set.call(obj, value);
668
+ return value;
669
+ }
670
+ }
671
+ }
672
+
390
673
  // add new entry
391
674
  // check if object is inextensible
392
675
  if (__Porffor_object_isInextensible(obj)) {
@@ -394,19 +677,19 @@ export const __Porffor_object_setStrict = (obj: any, key: any, value: any): any
394
677
  }
395
678
 
396
679
  // bump size +1
397
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
398
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
680
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
681
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
399
682
 
400
683
  // entryPtr = current end of object
401
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
684
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
402
685
 
403
- __Porffor_object_writeKey(entryPtr, key);
686
+ __Porffor_object_writeKey(entryPtr, key, hash);
404
687
 
405
688
  // flags = writable, enumerable, configurable, not accessor
406
689
  flags = 0b1110;
407
690
  } else {
408
691
  // existing entry, modify it
409
- const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
692
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
410
693
 
411
694
  if (tail & 0b0001) {
412
695
  // accessor descriptor
@@ -432,12 +715,12 @@ export const __Porffor_object_setStrict = (obj: any, key: any, value: any): any
432
715
  }
433
716
 
434
717
  // write new value value (lol)
435
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
718
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
436
719
 
437
720
  // write new tail (value type + flags)
438
721
  Porffor.wasm.i32.store16(entryPtr,
439
722
  flags + (Porffor.wasm`local.get ${value+1}` << 8),
440
- 0, 12);
723
+ 0, 16);
441
724
 
442
725
  return value;
443
726
  };
@@ -448,7 +731,8 @@ export const __Porffor_object_define = (obj: any, key: any, value: any, flags: i
448
731
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return;
449
732
  }
450
733
 
451
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
734
+ const hash: i32 = __Porffor_object_hash(key);
735
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
452
736
  if (entryPtr == -1) {
453
737
  // add new entry
454
738
  // check if object is inextensible
@@ -457,16 +741,16 @@ export const __Porffor_object_define = (obj: any, key: any, value: any, flags: i
457
741
  }
458
742
 
459
743
  // bump size +1
460
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
461
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
744
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
745
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
462
746
 
463
747
  // entryPtr = current end of object
464
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
748
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
465
749
 
466
- __Porffor_object_writeKey(entryPtr, key);
750
+ __Porffor_object_writeKey(entryPtr, key, hash);
467
751
  } else {
468
752
  // existing entry, check and maybe modify it
469
- const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
753
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
470
754
 
471
755
  if ((tail & 0b0010) == 0) {
472
756
  // not already configurable, check to see if we can redefine
@@ -484,9 +768,9 @@ export const __Porffor_object_define = (obj: any, key: any, value: any, flags: i
484
768
  // if already non-writable, check value isn't being changed
485
769
  Porffor.wasm`
486
770
  local.get ${entryPtr}
487
- f64.load 0 4
771
+ f64.load 0 8
488
772
  local.get ${entryPtr}
489
- i32.load8_u 0 13
773
+ i32.load8_u 0 17
490
774
 
491
775
  local.get ${value}
492
776
  local.get ${value+1}
@@ -503,40 +787,39 @@ local.set ${err}`;
503
787
  }
504
788
 
505
789
  // write new value value (lol)
506
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
790
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
507
791
 
508
792
  // write new tail (value type + flags)
509
793
  Porffor.wasm.i32.store16(entryPtr,
510
794
  flags + (Porffor.wasm`local.get ${value+1}` << 8),
511
- 0, 12);
795
+ 0, 16);
512
796
  };
513
797
 
514
798
  export const __Porffor_object_delete = (obj: any, key: any): boolean => {
515
799
  if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot delete property of null');
516
800
 
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;
801
+ if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
802
+ obj = __Porffor_object_underlying(obj);
803
+ if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return true;
521
804
  }
522
805
 
523
- const entryPtr: i32 = __Porffor_object_lookup(obj, key);
806
+ const entryPtr: i32 = __Porffor_object_lookup(obj, key, __Porffor_object_hash(key));
524
807
  if (entryPtr == -1) {
525
808
  // not found, stop
526
809
  return true;
527
810
  }
528
811
 
529
- const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
812
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
530
813
  if (!(tail & 0b0010)) {
531
814
  // not configurable
532
815
  return false;
533
816
  }
534
817
 
535
- const ind: i32 = (entryPtr - Porffor.wasm`local.get ${obj}`) / 14;
818
+ const ind: i32 = (entryPtr - Porffor.wasm`local.get ${obj}`) / 18;
536
819
 
537
820
  // decrement size
538
- let size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
539
- Porffor.wasm.i32.store(obj, --size, 0, 0);
821
+ let size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
822
+ Porffor.wasm.i32.store16(obj, --size, 0, 0);
540
823
 
541
824
  if (size > ind) {
542
825
  // offset all elements after by -1 ind
@@ -544,16 +827,16 @@ export const __Porffor_object_delete = (obj: any, key: any): boolean => {
544
827
  ;; dst = entryPtr
545
828
  local.get ${entryPtr}
546
829
 
547
- ;; src = entryPtr + 14 (+ 1 entry)
830
+ ;; src = entryPtr + 18 (+ 1 entry)
548
831
  local.get ${entryPtr}
549
- i32.const 14
832
+ i32.const 18
550
833
  i32.add
551
834
 
552
- ;; size = (size - ind) * 14
835
+ ;; size = (size - ind) * 18
553
836
  local.get ${size}
554
837
  local.get ${ind}
555
838
  i32.sub
556
- i32.const 14
839
+ i32.const 18
557
840
  i32.mul
558
841
 
559
842
  memory.copy 0 0`;
@@ -565,29 +848,28 @@ memory.copy 0 0`;
565
848
  export const __Porffor_object_deleteStrict = (obj: any, key: any): boolean => {
566
849
  if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot delete property of null');
567
850
 
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;
851
+ if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
852
+ obj = __Porffor_object_underlying(obj);
853
+ if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return true;
572
854
  }
573
855
 
574
- const entryPtr: i32 = __Porffor_object_lookup(obj, key);
856
+ const entryPtr: i32 = __Porffor_object_lookup(obj, key, __Porffor_object_hash(key));
575
857
  if (entryPtr == -1) {
576
858
  // not found, stop
577
859
  return true;
578
860
  }
579
861
 
580
- const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
862
+ const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
581
863
  if (!(tail & 0b0010)) {
582
864
  // not configurable
583
865
  throw new TypeError('Cannot delete non-configurable property of object');
584
866
  }
585
867
 
586
- const ind: i32 = (entryPtr - Porffor.wasm`local.get ${obj}`) / 14;
868
+ const ind: i32 = (entryPtr - Porffor.wasm`local.get ${obj}`) / 18;
587
869
 
588
870
  // decrement size
589
- let size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
590
- Porffor.wasm.i32.store(obj, --size, 0, 0);
871
+ let size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
872
+ Porffor.wasm.i32.store16(obj, --size, 0, 0);
591
873
 
592
874
  if (size > ind) {
593
875
  // offset all elements after by -1 ind
@@ -595,16 +877,16 @@ export const __Porffor_object_deleteStrict = (obj: any, key: any): boolean => {
595
877
  ;; dst = entryPtr
596
878
  local.get ${entryPtr}
597
879
 
598
- ;; src = entryPtr + 14 (+ 1 entry)
880
+ ;; src = entryPtr + 18 (+ 1 entry)
599
881
  local.get ${entryPtr}
600
- i32.const 14
882
+ i32.const 18
601
883
  i32.add
602
884
 
603
- ;; size = (size - ind) * 14
885
+ ;; size = (size - ind) * 18
604
886
  local.get ${size}
605
887
  local.get ${ind}
606
888
  i32.sub
607
- i32.const 14
889
+ i32.const 18
608
890
  i32.mul
609
891
 
610
892
  memory.copy 0 0`;
@@ -615,156 +897,155 @@ memory.copy 0 0`;
615
897
 
616
898
 
617
899
  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
- );
900
+ return (Porffor.wasm.i32.load8_u(entryPtr, 0, 16) & 0b0100) as boolean;
650
901
  };
651
902
 
652
903
 
653
904
  // used for { foo: 5 }
654
905
  export const __Porffor_object_expr_init = (obj: any, key: any, value: any): void => {
655
906
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
656
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
907
+
908
+ const hash: i32 = __Porffor_object_hash(key);
909
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
657
910
  if (entryPtr == -1) {
911
+ if (key == '__proto__') {
912
+ // set prototype
913
+ Porffor.wasm`
914
+ local.get ${obj}
915
+ local.get ${obj+1}
916
+ local.get ${value}
917
+ i32.trunc_sat_f64_u
918
+ local.get ${value+1}
919
+ call __Porffor_object_setPrototype`;
920
+ return value;
921
+ }
922
+
658
923
  // add new entry
659
924
  // bump size +1
660
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
661
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
925
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
926
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
662
927
 
663
928
  // entryPtr = current end of object
664
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
665
-
666
- __Porffor_object_writeKey(entryPtr, key);
929
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
930
+ __Porffor_object_writeKey(entryPtr, key, hash);
667
931
  }
668
932
 
669
- // write new value value (lol)
670
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
933
+ // write new value value
934
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
671
935
 
672
936
  // write new tail (value type + flags)
673
937
  // flags = writable, enumerable, configurable, not accessor
674
938
  Porffor.wasm.i32.store16(entryPtr,
675
939
  0b1110 + (Porffor.wasm`local.get ${value+1}` << 8),
676
- 0, 12);
940
+ 0, 16);
677
941
  };
678
942
 
679
943
  export const __Porffor_object_expr_initWithFlags = (obj: any, key: any, value: any, flags: i32): void => {
680
944
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
681
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
945
+
946
+ const hash: i32 = __Porffor_object_hash(key);
947
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
682
948
  if (entryPtr == -1) {
949
+ if (key == '__proto__') {
950
+ // set prototype
951
+ Porffor.wasm`
952
+ local.get ${obj}
953
+ local.get ${obj+1}
954
+ local.get ${value}
955
+ i32.trunc_sat_f64_u
956
+ local.get ${value+1}
957
+ call __Porffor_object_setPrototype`;
958
+ return value;
959
+ }
960
+
683
961
  // add new entry
684
962
  // bump size +1
685
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
686
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
963
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
964
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
687
965
 
688
966
  // entryPtr = current end of object
689
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
690
-
691
- __Porffor_object_writeKey(entryPtr, key);
967
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
968
+ __Porffor_object_writeKey(entryPtr, key, hash);
692
969
  }
693
970
 
694
- // write new value value (lol)
695
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
971
+ // write new value value
972
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
696
973
 
697
974
  // write new tail (value type + flags)
698
975
  Porffor.wasm.i32.store16(entryPtr,
699
976
  flags + (Porffor.wasm`local.get ${value+1}` << 8),
700
- 0, 12);
977
+ 0, 16);
701
978
  };
702
979
 
703
980
  // used for { get foo() {} }
704
981
  export const __Porffor_object_expr_get = (obj: any, key: any, get: any): void => {
705
982
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
706
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
983
+
984
+ const hash: i32 = __Porffor_object_hash(key);
985
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
707
986
  let set: any = undefined;
708
987
  if (entryPtr == -1) {
709
988
  // add new entry
710
989
  // bump size +1
711
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
712
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
990
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
991
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
713
992
 
714
993
  // entryPtr = current end of object
715
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
716
-
717
- __Porffor_object_writeKey(entryPtr, key);
994
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
995
+ __Porffor_object_writeKey(entryPtr, key, hash);
718
996
  } else {
719
997
  // existing entry, keep set (if exists)
720
998
  set = __Porffor_object_accessorSet(entryPtr);
721
999
  }
722
1000
 
723
- // write new value value (lol)
724
- Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 4);
1001
+ // write new value value
1002
+ Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 8);
725
1003
 
726
1004
  // write new tail (value type + flags)
727
1005
  // flags = writable, enumerable, configurable, accessor
728
1006
  Porffor.wasm.i32.store16(entryPtr,
729
1007
  0b1111 + (Porffor.TYPES.number << 8),
730
- 0, 12);
1008
+ 0, 16);
731
1009
  };
732
1010
 
733
1011
  // used for { set foo(v) {} }
734
1012
  export const __Porffor_object_expr_set = (obj: any, key: any, set: any): void => {
735
1013
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
736
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
1014
+
1015
+ const hash: i32 = __Porffor_object_hash(key);
1016
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
737
1017
  let get: any = undefined;
738
1018
  if (entryPtr == -1) {
739
1019
  // add new entry
740
1020
  // bump size +1
741
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
742
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
1021
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
1022
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
743
1023
 
744
1024
  // entryPtr = current end of object
745
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
746
-
747
- __Porffor_object_writeKey(entryPtr, key);
1025
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
1026
+ __Porffor_object_writeKey(entryPtr, key, hash);
748
1027
  } else {
749
1028
  // existing entry, keep set (if exists)
750
1029
  get = __Porffor_object_accessorGet(entryPtr);
751
1030
  }
752
1031
 
753
- // write new value value (lol)
754
- Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 4);
1032
+ // write new value value
1033
+ Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 8);
755
1034
 
756
1035
  // write new tail (value type + flags)
757
1036
  // flags = writable, enumerable, configurable, accessor
758
1037
  Porffor.wasm.i32.store16(entryPtr,
759
1038
  0b1111 + (Porffor.TYPES.number << 8),
760
- 0, 12);
1039
+ 0, 16);
761
1040
  };
762
1041
 
763
1042
 
764
1043
  // used for { foo: 5 }
765
1044
  export const __Porffor_object_class_value = (obj: any, key: any, value: any): void => {
766
1045
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
767
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
1046
+
1047
+ const hash: i32 = __Porffor_object_hash(key);
1048
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
768
1049
  if (entryPtr == -1) {
769
1050
  // add new entry
770
1051
  // check if object is inextensible
@@ -773,29 +1054,30 @@ export const __Porffor_object_class_value = (obj: any, key: any, value: any): vo
773
1054
  }
774
1055
 
775
1056
  // bump size +1
776
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
777
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
1057
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
1058
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
778
1059
 
779
1060
  // entryPtr = current end of object
780
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
781
-
782
- __Porffor_object_writeKey(entryPtr, key);
1061
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
1062
+ __Porffor_object_writeKey(entryPtr, key, hash);
783
1063
  }
784
1064
 
785
- // write new value value (lol)
786
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
1065
+ // write new value value
1066
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
787
1067
 
788
1068
  // write new tail (value type + flags)
789
1069
  // flags = writable, enumerable, configurable, not accessor
790
1070
  Porffor.wasm.i32.store16(entryPtr,
791
1071
  0b1110 + (Porffor.wasm`local.get ${value+1}` << 8),
792
- 0, 12);
1072
+ 0, 16);
793
1073
  };
794
1074
 
795
1075
  // used for { foo() {} }
796
1076
  export const __Porffor_object_class_method = (obj: any, key: any, value: any): void => {
797
1077
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
798
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
1078
+
1079
+ const hash: i32 = __Porffor_object_hash(key);
1080
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
799
1081
  if (entryPtr == -1) {
800
1082
  // add new entry
801
1083
  // check if object is inextensible
@@ -804,29 +1086,30 @@ export const __Porffor_object_class_method = (obj: any, key: any, value: any): v
804
1086
  }
805
1087
 
806
1088
  // bump size +1
807
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
808
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
1089
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
1090
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
809
1091
 
810
1092
  // entryPtr = current end of object
811
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
812
-
813
- __Porffor_object_writeKey(entryPtr, key);
1093
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
1094
+ __Porffor_object_writeKey(entryPtr, key, hash);
814
1095
  }
815
1096
 
816
1097
  // write new value value (lol)
817
- Porffor.wasm.f64.store(entryPtr, value, 0, 4);
1098
+ Porffor.wasm.f64.store(entryPtr, value, 0, 8);
818
1099
 
819
1100
  // write new tail (value type + flags)
820
1101
  // flags = writable, enumerable, configurable, not accessor
821
1102
  Porffor.wasm.i32.store16(entryPtr,
822
1103
  0b1010 + (Porffor.wasm`local.get ${value+1}` << 8),
823
- 0, 12);
1104
+ 0, 16);
824
1105
  };
825
1106
 
826
1107
  // used for { get foo() {} }
827
1108
  export const __Porffor_object_class_get = (obj: any, key: any, get: any): void => {
828
1109
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
829
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
1110
+
1111
+ const hash: i32 = __Porffor_object_hash(key);
1112
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
830
1113
  let set: any = undefined;
831
1114
  if (entryPtr == -1) {
832
1115
  // add new entry
@@ -836,32 +1119,33 @@ export const __Porffor_object_class_get = (obj: any, key: any, get: any): void =
836
1119
  }
837
1120
 
838
1121
  // bump size +1
839
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
840
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
1122
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
1123
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
841
1124
 
842
1125
  // entryPtr = current end of object
843
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
844
-
845
- __Porffor_object_writeKey(entryPtr, key);
1126
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
1127
+ __Porffor_object_writeKey(entryPtr, key, hash);
846
1128
  } else {
847
1129
  // existing entry, keep set (if exists)
848
1130
  set = __Porffor_object_accessorSet(entryPtr);
849
1131
  }
850
1132
 
851
1133
  // write new value value (lol)
852
- Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 4);
1134
+ Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 8);
853
1135
 
854
1136
  // write new tail (value type + flags)
855
1137
  // flags = writable, enumerable, configurable, accessor
856
1138
  Porffor.wasm.i32.store16(entryPtr,
857
1139
  0b1011 + (Porffor.TYPES.number << 8),
858
- 0, 12);
1140
+ 0, 16);
859
1141
  };
860
1142
 
861
1143
  // used for { set foo(v) {} }
862
1144
  export const __Porffor_object_class_set = (obj: any, key: any, set: any): void => {
863
1145
  if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
864
- let entryPtr: i32 = __Porffor_object_lookup(obj, key);
1146
+
1147
+ const hash: i32 = __Porffor_object_hash(key);
1148
+ let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
865
1149
  let get: any = undefined;
866
1150
  if (entryPtr == -1) {
867
1151
  // add new entry
@@ -871,24 +1155,23 @@ export const __Porffor_object_class_set = (obj: any, key: any, set: any): void =
871
1155
  }
872
1156
 
873
1157
  // bump size +1
874
- const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
875
- Porffor.wasm.i32.store(obj, size + 1, 0, 0);
1158
+ const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
1159
+ Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
876
1160
 
877
1161
  // entryPtr = current end of object
878
- entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
879
-
880
- __Porffor_object_writeKey(entryPtr, key);
1162
+ entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
1163
+ __Porffor_object_writeKey(entryPtr, key, hash);
881
1164
  } else {
882
1165
  // existing entry, keep set (if exists)
883
1166
  get = __Porffor_object_accessorGet(entryPtr);
884
1167
  }
885
1168
 
886
1169
  // write new value value (lol)
887
- Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 4);
1170
+ Porffor.wasm.f64.store(entryPtr, __Porffor_object_packAccessor(get, set), 0, 8);
888
1171
 
889
1172
  // write new tail (value type + flags)
890
1173
  // flags = writable, enumerable, configurable, accessor
891
1174
  Porffor.wasm.i32.store16(entryPtr,
892
1175
  0b1011 + (Porffor.TYPES.number << 8),
893
- 0, 12);
1176
+ 0, 16);
894
1177
  };