porffor 0.2.0-31c2539 → 0.2.0-4035760
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/README.md +16 -5
- package/compiler/builtins.js +134 -6
- package/compiler/codeGen.js +271 -54
- package/compiler/decompile.js +3 -3
- package/compiler/index.js +1 -1
- package/compiler/opt.js +14 -2
- package/compiler/prototype.js +171 -16
- package/compiler/wasmSpec.js +6 -2
- package/compiler/wrap.js +101 -8
- package/package.json +1 -1
- package/r.js +45 -0
package/README.md
CHANGED
@@ -121,7 +121,7 @@ No particular order and no guarentees, just what could happen soon™
|
|
121
121
|
- *Basic* Wasm engine (interpreter) in JS
|
122
122
|
- More math operators (`**`, etc)
|
123
123
|
- `do { ... } while (...)`
|
124
|
-
-
|
124
|
+
- Typed export inputs (array)
|
125
125
|
- Exceptions
|
126
126
|
- Rewrite to use actual strings (optional?)
|
127
127
|
- `try { } finally { }`
|
@@ -130,7 +130,10 @@ No particular order and no guarentees, just what could happen soon™
|
|
130
130
|
- Rewrite local indexes per func for smallest local header and remove unused idxs
|
131
131
|
- Smarter inline selection (snapshots?)
|
132
132
|
- Remove const ifs (`if (true)`, etc)
|
133
|
-
-
|
133
|
+
- Memory alignment
|
134
|
+
- Runtime
|
135
|
+
- WASI target
|
136
|
+
- Run precompiled Wasm file if given
|
134
137
|
- Cool proposals
|
135
138
|
- [Optional Chaining Assignment](https://github.com/tc39/proposal-optional-chaining-assignment)
|
136
139
|
- [Modulus and Additional Integer Math](https://github.com/tc39/proposal-integer-and-modulus-math)
|
@@ -139,9 +142,12 @@ No particular order and no guarentees, just what could happen soon™
|
|
139
142
|
- [Seeded Pseudo-Random Numbers](https://github.com/tc39/proposal-seeded-random)
|
140
143
|
- [`do` expressions](https://github.com/tc39/proposal-do-expressions)
|
141
144
|
- [String Trim Characters](https://github.com/Kingwl/proposal-string-trim-characters)
|
145
|
+
- Posts
|
146
|
+
- Inlining investigation
|
147
|
+
- Self hosted testing?
|
142
148
|
|
143
149
|
## Performance
|
144
|
-
*For the things it supports most of the time*, Porffor is blazingly fast compared to most interpreters, and common engines running without JIT. For those with JIT, it is
|
150
|
+
*For the things it supports most of the time*, Porffor is *blazingly fast* compared to most interpreters, and common engines running without JIT. For those with JIT, it is usually slower by default, but can catch up with compiler arguments and typed input.
|
145
151
|
|
146
152
|

|
147
153
|
|
@@ -165,10 +171,12 @@ Mostly for reducing size. I do not really care about compiler perf/time as long
|
|
165
171
|
- Remove unneeded blocks (no `br`s inside)
|
166
172
|
- Remove unused imports
|
167
173
|
- Use data segments for initing arrays/strings
|
174
|
+
- (Likely more not documented yet, todo)
|
168
175
|
|
169
176
|
### Wasm module
|
170
177
|
- Type cache/index (no repeated types)
|
171
178
|
- No main func if empty (and other exports)
|
179
|
+
- No tags if unused/optimized out
|
172
180
|
|
173
181
|
## Test262
|
174
182
|
Porffor can run Test262 via some hacks/transforms which remove unsupported features whilst still doing the same asserts (eg simpler error messages using literals only). It currently passes >10% (see latest commit desc for latest and details). Use `node test262` to test, it will also show a difference of overall results between the last commit and current results.
|
@@ -201,10 +209,13 @@ Porffor can run Test262 via some hacks/transforms which remove unsupported featu
|
|
201
209
|
- `test262`: test262 runner and utils
|
202
210
|
|
203
211
|
## Usecases
|
204
|
-
Basically none (other than giving people headaches). Potential ideas
|
212
|
+
Basically none right now (other than giving people headaches). Potential ideas:
|
213
|
+
- Safety. As Porffor is written in JS, a memory-safe language\*, and compiles JS to Wasm, a fully sandboxed environment\*, it is quite safe. (\* These rely on the underlying implementations being secure. You could also run Wasm, or even Porffor itself, with an interpreter instead of a JIT for bonus security points too.)
|
214
|
+
- Compiling JS to native binaries. This is still very early, [`2c`](#2c) is not that good yet :(
|
215
|
+
- More in future probably?
|
205
216
|
|
206
217
|
## Usage
|
207
|
-
Basically nothing will work :). See files in `test` for examples.
|
218
|
+
Basically nothing will work :). See files in `test` and `bench` for examples.
|
208
219
|
|
209
220
|
1. Clone repo
|
210
221
|
2. `npm install`
|
package/compiler/builtins.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Blocktype, Opcodes, Valtype } from "./wasmSpec.js";
|
1
|
+
import { Blocktype, Opcodes, Valtype, ValtypeSize } from "./wasmSpec.js";
|
2
2
|
import { number, i32x4 } from "./embedding.js";
|
3
3
|
|
4
4
|
export const importedFuncs = [
|
@@ -29,6 +29,21 @@ for (let i = 0; i < importedFuncs.length; i++) {
|
|
29
29
|
|
30
30
|
const char = c => number(c.charCodeAt(0));
|
31
31
|
|
32
|
+
const printStaticStr = str => {
|
33
|
+
const out = [];
|
34
|
+
|
35
|
+
for (let i = 0; i < str.length; i++) {
|
36
|
+
out.push(
|
37
|
+
// ...number(str.charCodeAt(i)),
|
38
|
+
...number(str.charCodeAt(i), Valtype.i32),
|
39
|
+
Opcodes.i32_from_u,
|
40
|
+
[ Opcodes.call, importedFuncs.printChar ]
|
41
|
+
);
|
42
|
+
}
|
43
|
+
|
44
|
+
return out;
|
45
|
+
};
|
46
|
+
|
32
47
|
// todo: somehow diff between these (undefined != null) while remaining falsey in wasm as a number value
|
33
48
|
export const UNDEFINED = 0;
|
34
49
|
export const NULL = 0;
|
@@ -187,12 +202,125 @@ export const BuiltinFuncs = function() {
|
|
187
202
|
|
188
203
|
|
189
204
|
this.__console_log = {
|
190
|
-
params: [ valtypeBinary ],
|
191
|
-
|
205
|
+
params: [ valtypeBinary, Valtype.i32 ],
|
206
|
+
typedParams: true,
|
207
|
+
locals: [ Valtype.i32, Valtype.i32 ],
|
192
208
|
returns: [],
|
193
|
-
wasm: [
|
194
|
-
[ Opcodes.local_get,
|
195
|
-
|
209
|
+
wasm: (scope, { TYPES, typeSwitch }) => [
|
210
|
+
...typeSwitch(scope, [ [ Opcodes.local_get, 1 ] ], {
|
211
|
+
[TYPES.number]: [
|
212
|
+
[ Opcodes.local_get, 0 ],
|
213
|
+
[ Opcodes.call, importedFuncs.print ],
|
214
|
+
],
|
215
|
+
[TYPES.boolean]: [
|
216
|
+
[ Opcodes.local_get, 0 ],
|
217
|
+
Opcodes.i32_to_u,
|
218
|
+
[ Opcodes.if, Blocktype.void ],
|
219
|
+
...printStaticStr('true'),
|
220
|
+
[ Opcodes.else ],
|
221
|
+
...printStaticStr('false'),
|
222
|
+
[ Opcodes.end ]
|
223
|
+
],
|
224
|
+
[TYPES.string]: [
|
225
|
+
// simply print a string :))
|
226
|
+
// cache input pointer as i32
|
227
|
+
[ Opcodes.local_get, 0 ],
|
228
|
+
Opcodes.i32_to_u,
|
229
|
+
[ Opcodes.local_tee, 2 ],
|
230
|
+
|
231
|
+
// make end pointer
|
232
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
233
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
234
|
+
[ Opcodes.i32_mul ],
|
235
|
+
|
236
|
+
[ Opcodes.local_get, 2 ],
|
237
|
+
[ Opcodes.i32_add ],
|
238
|
+
[ Opcodes.local_set, 3 ],
|
239
|
+
|
240
|
+
[ Opcodes.loop, Blocktype.void ],
|
241
|
+
|
242
|
+
// print current char
|
243
|
+
[ Opcodes.local_get, 2 ],
|
244
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
245
|
+
Opcodes.i32_from_u,
|
246
|
+
[ Opcodes.call, importedFuncs.printChar ],
|
247
|
+
|
248
|
+
// increment pointer by sizeof i16
|
249
|
+
[ Opcodes.local_get, 2 ],
|
250
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
251
|
+
[ Opcodes.i32_add ],
|
252
|
+
[ Opcodes.local_tee, 2 ],
|
253
|
+
|
254
|
+
// if pointer != end pointer, loop
|
255
|
+
[ Opcodes.local_get, 3 ],
|
256
|
+
[ Opcodes.i32_ne ],
|
257
|
+
[ Opcodes.br_if, 0 ],
|
258
|
+
|
259
|
+
[ Opcodes.end ]
|
260
|
+
],
|
261
|
+
[TYPES._array]: [
|
262
|
+
...printStaticStr('[ '),
|
263
|
+
|
264
|
+
// cache input pointer as i32
|
265
|
+
[ Opcodes.local_get, 0 ],
|
266
|
+
Opcodes.i32_to_u,
|
267
|
+
[ Opcodes.local_tee, 2 ],
|
268
|
+
|
269
|
+
// make end pointer
|
270
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
271
|
+
...number(ValtypeSize[valtype], Valtype.i32),
|
272
|
+
[ Opcodes.i32_mul ],
|
273
|
+
|
274
|
+
[ Opcodes.local_get, 2 ],
|
275
|
+
[ Opcodes.i32_add ],
|
276
|
+
[ Opcodes.local_set, 3 ],
|
277
|
+
|
278
|
+
[ Opcodes.loop, Blocktype.void ],
|
279
|
+
|
280
|
+
// print current char
|
281
|
+
[ Opcodes.local_get, 2 ],
|
282
|
+
[ Opcodes.load, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
283
|
+
[ Opcodes.call, importedFuncs.print ],
|
284
|
+
|
285
|
+
// increment pointer by sizeof valtype
|
286
|
+
[ Opcodes.local_get, 2 ],
|
287
|
+
...number(ValtypeSize[valtype], Valtype.i32),
|
288
|
+
[ Opcodes.i32_add ],
|
289
|
+
[ Opcodes.local_tee, 2 ],
|
290
|
+
|
291
|
+
// if pointer != end pointer, print separator and loop
|
292
|
+
[ Opcodes.local_get, 3 ],
|
293
|
+
[ Opcodes.i32_ne ],
|
294
|
+
[ Opcodes.if, Blocktype.void ],
|
295
|
+
...printStaticStr(', '),
|
296
|
+
[ Opcodes.br, 1 ],
|
297
|
+
[ Opcodes.end ],
|
298
|
+
|
299
|
+
[ Opcodes.end ],
|
300
|
+
|
301
|
+
...printStaticStr(' ]'),
|
302
|
+
],
|
303
|
+
[TYPES.undefined]: [
|
304
|
+
...printStaticStr('undefined')
|
305
|
+
],
|
306
|
+
[TYPES.function]: [
|
307
|
+
...printStaticStr('function () {}')
|
308
|
+
],
|
309
|
+
[TYPES.object]: [
|
310
|
+
[ Opcodes.local_get, 0 ],
|
311
|
+
Opcodes.i32_to_u,
|
312
|
+
[ Opcodes.if, Blocktype.void ],
|
313
|
+
...printStaticStr('{}'),
|
314
|
+
[ Opcodes.else ],
|
315
|
+
...printStaticStr('null'),
|
316
|
+
[ Opcodes.end ]
|
317
|
+
],
|
318
|
+
default: [
|
319
|
+
[ Opcodes.local_get, 0 ],
|
320
|
+
[ Opcodes.call, importedFuncs.print ],
|
321
|
+
]
|
322
|
+
}, Blocktype.void),
|
323
|
+
|
196
324
|
...char('\n'),
|
197
325
|
[ Opcodes.call, importedFuncs.printChar ]
|
198
326
|
]
|