porffor 0.47.6 → 0.47.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/compiler/2c.js CHANGED
@@ -2,7 +2,7 @@ import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from '.
2
2
  import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
3
3
  import { operatorOpcode } from './expression.js';
4
4
  import { log } from './log.js';
5
- import {} from './prefs.js';
5
+ import './prefs.js';
6
6
 
7
7
  const CValtype = {
8
8
  i8: 'u8',
@@ -222,7 +222,7 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
222
222
 
223
223
  const activeData = data.filter(x => x.page != null);
224
224
  if (activeData.length > 0) {
225
- const dataOffset = x => pages.get(x.page).ind * pageSize;
225
+ const dataOffset = x => pages.allocs.get(x.page) ?? (pages.get(x.page) * pageSize);
226
226
  if (Prefs['2cMemcpy']) {
227
227
  prependMain.set('_data', activeData.map(x => `memcpy(_memory + ${dataOffset(x)}, (unsigned char[]){${x.bytes.join(',')}}, ${x.bytes.length});`).join('\n '));
228
228
  } else {
@@ -857,7 +857,7 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
857
857
  const name = invOpcodes[i[0]];
858
858
  const func = CMemFuncs[i[0]];
859
859
  if (!prepend.has(name)) {
860
- prepend.set(name, `${func.returns || 'void'} ${name}(i32 align, i32 offset, ${func.args.map((x, i) => `${func.argTypes[i]} ${x}`).join(', ')}) {\n ${func.c.replaceAll('\n', '\n ')}\n}\n`);
860
+ prepend.set(name, `inline ${func.returns || 'void'} ${name}(i32 align, i32 offset, ${func.args.map((x, i) => `${func.argTypes[i]} ${x}`).join(', ')}) {\n ${func.c.replaceAll('\n', '\n ')}\n}\n`);
861
861
  }
862
862
 
863
863
  const immediates = [ i[1], read_unsignedLEB128(i.slice(2)) ];
@@ -915,5 +915,5 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
915
915
  const makeIncludes = includes => [...includes.keys()].map(x => `#include <${x}>\n`).join('');
916
916
  out = platformSpecific(makeIncludes(winIncludes), makeIncludes(unixIncludes), false) + '\n' + makeIncludes(includes) + '\n' + alwaysPreface + [...prepend.values()].join('\n') + '\n\n' + out;
917
917
 
918
- return `// generated by porffor ${globalThis.version ?? '0.17.0'}\n` + out.trim();
918
+ return `// generated by porffor ${globalThis.version}\n` + out.trim();
919
919
  };
@@ -0,0 +1,64 @@
1
+ import { PageSize } from './wasmSpec.js';
2
+ import './prefs.js';
3
+
4
+ const pagePtr = ind => {
5
+ if (ind === 0) return 16;
6
+ return ind * PageSize;
7
+ };
8
+
9
+ export const nameToReason = (scope, name) => {
10
+ let scopeName = scope.name;
11
+ if (globalThis.precompile && scopeName === 'main') scopeName = globalThis.precompile;
12
+
13
+ return `${Prefs.scopedPageNames ? (scopeName + '/') : ''}${name}`;
14
+ };
15
+
16
+ export const allocPage = ({ scope, pages }, name) => {
17
+ const reason = nameToReason(scope, name);
18
+
19
+ if (pages.has(reason)) {
20
+ return pagePtr(pages.get(reason));
21
+ }
22
+
23
+ const ind = pages.size;
24
+ pages.set(reason, ind);
25
+
26
+ scope.pages ??= new Map();
27
+ scope.pages.set(reason, ind);
28
+
29
+ return pagePtr(ind);
30
+ };
31
+
32
+ export const allocBytes = ({ scope, pages }, reason, bytes) => {
33
+ const allocs = pages.allocs ??= new Map();
34
+ const bins = pages.bins ??= [];
35
+
36
+ if (allocs.has(reason)) {
37
+ return allocs.get(reason);
38
+ }
39
+
40
+ let bin = bins.find(x => (PageSize - x.used) >= bytes);
41
+ if (!bin) {
42
+ // new bin
43
+ const page = pages.size;
44
+ bin = {
45
+ used: 0,
46
+ page
47
+ };
48
+
49
+ const id = bins.push(bin);
50
+ pages.set(`#bin_${id}`, page);
51
+ }
52
+
53
+ const ptr = pagePtr(bin.page) + bin.used;
54
+ bin.used += bytes;
55
+
56
+ allocs.set(reason, ptr);
57
+ return ptr;
58
+ };
59
+
60
+ export const allocStr = ({ scope, pages }, str, bytestring) => {
61
+ // basic string interning for ~free
62
+ const bytes = 4 + str.length * (bytestring ? 1 : 2);
63
+ return allocBytes({ scope, pages }, str, bytes);
64
+ };
@@ -2,7 +2,7 @@ import { Valtype, FuncType, ExportDesc, Section, Magic, ModuleVersion, Opcodes,
2
2
  import { encodeVector, encodeString, encodeLocal, unsignedLEB128, signedLEB128, unsignedLEB128_into, signedLEB128_into, ieee754_binary64, ieee754_binary64_into } from './encoding.js';
3
3
  import { importedFuncs } from './builtins.js';
4
4
  import { log } from './log.js';
5
- import {} from './prefs.js';
5
+ import './prefs.js';
6
6
 
7
7
  const createSection = (type, data) => [
8
8
  type,
@@ -372,7 +372,7 @@ export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
372
372
  const bytes = unsignedLEB128(x.bytes.length).concat(x.bytes);
373
373
  if (x.page != null) {
374
374
  // type: active
375
- let offset = pages.get(x.page).ind * pageSize;
375
+ let offset = pages.allocs.get(x.page) ?? (pages.get(x.page) * pageSize);
376
376
  if (offset === 0) offset = 16;
377
377
  bytes.unshift(0x00, Opcodes.i32_const, ...signedLEB128(offset), Opcodes.end);
378
378
  } else {
@@ -158,44 +158,127 @@ end`;
158
158
  return true;
159
159
  } else {
160
160
  // string, string
161
- let ap: i32 = a - 4;
162
- let bp: i32 = b - 4;
161
+ // change char lengths to byte lengths
162
+ al *= 2;
163
+ bl *= 2;
164
+
165
+ // copied from bytestring, bytestring
166
+ let ap32: i32 = a - 28;
167
+ let bp32: i32 = b - 28;
168
+ let ap8: i32 = a - 4;
169
+ let bp8: i32 = b - 4;
163
170
  Porffor.wasm`
164
- loop 64
165
- local.get ${ap}
166
- local.get ${al}
167
- i32.const 2
168
- i32.mul
169
- i32.add
170
- i64.load 0 0
171
-
172
- local.get ${bp}
173
- local.get ${al}
174
- i32.const 2
175
- i32.mul
176
- i32.add
177
- i64.load 0 0
178
-
179
- i64.ne
180
- if 64
181
- i32.const 0
182
- i32.const 2
183
- return
171
+ ;; load in 2 i64x2 chunks while length >= 32
172
+ local.get ${al}
173
+ i32.const 32
174
+ i32.ge_s
175
+ if 64
176
+ loop 64
177
+ local.get ${ap32}
178
+ local.get ${al}
179
+ i32.add
180
+ v128.load 0 0
181
+
182
+ local.get ${bp32}
183
+ local.get ${al}
184
+ i32.add
185
+ v128.load 0 0
186
+ v128.xor
187
+
188
+ local.get ${ap32}
189
+ local.get ${al}
190
+ i32.add
191
+ v128.load 0 16
192
+
193
+ local.get ${bp32}
194
+ local.get ${al}
195
+ i32.add
196
+ v128.load 0 16
197
+ v128.xor
198
+
199
+ v128.or
200
+ v128.any_true
201
+ if 64
202
+ i32.const 0
203
+ i32.const 2
204
+ return
205
+ end
206
+
207
+ local.get ${al}
208
+ i32.const 32
209
+ i32.sub
210
+ local.tee ${al}
211
+ i32.const 32
212
+ i32.ge_s
213
+ br_if 0
184
214
  end
215
+ end
185
216
 
186
- local.get ${al}
187
- i32.const 4
188
- i32.sub
189
- local.tee ${al}
190
- i32.const 4
191
- i32.ge_s
192
- br_if 0
193
- end`;
217
+ ;; load in i64 chunks while length >= 8
218
+ local.get ${al}
219
+ i32.const 8
220
+ i32.ge_s
221
+ if 64
222
+ loop 64
223
+ local.get ${ap8}
224
+ local.get ${al}
225
+ i32.add
226
+ i64.load 0 0
194
227
 
195
- for (let i: i32 = 0; i < al; i++) {
196
- if (Porffor.wasm.i32.load16_u(Porffor.wasm`local.get ${a}` + i*2, 0, 4) !=
197
- Porffor.wasm.i32.load16_u(Porffor.wasm`local.get ${b}` + i*2, 0, 4)) return false;
198
- }
228
+ local.get ${bp8}
229
+ local.get ${al}
230
+ i32.add
231
+ i64.load 0 0
232
+
233
+ i64.ne
234
+ if 64
235
+ i32.const 0
236
+ i32.const 2
237
+ return
238
+ end
239
+
240
+ local.get ${al}
241
+ i32.const 8
242
+ i32.sub
243
+ local.tee ${al}
244
+ i32.const 8
245
+ i32.ge_s
246
+ br_if 0
247
+ end
248
+ end
249
+
250
+ ;; load in u16 chunks while length >= 2
251
+ local.get ${al}
252
+ i32.const 2
253
+ i32.ge_s
254
+ if 64
255
+ loop 64
256
+ local.get ${a}
257
+ local.get ${al}
258
+ i32.add
259
+ i32.load16_u 0 2
260
+
261
+ local.get ${b}
262
+ local.get ${al}
263
+ i32.add
264
+ i32.load16_u 0 2
265
+
266
+ i32.ne
267
+ if 64
268
+ i32.const 0
269
+ i32.const 2
270
+ return
271
+ end
272
+
273
+ local.get ${al}
274
+ i32.const 2
275
+ i32.sub
276
+ local.tee ${al}
277
+ i32.const 2
278
+ i32.ge_s
279
+ br_if 0
280
+ end
281
+ end`;
199
282
  return true;
200
283
  }
201
284
  }
@@ -18,11 +18,8 @@ export const Boolean = function (value: any): boolean|BooleanObject {
18
18
  export const __Boolean_prototype_toString = (_this: boolean) => {
19
19
  // 1. Let b be ? ThisBooleanValue(this value).
20
20
  // 2. If b is true, return "true"; else return "false".
21
- let out: bytestring = Porffor.allocate();
22
- if (_this) out = 'true';
23
- else out = 'false';
24
-
25
- return out;
21
+ if (_this) return 'true';
22
+ return 'false';
26
23
  };
27
24
 
28
25
  // 20.3.3.3 Boolean.prototype.valueOf ()
@@ -1,7 +1,16 @@
1
1
  import type {} from './porffor.d.ts';
2
2
 
3
3
  export const __Function_prototype_toString = (_this: Function) => {
4
- // todo: actually use source
5
- let out: bytestring = 'function () {}';
4
+ const out: bytestring = Porffor.allocate();
5
+
6
+ const prefix: bytestring = 'function ';
7
+ Porffor.bytestring.appendStr(out, prefix);
8
+
9
+ Porffor.bytestring.appendStr(out, _this.name);
10
+
11
+ const postfix: bytestring = '() { [native code] }';
12
+ Porffor.bytestring.appendStr(out, postfix);
6
13
  return out;
7
- };
14
+ };
15
+
16
+ export const __Function_prototype_toLocaleString = (_this: Function) => __Function_prototype_toString(_this);
@@ -698,33 +698,31 @@ export const __Object_prototype_toString = (_this: any) => {
698
698
  }
699
699
  }
700
700
 
701
- let out: bytestring = Porffor.allocate();
702
-
703
701
  // 1. If the this value is undefined, return "[object Undefined]".
704
- if (_this === undefined) return out = '[object Undefined]';
702
+ if (_this === undefined) return '[object Undefined]';
705
703
 
706
704
  // 2. If the this value is null, return "[object Null]".
707
- if (_this === null) return out = '[object Null]';
705
+ if (_this === null) return '[object Null]';
708
706
 
709
707
  // todo: toStringTag support
710
708
 
711
709
  const t: i32 = Porffor.rawType(_this);
712
- if (t == Porffor.TYPES.array) return out = '[object Array]';
713
- if (t == Porffor.TYPES.function) return out = '[object Function]';
710
+ if (t == Porffor.TYPES.array) return '[object Array]';
711
+ if (t == Porffor.TYPES.function) return '[object Function]';
714
712
  if (Porffor.fastOr(
715
713
  t == Porffor.TYPES.boolean,
716
- t == Porffor.TYPES.booleanobject)) return out = '[object Boolean]';
714
+ t == Porffor.TYPES.booleanobject)) return '[object Boolean]';
717
715
  if (Porffor.fastOr(
718
716
  t == Porffor.TYPES.number,
719
- t == Porffor.TYPES.numberobject)) return out = '[object Number]';
717
+ t == Porffor.TYPES.numberobject)) return '[object Number]';
720
718
  if (Porffor.fastOr(
721
719
  t == Porffor.TYPES.string,
722
720
  t == Porffor.TYPES.bytestring,
723
- t == Porffor.TYPES.stringobject)) return out = '[object String]';
724
- if (t == Porffor.TYPES.date) return out = '[object Date]';
725
- if (t == Porffor.TYPES.regexp) return out = '[object RegExp]';
721
+ t == Porffor.TYPES.stringobject)) return '[object String]';
722
+ if (t == Porffor.TYPES.date) return '[object Date]';
723
+ if (t == Porffor.TYPES.regexp) return '[object RegExp]';
726
724
 
727
- return out = '[object Object]';
725
+ return '[object Object]';
728
726
  };
729
727
 
730
728
  export const __Object_prototype_toLocaleString = (_this: any) => __Object_prototype_toString(_this);
@@ -129,24 +129,22 @@ export const __ecma262_ToString = (argument: unknown): any => {
129
129
  // 2. If argument is a Symbol, throw a TypeError exception.
130
130
  if (type == Porffor.TYPES.symbol) throw new TypeError('Cannot convert a Symbol value to a string');
131
131
 
132
- let out: bytestring = Porffor.allocate();
133
-
134
132
  // 3. If argument is undefined, return "undefined".
135
133
  if (Porffor.fastOr(
136
134
  type == Porffor.TYPES.undefined,
137
- type == Porffor.TYPES.empty)) return out = 'undefined';
135
+ type == Porffor.TYPES.empty)) return 'undefined';
138
136
 
139
137
  // 4. If argument is null, return "null".
140
138
  if (Porffor.fastAnd(
141
139
  type == Porffor.TYPES.object,
142
- argument == 0)) return out = 'null';
140
+ argument == 0)) return 'null';
143
141
 
144
142
  if (type == Porffor.TYPES.boolean) {
145
143
  // 5. If argument is true, return "true".
146
- if (argument == true) return out = 'true';
144
+ if (argument == true) return 'true';
147
145
 
148
146
  // 6. If argument is false, return "false".
149
- return out = 'false';
147
+ return 'false';
150
148
  }
151
149
 
152
150
  // 7. If argument is a Number, return Number::toString(argument, 10).
@@ -3,7 +3,7 @@ import ObjectBuiltins from './builtins_objects.js';
3
3
  import { Blocktype, Opcodes, Valtype, ValtypeSize } from './wasmSpec.js';
4
4
  import { number } from './embedding.js';
5
5
  import { TYPES, TYPE_NAMES } from './types.js';
6
- import {} from './prefs.js';
6
+ import './prefs.js';
7
7
  import { unsignedLEB128 } from './encoding.js';
8
8
 
9
9
  export const importedFuncs = [
@@ -860,7 +860,7 @@ export const BuiltinFuncs = function() {
860
860
  wasm: (scope, { typeSwitch, makeString }) => {
861
861
  const bc = {};
862
862
  for (const x in TYPE_NAMES) {
863
- bc[x] = makeString(scope, TYPE_NAMES[x], false, '#Porffor_type_result');
863
+ bc[x] = makeString(scope, TYPE_NAMES[x]);
864
864
  }
865
865
 
866
866
  return typeSwitch(scope, [ [ Opcodes.local_get, 1 ] ], bc);
@@ -64,7 +64,7 @@ export default function({ builtinFuncs }, Prefs) {
64
64
  getPtr,
65
65
  ...number(existingFunc ? TYPES.function : TYPES.object, Valtype.i32),
66
66
 
67
- ...makeString(scope, x, false, `#builtin_object_${name}_${x}`),
67
+ ...makeString(scope, x),
68
68
  Opcodes.i32_to_u,
69
69
  ...number(TYPES.bytestring, Valtype.i32),
70
70
 
@@ -109,7 +109,7 @@ export default function({ builtinFuncs }, Prefs) {
109
109
  }
110
110
 
111
111
  if (typeof d.value === 'string') {
112
- this[k] = (scope, { makeString }) => makeString(scope, d.value, false, k);
112
+ this[k] = (scope, { makeString }) => makeString(scope, d.value);
113
113
  this[k].type = TYPES.bytestring;
114
114
  continue;
115
115
  }