jz 0.8.0 → 0.9.0
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 +56 -9
- package/bench/README.md +121 -50
- package/bench/bench.svg +27 -27
- package/cli.js +3 -1
- package/dist/interop.js +1 -1
- package/dist/jz.js +7541 -6178
- package/index.js +165 -74
- package/interop.js +189 -17
- package/jzify/arguments.js +32 -1
- package/jzify/async.js +409 -0
- package/jzify/classes.js +136 -18
- package/jzify/generators.js +639 -0
- package/jzify/hoist-vars.js +73 -1
- package/jzify/index.js +123 -4
- package/jzify/names.js +1 -0
- package/jzify/transform.js +239 -1
- package/layout.js +48 -3
- package/module/array.js +318 -43
- package/module/atomics.js +144 -0
- package/module/collection.js +1429 -155
- package/module/core.js +431 -40
- package/module/date.js +142 -120
- package/module/fs.js +144 -0
- package/module/function.js +6 -3
- package/module/index.js +4 -1
- package/module/json.js +270 -49
- package/module/math.js +1032 -145
- package/module/number.js +532 -163
- package/module/object.js +353 -95
- package/module/regex.js +157 -7
- package/module/schema.js +100 -2
- package/module/string.js +428 -93
- package/module/typedarray.js +264 -72
- package/module/web.js +36 -0
- package/package.json +5 -5
- package/src/abi/string.js +82 -11
- package/src/ast.js +11 -5
- package/src/autoload.js +28 -1
- package/src/bridge.js +7 -2
- package/src/compile/analyze-scans.js +22 -7
- package/src/compile/analyze.js +136 -30
- package/src/compile/dyn-closure-tables.js +277 -0
- package/src/compile/emit-assign.js +281 -15
- package/src/compile/emit.js +1055 -70
- package/src/compile/index.js +277 -29
- package/src/compile/infer.js +42 -4
- package/src/compile/inplace-store.js +329 -0
- package/src/compile/loop-recurrence.js +167 -0
- package/src/compile/narrow.js +555 -18
- package/src/compile/peel-stencil.js +5 -0
- package/src/compile/plan/index.js +45 -3
- package/src/compile/plan/inline.js +8 -1
- package/src/compile/plan/literals.js +39 -0
- package/src/compile/plan/scope.js +430 -23
- package/src/compile/program-facts.js +732 -38
- package/src/ctx.js +64 -9
- package/src/helper-counters.js +7 -1
- package/src/ir.js +113 -5
- package/src/kind-traits.js +66 -3
- package/src/kind.js +84 -12
- package/src/op-policy.js +7 -4
- package/src/optimize/index.js +1179 -704
- package/src/optimize/recurse.js +2 -2
- package/src/optimize/vectorize.js +982 -67
- package/src/prepare/index.js +809 -67
- package/src/prepare/math-kernel.js +331 -0
- package/src/prepare/pre-eval.js +714 -0
- package/src/snapshot.js +194 -0
- package/src/type.js +1170 -56
- package/src/wat/assemble.js +403 -65
- package/src/wat/codegen.js +74 -14
- package/transform.js +113 -4
- package/wasi.js +3 -0
package/layout.js
CHANGED
|
@@ -52,7 +52,16 @@ const AUX_SHIFT = BigInt(LAYOUT.AUX_SHIFT), AUX_MASK = BigInt(LAYOUT.AUX_MASK)
|
|
|
52
52
|
const OFFSET_MASK = BigInt(LAYOUT.OFFSET_MASK)
|
|
53
53
|
|
|
54
54
|
/** Format an i64 BigInt as a zero-padded `0x…` hex literal for WAT/IR templates. */
|
|
55
|
-
|
|
55
|
+
// Formatted via 32-bit halves with an explicit logical shift, NOT
|
|
56
|
+
// bits.toString(16): under self-host, BigInts are raw SIGNED i64 bits
|
|
57
|
+
// (kind-erased — see ir.js's SELF-HOST CONTRACT), so toString(16) of a
|
|
58
|
+
// bit-63-set value renders a signed "-8000…" fragment and the emitted
|
|
59
|
+
// `(i64.const 0x00-8000…)` kills the kernel's watr parse ("Bad int") — the
|
|
60
|
+
// nanPrefixMaskHex regression that silently broke every durable-log helper
|
|
61
|
+
// the kernel compiled. `>> 32n` sign-extends on raw bits; the & masks the
|
|
62
|
+
// extension off, so both host and kernel produce the same unsigned halves.
|
|
63
|
+
const _hx8 = (n) => n.toString(16).toUpperCase().padStart(8, '0')
|
|
64
|
+
export const i64Hex = bits => '0x' + _hx8(Number((bits >> 32n) & 0xFFFFFFFFn)) + _hx8(Number(bits & 0xFFFFFFFFn))
|
|
56
65
|
|
|
57
66
|
/** Pack (type, aux, offset) into the i64 NaN-box carrier — the single source of
|
|
58
67
|
* truth for pointer bit layout. Compiler IR (`packPtrBits`/`mkPtrIR`), the
|
|
@@ -123,6 +132,12 @@ export const decodePtrAux = hi => hi & LAYOUT.AUX_MASK
|
|
|
123
132
|
/** i64 NaN-prefix OR-mask for WAT `(i64.const …)` templates. */
|
|
124
133
|
export const nanPrefixHex = () => i64Hex(LAYOUT.NAN_PREFIX_BITS)
|
|
125
134
|
|
|
135
|
+
/** AND-mask isolating the boxed-carrier prefix (sign + exponent + quiet bit):
|
|
136
|
+
* `(v & nanPrefixMask) == nanPrefix` ⇔ v is a NaN-boxed carrier (any tag/aux/
|
|
137
|
+
* payload). The mask is the prefix with the SIGN bit forced on — boxes are
|
|
138
|
+
* emitted sign-clear, so a set sign bit must fail the carrier test. */
|
|
139
|
+
export const nanPrefixMaskHex = () => i64Hex(LAYOUT.NAN_PREFIX_BITS | (1n << 63n))
|
|
140
|
+
|
|
126
141
|
/** Atom sentinel as i64 hex (compiler WAT templates). */
|
|
127
142
|
export const atomNanHex = atomId => i64Hex(LAYOUT.NAN_PREFIX_BITS | (BigInt(atomId) << AUX_SHIFT))
|
|
128
143
|
|
|
@@ -136,12 +151,27 @@ export const atomNanHex = atomId => i64Hex(LAYOUT.NAN_PREFIX_BITS | (BigInt(atom
|
|
|
136
151
|
* heap consumers read the len header at -4 regardless of aux. */
|
|
137
152
|
export const STR_INTERN_BIT = 0x1
|
|
138
153
|
|
|
154
|
+
/** STRING aux bit 1 on a PLAIN-HEAP string (SSO and SLICE clear): the string was
|
|
155
|
+
* allocated with an [hash u32][len u32][bytes] header where the hash cell is a
|
|
156
|
+
* LAZY cache — seeded 0 (byte-FNV clamps to ≥2, so 0 is unambiguous "uncomputed"),
|
|
157
|
+
* filled by __str_hash on first hash. Sound because heap strings never relocate
|
|
158
|
+
* and die with their arena; the two in-place mutators (concat/append bump-extend
|
|
159
|
+
* of a heap-top accumulator) zero the cell when they change the bytes. Unlike
|
|
160
|
+
* STR_INTERN_BIT it carries NO canonicality claim — two hcache strings with equal
|
|
161
|
+
* content are ordinary bit-unequal pointers. Inert for slices (their aux[12:0]
|
|
162
|
+
* is a length, only read under SLICE_BIT) and every len/byte reader (-4 header
|
|
163
|
+
* unchanged). Producers opt in one by one; an unmarked string just re-hashes. */
|
|
164
|
+
export const STR_HCACHE_BIT = 0x2
|
|
165
|
+
|
|
139
166
|
/** Pre-shifted STRING SSO aux bit as i64 hex. */
|
|
140
167
|
export const ssoBitI64Hex = () => i64Hex(BigInt(LAYOUT.SSO_BIT) << AUX_SHIFT)
|
|
141
168
|
|
|
142
169
|
/** Pre-shifted STRING slice/view aux bit as i64 hex. */
|
|
143
170
|
export const sliceBitI64Hex = () => i64Hex(BigInt(LAYOUT.SLICE_BIT) << AUX_SHIFT)
|
|
144
171
|
|
|
172
|
+
/** Pre-shifted STRING hash-cache aux bit as i64 hex. */
|
|
173
|
+
export const hcacheBitI64Hex = () => i64Hex(BigInt(STR_HCACHE_BIT) << AUX_SHIFT)
|
|
174
|
+
|
|
145
175
|
/** Full i64 NaN-box hex for `(i64.const …)` — ptr type + aux, offset OR'd separately. */
|
|
146
176
|
export const ptrNanHex = (ptrType, aux = 0) => i64Hex(ptrBits(ptrType, aux))
|
|
147
177
|
|
|
@@ -174,10 +204,25 @@ export const oobNanIR = () => ['f64.const', oobNanLiteral()]
|
|
|
174
204
|
* __arr_idx_known, __typed_idx…) — a body containing a loop is excluded from
|
|
175
205
|
* V8's wasm inliner, and these helpers sit on ~25% of self-host compile time.
|
|
176
206
|
* Callers must list '__ptr_offset_fwd' in their deps()/wat() dependency set. */
|
|
207
|
+
// Upper bound is `off <= memory.size() * 65536` (total bytes currently backed) — read from
|
|
208
|
+
// $__heap_end64 (module/core.js, kept in sync by __memgrow on every grow), NOT recomputed
|
|
209
|
+
// as `i64.shl(i64.extend_i32_u(memory.size), 16)` inline: this check is on the hottest
|
|
210
|
+
// pointer-dereference path (~25% of self-host compile time, per the doc comment above), so
|
|
211
|
+
// a per-call recompute would cost 3 extra instructions at every inlined site instead of one
|
|
212
|
+
// global read. The i32 form `memory.size() << 16` (what a naive version — and $__heap_end
|
|
213
|
+
// itself — uses) overflows to exactly 0 at the wasm32 ceiling (memory.size()==65536 pages,
|
|
214
|
+
// i.e. the full 4 GiB: 65536*65536 == 2^32, unrepresentable in i32). Reading $__heap_end
|
|
215
|
+
// here instead of $__heap_end64 would make the bound "off <= 0", failing for every real off
|
|
216
|
+
// and silently disabling the forward-chase for the rest of execution: any pointer to an
|
|
217
|
+
// already-relocated ARRAY/SET/MAP/HASH stops following its forwarding header and reads the
|
|
218
|
+
// abandoned old block (cap=-1 sentinel misread as a real capacity) instead. That wraparound
|
|
219
|
+
// is benign for $__heap_end's own consumer (__alloc's fast-path check just slow-paths one
|
|
220
|
+
// extra time and __memgrow re-derives everything fresh in i64) but NOT here, where it gates
|
|
221
|
+
// whether forwarding runs at all — hence the separate i64 global instead of reusing $__heap_end.
|
|
177
222
|
export const followForwardingWat = (off = '$off', { lowGuard = true } = {}) =>
|
|
178
223
|
`(if (i32.and
|
|
179
224
|
${lowGuard ? `(i32.ge_u (local.get ${off}) (i32.const 8))` : '(i32.const 1)'}
|
|
180
|
-
(
|
|
225
|
+
(i64.le_u (i64.extend_i32_u (local.get ${off})) (global.get $__heap_end64)))
|
|
181
226
|
(then (if (i32.eq (i32.load (i32.sub (local.get ${off}) (i32.const 4))) (i32.const -1))
|
|
182
227
|
(then (local.set ${off} (call $__ptr_offset_fwd (local.get ${off})))))))`
|
|
183
228
|
|
|
@@ -188,7 +233,7 @@ export const ptrOffsetFwdWat = () =>
|
|
|
188
233
|
`(func $__ptr_offset_fwd (param $off i32) (result i32)
|
|
189
234
|
(block $done (loop $follow
|
|
190
235
|
(br_if $done (i32.lt_u (local.get $off) (i32.const 8)))
|
|
191
|
-
(br_if $done (
|
|
236
|
+
(br_if $done (i64.gt_u (i64.extend_i32_u (local.get $off)) (global.get $__heap_end64)))
|
|
192
237
|
(br_if $done (i32.ne (i32.load (i32.sub (local.get $off) (i32.const 4))) (i32.const -1)))
|
|
193
238
|
(local.set $off (i32.load (i32.sub (local.get $off) (i32.const 8))))
|
|
194
239
|
(br $follow)))
|