@scriptc/compiler 0.4.5 → 0.4.6
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/ambient/node-fallback/assert-strict.d.ts +47 -0
- package/ambient/node-fallback/assert.d.ts +86 -0
- package/ambient/node-fallback/async_hooks.d.ts +41 -0
- package/ambient/node-fallback/buffer.d.ts +23 -0
- package/ambient/node-fallback/child_process.d.ts +242 -0
- package/ambient/node-fallback/cluster.d.ts +17 -0
- package/ambient/node-fallback/constants.d.ts +15 -0
- package/ambient/node-fallback/crypto.d.ts +837 -0
- package/ambient/node-fallback/dgram.d.ts +58 -0
- package/ambient/node-fallback/diagnostics_channel.d.ts +87 -0
- package/ambient/node-fallback/dns-promises.d.ts +27 -0
- package/ambient/node-fallback/dns.d.ts +65 -0
- package/ambient/node-fallback/events.d.ts +60 -0
- package/ambient/node-fallback/fs-promises.d.ts +225 -0
- package/ambient/node-fallback/fs.d.ts +641 -0
- package/ambient/node-fallback/graceful-fs.d.ts +9 -0
- package/ambient/node-fallback/http.d.ts +326 -0
- package/ambient/node-fallback/http2.d.ts +816 -0
- package/ambient/node-fallback/https.d.ts +59 -0
- package/ambient/node-fallback/module.d.ts +10 -0
- package/ambient/node-fallback/net.d.ts +374 -0
- package/ambient/node-fallback/os.d.ts +288 -0
- package/ambient/node-fallback/path-posix.d.ts +22 -0
- package/ambient/node-fallback/path-win32.d.ts +22 -0
- package/ambient/node-fallback/path.d.ts +55 -0
- package/ambient/node-fallback/process.d.ts +11 -0
- package/ambient/node-fallback/punycode.d.ts +18 -0
- package/ambient/node-fallback/querystring.d.ts +55 -0
- package/ambient/node-fallback/stream-consumers.d.ts +21 -0
- package/ambient/node-fallback/stream-promises.d.ts +28 -0
- package/ambient/node-fallback/stream-web.d.ts +36 -0
- package/ambient/node-fallback/stream.d.ts +644 -0
- package/ambient/node-fallback/string_decoder.d.ts +20 -0
- package/ambient/node-fallback/test.d.ts +236 -0
- package/ambient/node-fallback/timers-promises.d.ts +31 -0
- package/ambient/node-fallback/timers.d.ts +28 -0
- package/ambient/node-fallback/tls.d.ts +169 -0
- package/ambient/node-fallback/url.d.ts +95 -0
- package/ambient/node-fallback/util-types.d.ts +50 -0
- package/ambient/node-fallback/util.d.ts +416 -0
- package/ambient/node-fallback/v8.d.ts +43 -0
- package/ambient/node-fallback/worker_threads.d.ts +113 -0
- package/ambient/node-fallback/zlib.d.ts +422 -0
- package/ambient/scriptc-node-fallback.d.ts +224 -6688
- package/dist/backend/cycle-analysis.js +4 -0
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/executable-features.d.ts +1 -1
- package/dist/backend/executable-features.js +15 -2
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/huge-text.d.ts +16 -0
- package/dist/backend/huge-text.js +103 -0
- package/dist/backend/huge-text.js.map +1 -0
- package/dist/backend/huge-text.test.d.ts +1 -0
- package/dist/backend/huge-text.test.js +73 -0
- package/dist/backend/huge-text.test.js.map +1 -0
- package/dist/backend/library-pack.js +1 -1
- package/dist/backend/library-pack.js.map +1 -1
- package/dist/backend/link-plan-core.d.ts +10 -0
- package/dist/backend/link-plan-core.js +14 -2
- package/dist/backend/link-plan-core.js.map +1 -1
- package/dist/backend/link-plan-core.test.d.ts +1 -0
- package/dist/backend/link-plan-core.test.js +20 -0
- package/dist/backend/link-plan-core.test.js.map +1 -0
- package/dist/backend/link-plan.d.ts +8 -0
- package/dist/backend/link-plan.js +7 -0
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/linker.js +37 -14
- package/dist/backend/linker.js.map +1 -1
- package/dist/backend/lld.d.ts +13 -0
- package/dist/backend/lld.js +18 -1
- package/dist/backend/lld.js.map +1 -1
- package/dist/backend/lld.test.js +7 -1
- package/dist/backend/lld.test.js.map +1 -1
- package/dist/backend/llvm/alloc.d.ts +2 -0
- package/dist/backend/llvm/alloc.js +1 -1
- package/dist/backend/llvm/alloc.js.map +1 -1
- package/dist/backend/llvm/arenas.d.ts +78 -0
- package/dist/backend/llvm/arenas.js +313 -0
- package/dist/backend/llvm/arenas.js.map +1 -0
- package/dist/backend/llvm/arenas.test.d.ts +1 -0
- package/dist/backend/llvm/arenas.test.js +140 -0
- package/dist/backend/llvm/arenas.test.js.map +1 -0
- package/dist/backend/llvm/blocks.d.ts +11 -1
- package/dist/backend/llvm/blocks.js +23 -5
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/bytes-headers.d.ts +19 -0
- package/dist/backend/llvm/bytes-headers.js +55 -0
- package/dist/backend/llvm/bytes-headers.js.map +1 -0
- package/dist/backend/llvm/bytes-loop-versions.d.ts +4 -3
- package/dist/backend/llvm/bytes-loop-versions.js +42 -7
- package/dist/backend/llvm/bytes-loop-versions.js.map +1 -1
- package/dist/backend/llvm/bytes-loop-versions.test.js +39 -4
- package/dist/backend/llvm/bytes-loop-versions.test.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.d.ts +5 -0
- package/dist/backend/llvm/call-lifetimes.js +43 -8
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +26 -0
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/checked-narrows.d.ts +3 -0
- package/dist/backend/llvm/checked-narrows.js +8 -1
- package/dist/backend/llvm/checked-narrows.js.map +1 -1
- package/dist/backend/llvm/class-unions.d.ts +21 -0
- package/dist/backend/llvm/class-unions.js +141 -0
- package/dist/backend/llvm/class-unions.js.map +1 -0
- package/dist/backend/llvm/class-unions.test.d.ts +1 -0
- package/dist/backend/llvm/class-unions.test.js +137 -0
- package/dist/backend/llvm/class-unions.test.js.map +1 -0
- package/dist/backend/llvm/classes.d.ts +46 -8
- package/dist/backend/llvm/classes.js +259 -32
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +4 -0
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +23 -0
- package/dist/backend/llvm/common.js +34 -0
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.test.js +39 -0
- package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
- package/dist/backend/llvm/constant-choices.d.ts +32 -0
- package/dist/backend/llvm/constant-choices.js +209 -0
- package/dist/backend/llvm/constant-choices.js.map +1 -0
- package/dist/backend/llvm/constant-choices.test.d.ts +1 -0
- package/dist/backend/llvm/constant-choices.test.js +94 -0
- package/dist/backend/llvm/constant-choices.test.js.map +1 -0
- package/dist/backend/llvm/counted-loops.d.ts +14 -2
- package/dist/backend/llvm/counted-loops.js +60 -7
- package/dist/backend/llvm/counted-loops.js.map +1 -1
- package/dist/backend/llvm/counted-loops.test.d.ts +1 -0
- package/dist/backend/llvm/counted-loops.test.js +34 -0
- package/dist/backend/llvm/counted-loops.test.js.map +1 -0
- package/dist/backend/llvm/cpu-dispatch.d.ts +26 -0
- package/dist/backend/llvm/cpu-dispatch.js +279 -0
- package/dist/backend/llvm/cpu-dispatch.js.map +1 -0
- package/dist/backend/llvm/dense-array-access.d.ts +13 -2
- package/dist/backend/llvm/dense-array-access.js +60 -6
- package/dist/backend/llvm/dense-array-access.js.map +1 -1
- package/dist/backend/llvm/dyn-handle-tags.test.js +40 -14
- package/dist/backend/llvm/dyn-handle-tags.test.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +28 -2
- package/dist/backend/llvm/dyn.js +176 -27
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emit-function.js +25 -3
- package/dist/backend/llvm/emit-function.js.map +1 -1
- package/dist/backend/llvm/emit-journal.d.ts +1 -0
- package/dist/backend/llvm/emit-journal.js.map +1 -1
- package/dist/backend/llvm/emit-module.d.ts +5 -3
- package/dist/backend/llvm/emit-module.js +362 -74
- package/dist/backend/llvm/emit-module.js.map +1 -1
- package/dist/backend/llvm/emit-statements.js +327 -59
- package/dist/backend/llvm/emit-statements.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +223 -33
- package/dist/backend/llvm/emitter.js +713 -100
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +20 -1
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +32 -6
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +9 -1
- package/dist/backend/llvm/expr-bytes.js +105 -9
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-callbacks.js +29 -22
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.d.ts +0 -4
- package/dist/backend/llvm/expr-calls.js +116 -14
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +77 -12
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +22 -0
- package/dist/backend/llvm/expr-control.d.ts +4 -0
- package/dist/backend/llvm/expr-control.js +485 -426
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.js +4 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +3 -3
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +6 -0
- package/dist/backend/llvm/expr-primitives.js +119 -58
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +11 -2
- package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
- package/dist/backend/llvm/expr-records.d.ts +36 -4
- package/dist/backend/llvm/expr-records.js +249 -37
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +124 -7
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.js +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.js +13 -14
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/frame-escapes.d.ts +11 -0
- package/dist/backend/llvm/frame-escapes.js +219 -0
- package/dist/backend/llvm/frame-escapes.js.map +1 -0
- package/dist/backend/llvm/function-layout.d.ts +15 -0
- package/dist/backend/llvm/function-layout.js +40 -0
- package/dist/backend/llvm/function-layout.js.map +1 -0
- package/dist/backend/llvm/heap-census.d.ts +34 -0
- package/dist/backend/llvm/heap-census.js +163 -0
- package/dist/backend/llvm/heap-census.js.map +1 -0
- package/dist/backend/llvm/inline-arrays.d.ts +41 -0
- package/dist/backend/llvm/inline-arrays.js +195 -0
- package/dist/backend/llvm/inline-arrays.js.map +1 -0
- package/dist/backend/llvm/int32-kind-loops.js +2 -0
- package/dist/backend/llvm/int32-kind-loops.js.map +1 -1
- package/dist/backend/llvm/integer-clones.d.ts +32 -5
- package/dist/backend/llvm/integer-clones.js +237 -44
- package/dist/backend/llvm/integer-clones.js.map +1 -1
- package/dist/backend/llvm/integer-clones.test.js +120 -0
- package/dist/backend/llvm/integer-clones.test.js.map +1 -1
- package/dist/backend/llvm/iterative-teardown.test.d.ts +1 -0
- package/dist/backend/llvm/iterative-teardown.test.js +62 -0
- package/dist/backend/llvm/iterative-teardown.test.js.map +1 -0
- package/dist/backend/llvm/js-ic.js +246 -62
- package/dist/backend/llvm/js-ic.js.map +1 -1
- package/dist/backend/llvm/lib-connect.js +1 -1
- package/dist/backend/llvm/lib-connect.js.map +1 -1
- package/dist/backend/llvm/lib-datagram.js +2 -2
- package/dist/backend/llvm/lib-datagram.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +153 -16
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.d.ts +8 -0
- package/dist/backend/llvm/lib-filesystem.js +48 -4
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.js +4 -3
- package/dist/backend/llvm/lib-http2.js.map +1 -1
- package/dist/backend/llvm/lib-lookup.js +1 -1
- package/dist/backend/llvm/lib-lookup.js.map +1 -1
- package/dist/backend/llvm/lib-network.js +15 -1
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +32 -8
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.d.ts +3 -0
- package/dist/backend/llvm/lib-shared.js +191 -28
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +1 -1
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +15 -1
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +1 -1
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
- package/dist/backend/llvm/local-extents.d.ts +22 -0
- package/dist/backend/llvm/local-extents.js +102 -0
- package/dist/backend/llvm/local-extents.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.js +15 -2
- package/dist/backend/llvm/local-union-storage.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.test.js +1 -1
- package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
- package/dist/backend/llvm/loop-callees.d.ts +21 -0
- package/dist/backend/llvm/loop-callees.js +119 -0
- package/dist/backend/llvm/loop-callees.js.map +1 -0
- package/dist/backend/llvm/loop-callees.test.d.ts +1 -0
- package/dist/backend/llvm/loop-callees.test.js +65 -0
- package/dist/backend/llvm/loop-callees.test.js.map +1 -0
- package/dist/backend/llvm/loop-entry-versions.d.ts +17 -0
- package/dist/backend/llvm/loop-entry-versions.js +185 -0
- package/dist/backend/llvm/loop-entry-versions.js.map +1 -0
- package/dist/backend/llvm/map-number-lookup.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.test.js +13 -4
- package/dist/backend/llvm/map-number-lookup.test.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.d.ts +11 -0
- package/dist/backend/llvm/map-read-lifetimes.js +51 -1
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js +6 -3
- package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/nullable-unions.d.ts +67 -10
- package/dist/backend/llvm/nullable-unions.js +218 -22
- package/dist/backend/llvm/nullable-unions.js.map +1 -1
- package/dist/backend/llvm/nullable-unions.test.js +124 -1
- package/dist/backend/llvm/nullable-unions.test.js.map +1 -1
- package/dist/backend/llvm/periodic-guards.d.ts +16 -0
- package/dist/backend/llvm/periodic-guards.js +91 -0
- package/dist/backend/llvm/periodic-guards.js.map +1 -0
- package/dist/backend/llvm/periodic-guards.test.d.ts +1 -0
- package/dist/backend/llvm/periodic-guards.test.js +64 -0
- package/dist/backend/llvm/periodic-guards.test.js.map +1 -0
- package/dist/backend/llvm/publish.d.ts +12 -2
- package/dist/backend/llvm/publish.js +15 -8
- package/dist/backend/llvm/publish.js.map +1 -1
- package/dist/backend/llvm/rebound-parameters.d.ts +4 -1
- package/dist/backend/llvm/rebound-parameters.js +17 -1
- package/dist/backend/llvm/rebound-parameters.js.map +1 -1
- package/dist/backend/llvm/receivers.d.ts +7 -0
- package/dist/backend/llvm/receivers.js +77 -10
- package/dist/backend/llvm/receivers.js.map +1 -1
- package/dist/backend/llvm/record-union-keys.test.js +29 -0
- package/dist/backend/llvm/record-union-keys.test.js.map +1 -1
- package/dist/backend/llvm/record-views.d.ts +29 -0
- package/dist/backend/llvm/record-views.js +249 -0
- package/dist/backend/llvm/record-views.js.map +1 -0
- package/dist/backend/llvm/record-views.test.d.ts +1 -0
- package/dist/backend/llvm/record-views.test.js +118 -0
- package/dist/backend/llvm/record-views.test.js.map +1 -0
- package/dist/backend/llvm/reference-writes.js +21 -0
- package/dist/backend/llvm/reference-writes.js.map +1 -1
- package/dist/backend/llvm/reference-writes.test.js +42 -0
- package/dist/backend/llvm/reference-writes.test.js.map +1 -1
- package/dist/backend/llvm/regex-matchers.d.ts +5 -1
- package/dist/backend/llvm/regex-matchers.js +173 -21
- package/dist/backend/llvm/regex-matchers.js.map +1 -1
- package/dist/backend/llvm/regex-matchers.test.js +39 -1
- package/dist/backend/llvm/regex-matchers.test.js.map +1 -1
- package/dist/backend/llvm/region-groups.d.ts +67 -0
- package/dist/backend/llvm/region-groups.js +1719 -0
- package/dist/backend/llvm/region-groups.js.map +1 -0
- package/dist/backend/llvm/region-groups.test.d.ts +1 -0
- package/dist/backend/llvm/region-groups.test.js +197 -0
- package/dist/backend/llvm/region-groups.test.js.map +1 -0
- package/dist/backend/llvm/region-ir.d.ts +31 -0
- package/dist/backend/llvm/region-ir.js +256 -0
- package/dist/backend/llvm/region-ir.js.map +1 -0
- package/dist/backend/llvm/region-sites.d.ts +20 -0
- package/dist/backend/llvm/region-sites.js +327 -0
- package/dist/backend/llvm/region-sites.js.map +1 -0
- package/dist/backend/llvm/region-sites.test.d.ts +1 -0
- package/dist/backend/llvm/region-sites.test.js +216 -0
- package/dist/backend/llvm/region-sites.test.js.map +1 -0
- package/dist/backend/llvm/repr-report.d.ts +9 -0
- package/dist/backend/llvm/repr-report.js +143 -0
- package/dist/backend/llvm/repr-report.js.map +1 -0
- package/dist/backend/llvm/repr-report.test.d.ts +1 -0
- package/dist/backend/llvm/repr-report.test.js +62 -0
- package/dist/backend/llvm/repr-report.test.js.map +1 -0
- package/dist/backend/llvm/runtime-registries.test.d.ts +1 -0
- package/dist/backend/llvm/runtime-registries.test.js +88 -0
- package/dist/backend/llvm/runtime-registries.test.js.map +1 -0
- package/dist/backend/llvm/serialized-ir-emission.test.js +1 -0
- package/dist/backend/llvm/serialized-ir-emission.test.js.map +1 -1
- package/dist/backend/llvm/shape-union-tags.test.d.ts +1 -0
- package/dist/backend/llvm/shape-union-tags.test.js +75 -0
- package/dist/backend/llvm/shape-union-tags.test.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +60 -10
- package/dist/backend/llvm/shapes.js +233 -51
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +37 -18
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/speculative-integers.d.ts +3 -0
- package/dist/backend/llvm/speculative-integers.js +20 -8
- package/dist/backend/llvm/speculative-integers.js.map +1 -1
- package/dist/backend/llvm/split.js +6 -1
- package/dist/backend/llvm/split.js.map +1 -1
- package/dist/backend/llvm/split.test.js +23 -0
- package/dist/backend/llvm/split.test.js.map +1 -1
- package/dist/backend/llvm/stack-callbacks.js +4 -2
- package/dist/backend/llvm/stack-callbacks.js.map +1 -1
- package/dist/backend/llvm/stack-objects.d.ts +12 -3
- package/dist/backend/llvm/stack-objects.js +110 -22
- package/dist/backend/llvm/stack-objects.js.map +1 -1
- package/dist/backend/llvm/stack-objects.test.js +144 -0
- package/dist/backend/llvm/stack-objects.test.js.map +1 -1
- package/dist/backend/llvm/stack-unions.test.js +24 -1
- package/dist/backend/llvm/stack-unions.test.js.map +1 -1
- package/dist/backend/llvm/string-lifetimes.js +2 -1
- package/dist/backend/llvm/string-lifetimes.js.map +1 -1
- package/dist/backend/llvm/string-lifetimes.test.js +1 -1
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/string-reads.d.ts +4 -0
- package/dist/backend/llvm/string-reads.js +27 -0
- package/dist/backend/llvm/string-reads.js.map +1 -1
- package/dist/backend/llvm/test-boxed-unions.d.ts +10 -8
- package/dist/backend/llvm/test-boxed-unions.js +20 -25
- package/dist/backend/llvm/test-boxed-unions.js.map +1 -1
- package/dist/backend/llvm/union-repr.js +9 -8
- package/dist/backend/llvm/union-repr.js.map +1 -1
- package/dist/backend/llvm/union-retype.test.js +45 -2
- package/dist/backend/llvm/union-retype.test.js.map +1 -1
- package/dist/backend/llvm/unwind-abi.d.ts +20 -8
- package/dist/backend/llvm/unwind-abi.js +177 -70
- package/dist/backend/llvm/unwind-abi.js.map +1 -1
- package/dist/backend/llvm/unwind-abi.test.js +90 -3
- package/dist/backend/llvm/unwind-abi.test.js.map +1 -1
- package/dist/backend/llvm/walk-borrows.d.ts +3 -2
- package/dist/backend/llvm/walk-borrows.js +2 -2
- package/dist/backend/llvm/walk-borrows.js.map +1 -1
- package/dist/backend/llvm/walk-borrows.test.js +18 -0
- package/dist/backend/llvm/walk-borrows.test.js.map +1 -1
- package/dist/backend/llvm/walkers.d.ts +14 -1
- package/dist/backend/llvm/walkers.js +103 -11
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/llvm/wrapping-sums.d.ts +26 -6
- package/dist/backend/llvm/wrapping-sums.js +64 -12
- package/dist/backend/llvm/wrapping-sums.js.map +1 -1
- package/dist/backend/loop-polls.d.ts +4 -2
- package/dist/backend/loop-polls.js +11 -2
- package/dist/backend/loop-polls.js.map +1 -1
- package/dist/backend/mangle.d.ts +0 -5
- package/dist/backend/mangle.js +0 -9
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/may-throw.d.ts +10 -9
- package/dist/backend/may-throw.js +189 -27
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +44 -7
- package/dist/backend/may-throw.test.js.map +1 -1
- package/dist/backend/native/compiler-fingerprint.d.ts +5 -0
- package/dist/backend/native/compiler-fingerprint.js +62 -16
- package/dist/backend/native/compiler-fingerprint.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +31 -8
- package/dist/backend/native/executable.js +56 -32
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/library.js +3 -4
- package/dist/backend/native/library.js.map +1 -1
- package/dist/backend/native/object-merge.d.ts +3 -1
- package/dist/backend/native/object-merge.js +24 -11
- package/dist/backend/native/object-merge.js.map +1 -1
- package/dist/backend/native/program-shards.js +6 -3
- package/dist/backend/native/program-shards.js.map +1 -1
- package/dist/backend/native/runtime-inputs.d.ts +1 -1
- package/dist/backend/native/runtime-inputs.js +3 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native/vendor.d.ts +1 -1
- package/dist/backend/native-codegen-core.d.ts +15 -6
- package/dist/backend/native-codegen-core.js +20 -9
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.js +51 -5
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +82 -8
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +30 -0
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/native-profile.d.ts +68 -4
- package/dist/backend/native-profile.js +86 -14
- package/dist/backend/native-profile.js.map +1 -1
- package/dist/backend/native-profile.test.js +127 -4
- package/dist/backend/native-profile.test.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +1 -1
- package/dist/backend/native-toolchain.js +1 -1
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +58 -4
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +17 -3
- package/dist/backend/native-tools.js +12 -4
- package/dist/backend/native-tools.js.map +1 -1
- package/dist/backend/native-tools.test.d.ts +1 -0
- package/dist/backend/native-tools.test.js +76 -0
- package/dist/backend/native-tools.test.js.map +1 -0
- package/dist/backend/object-localize.js +69 -9
- package/dist/backend/object-localize.js.map +1 -1
- package/dist/backend/object-localize.test.js +99 -10
- package/dist/backend/object-localize.test.js.map +1 -1
- package/dist/backend/publication.d.ts +2 -0
- package/dist/backend/publication.js +4 -0
- package/dist/backend/publication.js.map +1 -1
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-core.d.ts +19 -0
- package/dist/backend/runtime-pack-core.js +23 -3
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.test.js +48 -2
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-cpu.d.ts +2 -0
- package/dist/backend/target-cpu.js +4 -0
- package/dist/backend/target-cpu.js.map +1 -1
- package/dist/backend/target-diagnostics.js +1 -19
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/target-diagnostics.test.js +1 -1
- package/dist/backend/target-diagnostics.test.js.map +1 -1
- package/dist/backend/targets.d.ts +28 -0
- package/dist/backend/targets.js +70 -0
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +75 -1
- package/dist/backend/targets.test.js.map +1 -1
- package/dist/backend/vendor-archives.d.ts +1 -1
- package/dist/backend/vendor-archives.js +25 -12
- package/dist/backend/vendor-archives.js.map +1 -1
- package/dist/backend/vendor-inputs.d.ts +15 -2
- package/dist/backend/vendor-inputs.js +59 -3
- package/dist/backend/vendor-inputs.js.map +1 -1
- package/dist/backend/vendor-inputs.test.d.ts +1 -0
- package/dist/backend/vendor-inputs.test.js +74 -0
- package/dist/backend/vendor-inputs.test.js.map +1 -0
- package/dist/cli/command.js +95 -5
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/host.d.ts +3 -0
- package/dist/cli/output-options.d.ts +3 -0
- package/dist/cli/output-options.js +8 -2
- package/dist/cli/output-options.js.map +1 -1
- package/dist/cli/usage.d.ts +28 -1
- package/dist/cli/usage.js +56 -6
- package/dist/cli/usage.js.map +1 -1
- package/dist/compat/fetch-profile.d.ts +3 -0
- package/dist/compat/fetch-profile.js +23 -3
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/compile-types.d.ts +45 -0
- package/dist/contracts/check.js +70 -2
- package/dist/contracts/check.js.map +1 -1
- package/dist/contracts/int32-elements.d.ts +2 -1
- package/dist/contracts/int32-elements.js.map +1 -1
- package/dist/coverage/report.d.ts +5 -1
- package/dist/coverage/report.js +83 -2
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/verdict-cache.d.ts +2 -0
- package/dist/coverage/verdict-cache.js +5 -10
- package/dist/coverage/verdict-cache.js.map +1 -1
- package/dist/diagnostics/codes.d.ts +145 -0
- package/dist/diagnostics/codes.js +159 -0
- package/dist/diagnostics/codes.js.map +1 -0
- package/dist/diagnostics/codes.test.d.ts +1 -0
- package/dist/diagnostics/codes.test.js +78 -0
- package/dist/diagnostics/codes.test.js.map +1 -0
- package/dist/diagnostics/diagnostic.d.ts +101 -2
- package/dist/diagnostics/diagnostic.js +155 -0
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/dynamic-slots.d.ts +23 -0
- package/dist/diagnostics/dynamic-slots.js +29 -0
- package/dist/diagnostics/dynamic-slots.js.map +1 -0
- package/dist/diagnostics/dynamic-tier.d.ts +6 -0
- package/dist/diagnostics/dynamic-tier.js +8 -1
- package/dist/diagnostics/dynamic-tier.js.map +1 -1
- package/dist/diagnostics/envelope.d.ts +43 -1
- package/dist/diagnostics/envelope.js +19 -1
- package/dist/diagnostics/envelope.js.map +1 -1
- package/dist/diagnostics/envelope.test.js.map +1 -1
- package/dist/diagnostics/render.d.ts +3 -1
- package/dist/diagnostics/render.js +27 -6
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +41 -0
- package/dist/executable/executable-cache.js +39 -1
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +4 -1
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.d.ts +2 -1
- package/dist/executable/prepare.js +421 -10
- package/dist/executable/prepare.js.map +1 -1
- package/dist/frontend/analysis.js +1 -0
- package/dist/frontend/analysis.js.map +1 -1
- package/dist/frontend/canon-map.d.ts +17 -0
- package/dist/frontend/canon-map.js +177 -0
- package/dist/frontend/canon-map.js.map +1 -0
- package/dist/frontend/canon.d.ts +122 -0
- package/dist/frontend/canon.js +462 -0
- package/dist/frontend/canon.js.map +1 -0
- package/dist/frontend/contract-types.d.ts +9 -1
- package/dist/frontend/contract-types.js +46 -4
- package/dist/frontend/contract-types.js.map +1 -1
- package/dist/frontend/decl-projection.d.ts +3 -0
- package/dist/frontend/decl-projection.js +121 -3
- package/dist/frontend/decl-projection.js.map +1 -1
- package/dist/frontend/dts-paths.d.ts +17 -4
- package/dist/frontend/dts-paths.js +149 -5
- package/dist/frontend/dts-paths.js.map +1 -1
- package/dist/frontend/fork-target.js +4 -4
- package/dist/frontend/fork-target.js.map +1 -1
- package/dist/frontend/fork-target.test.js +3 -3
- package/dist/frontend/fork-target.test.js.map +1 -1
- package/dist/frontend/heritage-elements.d.ts +15 -0
- package/dist/frontend/heritage-elements.js +18 -0
- package/dist/frontend/heritage-elements.js.map +1 -0
- package/dist/frontend/heritage-elements.test.d.ts +1 -0
- package/dist/frontend/heritage-elements.test.js +68 -0
- package/dist/frontend/heritage-elements.test.js.map +1 -0
- package/dist/frontend/input-tracker.d.ts +20 -0
- package/dist/frontend/input-tracker.js +74 -4
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +66 -0
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/lowering/any-collection-residue.d.ts +9 -0
- package/dist/frontend/lowering/any-collection-residue.js +42 -0
- package/dist/frontend/lowering/any-collection-residue.js.map +1 -0
- package/dist/frontend/lowering/array-values.d.ts +44 -2
- package/dist/frontend/lowering/array-values.js +193 -3
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/builtin-namespaces.d.ts +6 -2
- package/dist/frontend/lowering/builtin-namespaces.js +28 -6
- package/dist/frontend/lowering/builtin-namespaces.js.map +1 -1
- package/dist/frontend/lowering/builtins/array-classes.d.ts +69 -0
- package/dist/frontend/lowering/builtins/array-classes.js +729 -0
- package/dist/frontend/lowering/builtins/array-classes.js.map +1 -0
- package/dist/frontend/lowering/builtins/callable-aliases.js +4 -0
- package/dist/frontend/lowering/builtins/callable-aliases.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-methods.js +34 -0
- package/dist/frontend/lowering/builtins/child-process-methods.js.map +1 -1
- package/dist/frontend/lowering/builtins/disposable-stack.js +1 -3
- package/dist/frontend/lowering/builtins/disposable-stack.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.d.ts +13 -9
- package/dist/frontend/lowering/builtins/errors.js +136 -56
- package/dist/frontend/lowering/builtins/errors.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +1 -0
- package/dist/frontend/lowering/builtins/filesystem-calls.js +85 -4
- package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem.d.ts +11 -6
- package/dist/frontend/lowering/builtins/filesystem.js +270 -24
- package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
- package/dist/frontend/lowering/builtins/json.js +7 -1
- package/dist/frontend/lowering/builtins/json.js.map +1 -1
- package/dist/frontend/lowering/builtins/mime.d.ts +25 -0
- package/dist/frontend/lowering/builtins/mime.js +167 -0
- package/dist/frontend/lowering/builtins/mime.js.map +1 -0
- package/dist/frontend/lowering/builtins/module-bindings.d.ts +3 -0
- package/dist/frontend/lowering/builtins/module-bindings.js +6 -0
- package/dist/frontend/lowering/builtins/module-bindings.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-calls.js +79 -12
- package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-resolution.d.ts +7 -4
- package/dist/frontend/lowering/builtins/module-resolution.js +115 -13
- package/dist/frontend/lowering/builtins/module-resolution.js.map +1 -1
- package/dist/frontend/lowering/builtins/navigator.d.ts +3 -1
- package/dist/frontend/lowering/builtins/navigator.js +22 -8
- package/dist/frontend/lowering/builtins/navigator.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.js +49 -9
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/builtins/promises.js +18 -3
- package/dist/frontend/lowering/builtins/promises.js.map +1 -1
- package/dist/frontend/lowering/builtins/promisify-callback.d.ts +6 -2
- package/dist/frontend/lowering/builtins/promisify-callback.js +19 -6
- package/dist/frontend/lowering/builtins/promisify-callback.js.map +1 -1
- package/dist/frontend/lowering/builtins/properties.js +23 -5
- package/dist/frontend/lowering/builtins/properties.js.map +1 -1
- package/dist/frontend/lowering/builtins/web-streams-dyn.d.ts +42 -0
- package/dist/frontend/lowering/builtins/web-streams-dyn.js +321 -0
- package/dist/frontend/lowering/builtins/web-streams-dyn.js.map +1 -0
- package/dist/frontend/lowering/builtins/x509.js +35 -5
- package/dist/frontend/lowering/builtins/x509.js.map +1 -1
- package/dist/frontend/lowering/call-arguments.d.ts +14 -1
- package/dist/frontend/lowering/call-arguments.js +84 -70
- package/dist/frontend/lowering/call-arguments.js.map +1 -1
- package/dist/frontend/lowering/call-signatures.js +108 -24
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/class-attributes.js +6 -5
- package/dist/frontend/lowering/class-attributes.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.js +40 -19
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
- package/dist/frontend/lowering/class-protocol-dispatch.js +4 -0
- package/dist/frontend/lowering/class-protocol-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-protocols.d.ts +61 -1
- package/dist/frontend/lowering/class-protocols.js +297 -21
- package/dist/frontend/lowering/class-protocols.js.map +1 -1
- package/dist/frontend/lowering/class-to-primitive.d.ts +3 -2
- package/dist/frontend/lowering/class-to-primitive.js +15 -5
- package/dist/frontend/lowering/class-to-primitive.js.map +1 -1
- package/dist/frontend/lowering/coercions/asserted.d.ts +16 -0
- package/dist/frontend/lowering/coercions/asserted.js +79 -0
- package/dist/frontend/lowering/coercions/asserted.js.map +1 -0
- package/dist/frontend/lowering/coercions/function-adapters.d.ts +13 -0
- package/dist/frontend/lowering/coercions/function-adapters.js +70 -3
- package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
- package/dist/frontend/lowering/coercions/state.d.ts +23 -0
- package/dist/frontend/lowering/coercions/state.js +9 -0
- package/dist/frontend/lowering/coercions/state.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural-plans.js +67 -1
- package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural.d.ts +10 -0
- package/dist/frontend/lowering/coercions/structural.js +134 -4
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/coercions/unions.d.ts +11 -0
- package/dist/frontend/lowering/coercions/unions.js +83 -4
- package/dist/frontend/lowering/coercions/unions.js.map +1 -1
- package/dist/frontend/lowering/completion-callbacks.js +3 -2
- package/dist/frontend/lowering/completion-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.d.ts +10 -0
- package/dist/frontend/lowering/containers/array-callbacks.js +224 -81
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-concat.d.ts +5 -2
- package/dist/frontend/lowering/containers/array-concat.js +76 -7
- package/dist/frontend/lowering/containers/array-concat.js.map +1 -1
- package/dist/frontend/lowering/containers/array-construction.d.ts +9 -4
- package/dist/frontend/lowering/containers/array-construction.js +112 -100
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.js +193 -45
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/array-pipelines.d.ts +3 -0
- package/dist/frontend/lowering/containers/array-pipelines.js +81 -13
- package/dist/frontend/lowering/containers/array-pipelines.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.d.ts +1 -0
- package/dist/frontend/lowering/containers/callback-arguments.js +28 -2
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +13 -3
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/filter-predicates.js +34 -3
- package/dist/frontend/lowering/containers/filter-predicates.js.map +1 -1
- package/dist/frontend/lowering/containers/indexed-objects.d.ts +34 -1
- package/dist/frontend/lowering/containers/indexed-objects.js +131 -72
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/cycle-initialization.js +43 -6
- package/dist/frontend/lowering/cycle-initialization.js.map +1 -1
- package/dist/frontend/lowering/decl-origin.d.ts +49 -0
- package/dist/frontend/lowering/decl-origin.js +402 -0
- package/dist/frontend/lowering/decl-origin.js.map +1 -0
- package/dist/frontend/lowering/deferred-module-initializers.d.ts +2 -0
- package/dist/frontend/lowering/deferred-module-initializers.js +7 -0
- package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -1
- package/dist/frontend/lowering/divergences.js +5 -0
- package/dist/frontend/lowering/divergences.js.map +1 -1
- package/dist/frontend/lowering/dynamic-tier.d.ts +8 -2
- package/dist/frontend/lowering/dynamic-tier.js +111 -3
- package/dist/frontend/lowering/dynamic-tier.js.map +1 -1
- package/dist/frontend/lowering/expressions/array-literals.d.ts +14 -1
- package/dist/frontend/lowering/expressions/array-literals.js +43 -5
- package/dist/frontend/lowering/expressions/array-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/asserted-receiver.d.ts +48 -0
- package/dist/frontend/lowering/expressions/asserted-receiver.js +233 -0
- package/dist/frontend/lowering/expressions/asserted-receiver.js.map +1 -0
- package/dist/frontend/lowering/expressions/binary.js +136 -1
- package/dist/frontend/lowering/expressions/binary.js.map +1 -1
- package/dist/frontend/lowering/expressions/element-access.d.ts +7 -0
- package/dist/frontend/lowering/expressions/element-access.js +363 -12
- package/dist/frontend/lowering/expressions/element-access.js.map +1 -1
- package/dist/frontend/lowering/expressions/identifiers.d.ts +3 -0
- package/dist/frontend/lowering/expressions/identifiers.js +78 -62
- package/dist/frontend/lowering/expressions/identifiers.js.map +1 -1
- package/dist/frontend/lowering/expressions/message-listeners.d.ts +3 -0
- package/dist/frontend/lowering/expressions/message-listeners.js +19 -0
- package/dist/frontend/lowering/expressions/message-listeners.js.map +1 -0
- package/dist/frontend/lowering/expressions/narrowing.js +224 -6
- package/dist/frontend/lowering/expressions/narrowing.js.map +1 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js +5 -2
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.d.ts +1 -1
- package/dist/frontend/lowering/expressions/object-literals.js +282 -24
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/property-access.d.ts +15 -3
- package/dist/frontend/lowering/expressions/property-access.js +397 -74
- package/dist/frontend/lowering/expressions/property-access.js.map +1 -1
- package/dist/frontend/lowering/expressions/relational.js +202 -70
- package/dist/frontend/lowering/expressions/relational.js.map +1 -1
- package/dist/frontend/lowering/expressions/typeof.js +9 -1
- package/dist/frontend/lowering/expressions/typeof.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-fields.d.ts +28 -8
- package/dist/frontend/lowering/expressions/union-fields.js +168 -14
- package/dist/frontend/lowering/expressions/union-fields.js.map +1 -1
- package/dist/frontend/lowering/frozen-records.d.ts +8 -0
- package/dist/frontend/lowering/frozen-records.js +56 -9
- package/dist/frontend/lowering/frozen-records.js.map +1 -1
- package/dist/frontend/lowering/function-context.d.ts +3 -0
- package/dist/frontend/lowering/function-context.js +4 -1
- package/dist/frontend/lowering/function-context.js.map +1 -1
- package/dist/frontend/lowering/function-returns.d.ts +4 -0
- package/dist/frontend/lowering/function-returns.js +231 -2
- package/dist/frontend/lowering/function-returns.js.map +1 -1
- package/dist/frontend/lowering/generator-delegation.js +3 -2
- package/dist/frontend/lowering/generator-delegation.js.map +1 -1
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +26 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +294 -2
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/generic-functions.d.ts +10 -0
- package/dist/frontend/lowering/generic-functions.js +67 -7
- package/dist/frontend/lowering/generic-functions.js.map +1 -1
- package/dist/frontend/lowering/global-values.d.ts +37 -0
- package/dist/frontend/lowering/global-values.js +395 -0
- package/dist/frontend/lowering/global-values.js.map +1 -0
- package/dist/frontend/lowering/handle-properties.js +3 -2
- package/dist/frontend/lowering/handle-properties.js.map +1 -1
- package/dist/frontend/lowering/handle-properties.test.d.ts +1 -0
- package/dist/frontend/lowering/handle-properties.test.js +25 -0
- package/dist/frontend/lowering/handle-properties.test.js.map +1 -0
- package/dist/frontend/lowering/import-meta.d.ts +3 -0
- package/dist/frontend/lowering/import-meta.js +8 -3
- package/dist/frontend/lowering/import-meta.js.map +1 -1
- package/dist/frontend/lowering/iterator-adapters.js +3 -3
- package/dist/frontend/lowering/iterator-adapters.js.map +1 -1
- package/dist/frontend/lowering/key-order-witness.d.ts +2 -0
- package/dist/frontend/lowering/key-order-witness.js +10 -0
- package/dist/frontend/lowering/key-order-witness.js.map +1 -1
- package/dist/frontend/lowering/lower-array-sort.d.ts +5 -1
- package/dist/frontend/lowering/lower-array-sort.js +16 -2
- package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +7 -0
- package/dist/frontend/lowering/lower-builtin-values.js +65 -16
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +222 -24
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +6 -0
- package/dist/frontend/lowering/lower-classes.js +154 -20
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-console.js +25 -2
- package/dist/frontend/lowering/lower-console.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +29 -0
- package/dist/frontend/lowering/lower-exprs.js +544 -24
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.js +93 -18
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.d.ts +4 -1
- package/dist/frontend/lowering/lower-global-value.js +10 -3
- package/dist/frontend/lowering/lower-global-value.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.d.ts +44 -4
- package/dist/frontend/lowering/lower-inspect.js +723 -26
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +3 -1
- package/dist/frontend/lowering/lower-modules.js +189 -24
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +7 -0
- package/dist/frontend/lowering/lower-namespaces.js +23 -0
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-node-island.d.ts +74 -0
- package/dist/frontend/lowering/lower-node-island.js +1931 -0
- package/dist/frontend/lowering/lower-node-island.js.map +1 -0
- package/dist/frontend/lowering/lower-server.js +44 -0
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-shared-modules.d.ts +27 -0
- package/dist/frontend/lowering/lower-shared-modules.js +611 -0
- package/dist/frontend/lowering/lower-shared-modules.js.map +1 -0
- package/dist/frontend/lowering/lower-stdlib.js +85 -9
- package/dist/frontend/lowering/lower-stdlib.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +2 -6
- package/dist/frontend/lowering/lower-stmts.js +781 -143
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +548 -36
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-timers.js +9 -0
- package/dist/frontend/lowering/lower-timers.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +514 -10
- package/dist/frontend/lowering/lowerer.js +2667 -163
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +44 -1
- package/dist/frontend/lowering/lowerer.test.js.map +1 -1
- package/dist/frontend/lowering/maybe-promise.d.ts +6 -0
- package/dist/frontend/lowering/maybe-promise.js +13 -0
- package/dist/frontend/lowering/maybe-promise.js.map +1 -1
- package/dist/frontend/lowering/module-namespace-elements.d.ts +12 -0
- package/dist/frontend/lowering/module-namespace-elements.js +114 -18
- package/dist/frontend/lowering/module-namespace-elements.js.map +1 -1
- package/dist/frontend/lowering/nan-coded-reads.d.ts +11 -0
- package/dist/frontend/lowering/nan-coded-reads.js +45 -2
- package/dist/frontend/lowering/nan-coded-reads.js.map +1 -1
- package/dist/frontend/lowering/narrowing-stability.d.ts +4 -0
- package/dist/frontend/lowering/narrowing-stability.js +14 -6
- package/dist/frontend/lowering/narrowing-stability.js.map +1 -1
- package/dist/frontend/lowering/receiver-returns.d.ts +3 -0
- package/dist/frontend/lowering/receiver-returns.js +134 -0
- package/dist/frontend/lowering/receiver-returns.js.map +1 -0
- package/dist/frontend/lowering/record-inherited.d.ts +26 -0
- package/dist/frontend/lowering/record-inherited.js +807 -0
- package/dist/frontend/lowering/record-inherited.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-elements.d.ts +31 -1
- package/dist/frontend/lowering/runtime-optional-elements.js +105 -13
- package/dist/frontend/lowering/runtime-optional-elements.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-guards.d.ts +3 -0
- package/dist/frontend/lowering/runtime-optional-guards.js +35 -7
- package/dist/frontend/lowering/runtime-optional-guards.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-guards.test.js +59 -1
- package/dist/frontend/lowering/runtime-optional-guards.test.js.map +1 -1
- package/dist/frontend/lowering/stable-names.d.ts +8 -0
- package/dist/frontend/lowering/stable-names.js +22 -0
- package/dist/frontend/lowering/stable-names.js.map +1 -1
- package/dist/frontend/lowering/stable-names.test.d.ts +1 -0
- package/dist/frontend/lowering/stable-names.test.js +16 -0
- package/dist/frontend/lowering/stable-names.test.js.map +1 -0
- package/dist/frontend/lowering/static-typeof.d.ts +5 -4
- package/dist/frontend/lowering/static-typeof.js +10 -4
- package/dist/frontend/lowering/static-typeof.js.map +1 -1
- package/dist/frontend/lowering/structural-instances.d.ts +22 -0
- package/dist/frontend/lowering/structural-instances.js +282 -0
- package/dist/frontend/lowering/structural-instances.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +3 -0
- package/dist/frontend/lowering/surfaces.js +108 -12
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/symbol-fields.d.ts +7 -0
- package/dist/frontend/lowering/symbol-fields.js +32 -0
- package/dist/frontend/lowering/symbol-fields.js.map +1 -1
- package/dist/frontend/lowering/type-failure.d.ts +17 -0
- package/dist/frontend/lowering/type-failure.js +163 -0
- package/dist/frontend/lowering/type-failure.js.map +1 -0
- package/dist/frontend/lowering/typed-arguments.d.ts +5 -6
- package/dist/frontend/lowering/typed-arguments.js +10 -2
- package/dist/frontend/lowering/typed-arguments.js.map +1 -1
- package/dist/frontend/lowering/union-narrow.d.ts +9 -1
- package/dist/frontend/lowering/union-narrow.js +31 -2
- package/dist/frontend/lowering/union-narrow.js.map +1 -1
- package/dist/frontend/lowering/union-retag.test.js +42 -2
- package/dist/frontend/lowering/union-retag.test.js.map +1 -1
- package/dist/frontend/lowering/unit-journal.d.ts +194 -0
- package/dist/frontend/lowering/unit-journal.js +556 -0
- package/dist/frontend/lowering/unit-journal.js.map +1 -0
- package/dist/frontend/lowering/unit-journal.test.d.ts +1 -0
- package/dist/frontend/lowering/unit-journal.test.js +335 -0
- package/dist/frontend/lowering/unit-journal.test.js.map +1 -0
- package/dist/frontend/lowering/width-lift.d.ts +19 -0
- package/dist/frontend/node-api-import.d.ts +21 -0
- package/dist/frontend/node-api-import.js +88 -0
- package/dist/frontend/node-api-import.js.map +1 -0
- package/dist/frontend/npm-static-type-exports-host.js +4 -3
- package/dist/frontend/npm-static-type-exports-host.js.map +1 -1
- package/dist/frontend/npm-static.js +9 -2
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/package-shims.d.ts +6 -2
- package/dist/frontend/package-shims.js +13 -2
- package/dist/frontend/package-shims.js.map +1 -1
- package/dist/frontend/pipeline.d.ts +11 -4
- package/dist/frontend/pipeline.js +249 -26
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/process-fork.d.ts +3 -0
- package/dist/frontend/process-fork.js.map +1 -1
- package/dist/frontend/program-analysis.d.ts +6 -0
- package/dist/frontend/program-analysis.js +4 -0
- package/dist/frontend/program-analysis.js.map +1 -1
- package/dist/frontend/program.d.ts +12 -1
- package/dist/frontend/program.js +256 -36
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.js +8 -2
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/shape-inference/analyze.d.ts +23 -1
- package/dist/frontend/shape-inference/analyze.js +982 -97
- package/dist/frontend/shape-inference/analyze.js.map +1 -1
- package/dist/frontend/shape-inference/constant-graphs.d.ts +2 -0
- package/dist/frontend/shape-inference/constant-graphs.js +39 -4
- package/dist/frontend/shape-inference/constant-graphs.js.map +1 -1
- package/dist/frontend/shape-inference/domain.d.ts +2 -0
- package/dist/frontend/shape-inference/domain.js.map +1 -1
- package/dist/frontend/shape-inference/fallback.d.ts +17 -0
- package/dist/frontend/shape-inference/fallback.js +303 -0
- package/dist/frontend/shape-inference/fallback.js.map +1 -0
- package/dist/frontend/shape-inference/index.d.ts +75 -1
- package/dist/frontend/shape-inference/index.js +531 -2
- package/dist/frontend/shape-inference/index.js.map +1 -1
- package/dist/frontend/shape-inference/inferred-checks.d.ts +2 -0
- package/dist/frontend/shape-inference/inferred-checks.js +90 -0
- package/dist/frontend/shape-inference/inferred-checks.js.map +1 -0
- package/dist/frontend/shape-inference/memo.d.ts +30 -0
- package/dist/frontend/shape-inference/memo.js +99 -0
- package/dist/frontend/shape-inference/memo.js.map +1 -0
- package/dist/frontend/shape-inference/overlay.d.ts +81 -0
- package/dist/frontend/shape-inference/overlay.js +1160 -0
- package/dist/frontend/shape-inference/overlay.js.map +1 -0
- package/dist/frontend/shape-inference/registry.test.d.ts +1 -0
- package/dist/frontend/shape-inference/registry.test.js +34 -0
- package/dist/frontend/shape-inference/registry.test.js.map +1 -0
- package/dist/frontend/shape-inference/report.js +42 -8
- package/dist/frontend/shape-inference/report.js.map +1 -1
- package/dist/frontend/shape-inference/static-objects.d.ts +29 -0
- package/dist/frontend/shape-inference/static-objects.js +1951 -0
- package/dist/frontend/shape-inference/static-objects.js.map +1 -0
- package/dist/frontend/tier-analysis.d.ts +53 -1
- package/dist/frontend/tier-analysis.js +133 -0
- package/dist/frontend/tier-analysis.js.map +1 -1
- package/dist/frontend/ts7/api.js +4 -2
- package/dist/frontend/ts7/api.js.map +1 -1
- package/dist/frontend/ts7/ast-node.d.ts +9 -0
- package/dist/frontend/ts7/ast-node.js +42 -10
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-node.test.js +23 -0
- package/dist/frontend/ts7/ast-node.test.js.map +1 -1
- package/dist/frontend/ts7/ast-wire-protocols.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-wire-protocols.test.js +93 -0
- package/dist/frontend/ts7/ast-wire-protocols.test.js.map +1 -0
- package/dist/frontend/ts7/ast-wire.d.ts +18 -0
- package/dist/frontend/ts7/ast-wire.js +66 -4
- package/dist/frontend/ts7/ast-wire.js.map +1 -1
- package/dist/frontend/ts7/checker-server.d.ts +12 -11
- package/dist/frontend/ts7/checker-server.js +28 -12
- package/dist/frontend/ts7/checker-server.js.map +1 -1
- package/dist/frontend/ts7/checker-server.test.js +8 -3
- package/dist/frontend/ts7/checker-server.test.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +4 -0
- package/dist/frontend/ts7/checker.js +9 -0
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.js +216 -205
- package/dist/frontend/ts7/checker.test.js.map +1 -1
- package/dist/frontend/ts7/lib-diagnostics.d.ts +71 -4
- package/dist/frontend/ts7/lib-diagnostics.js +337 -20
- package/dist/frontend/ts7/lib-diagnostics.js.map +1 -1
- package/dist/frontend/ts7/lib-diagnostics.test.js +268 -5
- package/dist/frontend/ts7/lib-diagnostics.test.js.map +1 -1
- package/dist/frontend/ts7/native-api.d.ts +4 -0
- package/dist/frontend/ts7/native-api.js +36 -1
- package/dist/frontend/ts7/native-api.js.map +1 -1
- package/dist/frontend/ts7/program-host.d.ts +19 -2
- package/dist/frontend/ts7/program-host.js +69 -9
- package/dist/frontend/ts7/program-host.js.map +1 -1
- package/dist/frontend/ts7/program-host.test.js +42 -1
- package/dist/frontend/ts7/program-host.test.js.map +1 -1
- package/dist/frontend/ts7/rpc-filesystem.d.ts +4 -2
- package/dist/frontend/ts7/rpc-filesystem.js +23 -2
- package/dist/frontend/ts7/rpc-filesystem.js.map +1 -1
- package/dist/frontend/ts7/rpc-filesystem.test.js +28 -2
- package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-checker.js +73 -5
- package/dist/frontend/ts7/semantic-checker.js.map +1 -1
- package/dist/frontend/ts7/semantic-checker.test.js +106 -74
- package/dist/frontend/ts7/semantic-checker.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-json.d.ts +2 -6
- package/dist/frontend/ts7/semantic-model-71.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-model-71.test.js +131 -0
- package/dist/frontend/ts7/semantic-model-71.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.d.ts +121 -3
- package/dist/frontend/ts7/semantic-model.js +245 -8
- package/dist/frontend/ts7/semantic-model.js.map +1 -1
- package/dist/frontend/ts7/session.d.ts +19 -1
- package/dist/frontend/ts7/session.js +111 -11
- package/dist/frontend/ts7/session.js.map +1 -1
- package/dist/frontend/ts7/session.test.js +259 -239
- package/dist/frontend/ts7/session.test.js.map +1 -1
- package/dist/frontend/ts7/test-servers.d.ts +12 -0
- package/dist/frontend/ts7/test-servers.js +16 -0
- package/dist/frontend/ts7/test-servers.js.map +1 -0
- package/dist/frontend/tsc-codes.js +6 -3
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +61 -1
- package/dist/frontend/type-mapper.js +577 -28
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-patches/command.d.ts +19 -0
- package/dist/frontend/type-patches/command.js +352 -0
- package/dist/frontend/type-patches/command.js.map +1 -0
- package/dist/frontend/type-patches/layer.d.ts +45 -0
- package/dist/frontend/type-patches/layer.js +409 -0
- package/dist/frontend/type-patches/layer.js.map +1 -0
- package/dist/frontend/type-patches/locate.d.ts +41 -0
- package/dist/frontend/type-patches/locate.js +914 -0
- package/dist/frontend/type-patches/locate.js.map +1 -0
- package/dist/frontend/type-patches/locate.test.d.ts +1 -0
- package/dist/frontend/type-patches/locate.test.js +179 -0
- package/dist/frontend/type-patches/locate.test.js.map +1 -0
- package/dist/frontend/type-patches/selector.d.ts +43 -0
- package/dist/frontend/type-patches/selector.js +126 -0
- package/dist/frontend/type-patches/selector.js.map +1 -0
- package/dist/frontend/type-patches/selector.test.d.ts +1 -0
- package/dist/frontend/type-patches/selector.test.js +56 -0
- package/dist/frontend/type-patches/selector.test.js.map +1 -0
- package/dist/frontend/type-patches/semver.d.ts +19 -0
- package/dist/frontend/type-patches/semver.js +221 -0
- package/dist/frontend/type-patches/semver.js.map +1 -0
- package/dist/frontend/type-patches/semver.test.d.ts +1 -0
- package/dist/frontend/type-patches/semver.test.js +47 -0
- package/dist/frontend/type-patches/semver.test.js.map +1 -0
- package/dist/frontend/worker-target.test.js +2 -2
- package/dist/frontend/worker-target.test.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +292 -27
- package/dist/index.js.map +1 -1
- package/dist/ir/builtin-effects.js +51 -5
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +4 -3
- package/dist/ir/builtin-signatures.js +277 -12
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/callback-specialization.js +108 -67
- package/dist/ir/callback-specialization.js.map +1 -1
- package/dist/ir/capture-values.d.ts +7 -1
- package/dist/ir/capture-values.js +28 -5
- package/dist/ir/capture-values.js.map +1 -1
- package/dist/ir/char-unit-locals.js +38 -42
- package/dist/ir/char-unit-locals.js.map +1 -1
- package/dist/ir/expression-inlining.js +12 -6
- package/dist/ir/expression-inlining.js.map +1 -1
- package/dist/ir/fields.generated.d.ts +751 -0
- package/dist/ir/fields.generated.js +2071 -0
- package/dist/ir/fields.generated.js.map +1 -0
- package/dist/ir/fields.test.d.ts +1 -0
- package/dist/ir/fields.test.js +113 -0
- package/dist/ir/fields.test.js.map +1 -0
- package/dist/ir/function-references.js +4 -0
- package/dist/ir/function-references.js.map +1 -1
- package/dist/ir/function-references.test.js +25 -0
- package/dist/ir/function-references.test.js.map +1 -1
- package/dist/ir/inline-array-sources.d.ts +15 -0
- package/dist/ir/inline-array-sources.js +1825 -0
- package/dist/ir/inline-array-sources.js.map +1 -0
- package/dist/ir/inline-arrays.d.ts +41 -0
- package/dist/ir/inline-arrays.js +533 -0
- package/dist/ir/inline-arrays.js.map +1 -0
- package/dist/ir/inline-arrays.test.d.ts +1 -0
- package/dist/ir/inline-arrays.test.js +225 -0
- package/dist/ir/inline-arrays.test.js.map +1 -0
- package/dist/ir/int32-slots.d.ts +6 -0
- package/dist/ir/int32-slots.js +154 -16
- package/dist/ir/int32-slots.js.map +1 -1
- package/dist/ir/int32-slots.test.js +48 -0
- package/dist/ir/int32-slots.test.js.map +1 -1
- package/dist/ir/integer-loops.d.ts +12 -0
- package/dist/ir/integer-loops.js +23 -0
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-ranges.d.ts +7 -1
- package/dist/ir/integer-ranges.js +29 -2
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/intrinsic-signatures.js +2 -1
- package/dist/ir/intrinsic-signatures.js.map +1 -1
- package/dist/ir/ir.d.ts +103 -5
- package/dist/ir/ir.js +38 -4
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +134 -1
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/jsval.js +211 -29
- package/dist/ir/jsval.js.map +1 -1
- package/dist/ir/jsval.test.js +120 -0
- package/dist/ir/jsval.test.js.map +1 -1
- package/dist/ir/loop-entry-ranges.d.ts +38 -0
- package/dist/ir/loop-entry-ranges.js +259 -0
- package/dist/ir/loop-entry-ranges.js.map +1 -0
- package/dist/ir/loop-entry-ranges.test.d.ts +1 -0
- package/dist/ir/loop-entry-ranges.test.js +191 -0
- package/dist/ir/loop-entry-ranges.test.js.map +1 -0
- package/dist/ir/node-index.d.ts +3 -0
- package/dist/ir/node-index.js +6 -0
- package/dist/ir/node-index.js.map +1 -1
- package/dist/ir/numeric-call-specialization.d.ts +9 -6
- package/dist/ir/numeric-call-specialization.js +164 -34
- package/dist/ir/numeric-call-specialization.js.map +1 -1
- package/dist/ir/paired-while-loops.js +23 -19
- package/dist/ir/paired-while-loops.js.map +1 -1
- package/dist/ir/parameter-versions.js +6 -3
- package/dist/ir/parameter-versions.js.map +1 -1
- package/dist/ir/receiver-readers.d.ts +10 -0
- package/dist/ir/receiver-readers.js +65 -28
- package/dist/ir/receiver-readers.js.map +1 -1
- package/dist/ir/row-pairs.d.ts +9 -1
- package/dist/ir/row-pairs.js +136 -43
- package/dist/ir/row-pairs.js.map +1 -1
- package/dist/ir/row-pairs.test.js +25 -5
- package/dist/ir/row-pairs.test.js.map +1 -1
- package/dist/ir/runtime-features.d.ts +33 -1
- package/dist/ir/runtime-features.js +104 -6
- package/dist/ir/runtime-features.js.map +1 -1
- package/dist/ir/runtime-features.test.js +13 -0
- package/dist/ir/runtime-features.test.js.map +1 -1
- package/dist/ir/saturating-loop-jams.d.ts +24 -0
- package/dist/ir/saturating-loop-jams.js +420 -0
- package/dist/ir/saturating-loop-jams.js.map +1 -0
- package/dist/ir/saturating-loop-jams.test.d.ts +1 -0
- package/dist/ir/saturating-loop-jams.test.js +196 -0
- package/dist/ir/saturating-loop-jams.test.js.map +1 -0
- package/dist/ir/scalar-records.js +9 -3
- package/dist/ir/scalar-records.js.map +1 -1
- package/dist/ir/self-captures.js +2 -1
- package/dist/ir/self-captures.js.map +1 -1
- package/dist/ir/serialize.d.ts +5 -1
- package/dist/ir/serialize.js +7 -1
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/traverse.js +3 -0
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +91 -9
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/ir-policy.js +1 -0
- package/dist/library/ir-policy.js.map +1 -1
- package/dist/native/cache.js +2 -0
- package/dist/native/cache.js.map +1 -1
- package/dist/native/cli.js +54 -7
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.d.ts +3 -0
- package/dist/native/compiler.js +173 -36
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/compiler.test.js +86 -3
- package/dist/native/compiler.test.js.map +1 -1
- package/dist/native/executable-cache.d.ts +20 -2
- package/dist/native/executable-cache.js +17 -10
- package/dist/native/executable-cache.js.map +1 -1
- package/dist/native/executable-cache.test.js +38 -1
- package/dist/native/executable-cache.test.js.map +1 -1
- package/dist/native/linker-job.d.ts +71 -0
- package/dist/native/linker-job.js +242 -0
- package/dist/native/linker-job.js.map +1 -0
- package/dist/native/linker-job.test.d.ts +1 -0
- package/dist/native/linker-job.test.js +349 -0
- package/dist/native/linker-job.test.js.map +1 -0
- package/dist/native/prepare.js +15 -2
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/sanitizer.js +10 -15
- package/dist/native/sanitizer.js.map +1 -1
- package/dist/native/sanitizer.test.js +152 -66
- package/dist/native/sanitizer.test.js.map +1 -1
- package/dist/native/toolchain.d.ts +11 -2
- package/dist/native/toolchain.js +43 -17
- package/dist/native/toolchain.js.map +1 -1
- package/dist/native/toolchain.test.js +75 -0
- package/dist/native/toolchain.test.js.map +1 -1
- package/dist/node-islands/boundary.d.ts +37 -0
- package/dist/node-islands/boundary.js +135 -0
- package/dist/node-islands/boundary.js.map +1 -0
- package/dist/node-islands/classify.js +1 -1
- package/dist/node-islands/classify.js.map +1 -1
- package/dist/node-islands/effect-gate.d.ts +11 -0
- package/dist/node-islands/effect-gate.js +746 -0
- package/dist/node-islands/effect-gate.js.map +1 -0
- package/dist/node-islands/effect-gate.test.d.ts +1 -0
- package/dist/node-islands/effect-gate.test.js +152 -0
- package/dist/node-islands/effect-gate.test.js.map +1 -0
- package/dist/node-islands/libnode-pack.d.ts +68 -0
- package/dist/node-islands/libnode-pack.js +199 -0
- package/dist/node-islands/libnode-pack.js.map +1 -0
- package/dist/node-islands/libnode-pack.test.d.ts +1 -0
- package/dist/node-islands/libnode-pack.test.js +258 -0
- package/dist/node-islands/libnode-pack.test.js.map +1 -0
- package/dist/node-islands/libnode.d.ts +32 -0
- package/dist/node-islands/libnode.js +212 -0
- package/dist/node-islands/libnode.js.map +1 -0
- package/dist/node-islands/libnode.test.d.ts +1 -0
- package/dist/node-islands/libnode.test.js +170 -0
- package/dist/node-islands/libnode.test.js.map +1 -0
- package/dist/node-islands/modules.d.ts +96 -0
- package/dist/node-islands/modules.js +803 -0
- package/dist/node-islands/modules.js.map +1 -0
- package/dist/node-islands/modules.test.d.ts +1 -0
- package/dist/node-islands/modules.test.js +276 -0
- package/dist/node-islands/modules.test.js.map +1 -0
- package/dist/node-islands/resolve.d.ts +8 -0
- package/dist/node-islands/resolve.js +10 -0
- package/dist/node-islands/resolve.js.map +1 -0
- package/dist/node-islands/snapshot.d.ts +16 -0
- package/dist/node-islands/snapshot.js +486 -0
- package/dist/node-islands/snapshot.js.map +1 -0
- package/dist/node-islands/snapshot.test.d.ts +1 -0
- package/dist/node-islands/snapshot.test.js +56 -0
- package/dist/node-islands/snapshot.test.js.map +1 -0
- package/dist/project-config.d.ts +37 -1
- package/dist/project-config.js +159 -7
- package/dist/project-config.js.map +1 -1
- package/dist/project-config.test.js +153 -0
- package/dist/project-config.test.js.map +1 -1
- package/dist/startup-cache.d.ts +1 -0
- package/dist/startup-cache.js +1 -0
- package/dist/startup-cache.js.map +1 -1
- package/package.json +24 -21
- package/surface-manifest.json +47 -7
|
@@ -0,0 +1,1719 @@
|
|
|
1
|
+
/* Region groups: call sites whose result is a fresh object graph the
|
|
2
|
+
* caller only borrows and then drops, so everything the call allocates
|
|
3
|
+
* can live in an arena that is dropped at once (arenas.ts).
|
|
4
|
+
*
|
|
5
|
+
* The group of a call is every object allocated while it runs. It can be
|
|
6
|
+
* dropped with its result when nothing outside reaches any member once the
|
|
7
|
+
* call returns except through the result. A function is leak-free when
|
|
8
|
+
* every value it allocates (an allocation, a fresh-producing builtin, or
|
|
9
|
+
* the result of a call) dies in its frame, is returned, or is stored into
|
|
10
|
+
* the graph of a value it returns, and every function it calls is
|
|
11
|
+
* leak-free too. Members may refer out of the group (to longer-lived
|
|
12
|
+
* objects, which an arena would release when it drops); nothing outside
|
|
13
|
+
* may refer in. A function is fresh when it is leak-free and returns only
|
|
14
|
+
* values it allocated.
|
|
15
|
+
*
|
|
16
|
+
* A root is a call of a fresh function (or a leak-free construction) whose
|
|
17
|
+
* value, and every reference read out of it, the caller keeps in its frame:
|
|
18
|
+
* deep parameter summaries, where reading a reference out of a parameter
|
|
19
|
+
* makes a value the callee must keep too. Everything is solved
|
|
20
|
+
* optimistically over the call graph and refined to a fixpoint. */
|
|
21
|
+
import { isRefCounted, } from "../../ir/ir.js";
|
|
22
|
+
import { everyExprChild, everyStmtChild } from "../../ir/traverse.js";
|
|
23
|
+
import { ALLOCATIONS, FRESH_ARRAY_METHODS, argsOf, children, forEachNode, indexOfNode, isExpr, keepsInFrame, same, refType, transparent, } from "./region-ir.js";
|
|
24
|
+
import { VirtualTargets } from "./reference-effects.js";
|
|
25
|
+
/** The module functions a virtual call can run, or null when unknown (or
|
|
26
|
+
* when `node` is no virtual call). */
|
|
27
|
+
function virtualTargetsOf(vt, node) {
|
|
28
|
+
return node.kind === "virtualCall" ? vt.targets(node.className, node.method) : null;
|
|
29
|
+
}
|
|
30
|
+
/** Projections whose result is a reference read out of the operand.
|
|
31
|
+
* Strings are leaves, not group members: reading one out of a member and
|
|
32
|
+
* keeping it anywhere keeps no member. */
|
|
33
|
+
function projection(child, parent) {
|
|
34
|
+
if (parent === undefined || !isExpr(parent) || !refType(parent.type))
|
|
35
|
+
return false;
|
|
36
|
+
switch (parent.kind) {
|
|
37
|
+
case "fieldGet":
|
|
38
|
+
case "recordGet":
|
|
39
|
+
case "recordKeyGet":
|
|
40
|
+
return same(parent.obj, child);
|
|
41
|
+
case "arrayGet":
|
|
42
|
+
return same(parent.arr, child);
|
|
43
|
+
case "unionKeyGet":
|
|
44
|
+
return same(parent.value, child);
|
|
45
|
+
case "mapIntrinsic":
|
|
46
|
+
case "setIntrinsic":
|
|
47
|
+
return (same(parent.receiver, child) &&
|
|
48
|
+
(parent.method === "get" || parent.method === "iterKey" || parent.method === "iterValue"));
|
|
49
|
+
default:
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const LOOP_KINDS = new Set(["while", "doWhile", "for", "forOf"]);
|
|
54
|
+
/** Collection methods that add their arguments to the receiver. */
|
|
55
|
+
const ADDING_METHODS = new Set(["push", "unshift", "set", "add"]);
|
|
56
|
+
export const throws = (e) => e.kind === "libCall" && e.fn === "error.nodeThrow";
|
|
57
|
+
/** Receiver methods that read a collection or remove from it, and so add
|
|
58
|
+
* nothing to its graph. */
|
|
59
|
+
const READ_RECEIVER = new Set([
|
|
60
|
+
"get",
|
|
61
|
+
"has",
|
|
62
|
+
"delete",
|
|
63
|
+
"iterKey",
|
|
64
|
+
"iterValue",
|
|
65
|
+
"size",
|
|
66
|
+
"clear",
|
|
67
|
+
"length",
|
|
68
|
+
"at",
|
|
69
|
+
"includes",
|
|
70
|
+
"indexOf",
|
|
71
|
+
"lastIndexOf",
|
|
72
|
+
"indexEq",
|
|
73
|
+
"getNumber",
|
|
74
|
+
"join",
|
|
75
|
+
"nextPresent",
|
|
76
|
+
"slice",
|
|
77
|
+
"concatSpread",
|
|
78
|
+
"pop",
|
|
79
|
+
"shift",
|
|
80
|
+
]);
|
|
81
|
+
/** The local a reference is read out of, through casts, checked reads and
|
|
82
|
+
* projections (`l.items[0]` → l), or the local itself. */
|
|
83
|
+
function projectionBase(e, through) {
|
|
84
|
+
let at = e;
|
|
85
|
+
for (let i = 0; i < 64; i++) {
|
|
86
|
+
if (at.kind === "varRef")
|
|
87
|
+
return at.localId;
|
|
88
|
+
if (at.kind === "call" && through !== undefined) {
|
|
89
|
+
const next = through(at);
|
|
90
|
+
if (next === null)
|
|
91
|
+
return null;
|
|
92
|
+
at = next;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (at.kind === "fieldGet" || at.kind === "recordGet" || at.kind === "recordKeyGet")
|
|
96
|
+
at = at.obj;
|
|
97
|
+
else if (at.kind === "arrayGet")
|
|
98
|
+
at = at.arr;
|
|
99
|
+
else if (at.kind === "unionKeyGet")
|
|
100
|
+
at = at.value;
|
|
101
|
+
else if ((at.kind === "mapIntrinsic" || at.kind === "setIntrinsic") &&
|
|
102
|
+
(at.method === "get" || at.method === "iterKey" || at.method === "iterValue"))
|
|
103
|
+
at = at.receiver;
|
|
104
|
+
else if (at.kind === "unionNarrow" ||
|
|
105
|
+
at.kind === "upcast" ||
|
|
106
|
+
at.kind === "downcast" ||
|
|
107
|
+
at.kind === "unionWrap" ||
|
|
108
|
+
at.kind === "unionRetype")
|
|
109
|
+
at = at.value;
|
|
110
|
+
else if (at.kind === "ternary" && throws(at.then))
|
|
111
|
+
at = at.else_;
|
|
112
|
+
else if (at.kind === "ternary" && throws(at.else_))
|
|
113
|
+
at = at.then;
|
|
114
|
+
else
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
/** The local whose graph a store into `target` writes (`l.f.items` → l). */
|
|
120
|
+
export function storeTarget(target) {
|
|
121
|
+
let at = target;
|
|
122
|
+
for (let i = 0; at !== undefined && i < 64; i++) {
|
|
123
|
+
if (at.kind === "varRef")
|
|
124
|
+
return at.localId;
|
|
125
|
+
if (at.kind === "fieldGet" || at.kind === "recordGet" || at.kind === "recordKeyGet")
|
|
126
|
+
at = at.obj;
|
|
127
|
+
else if (at.kind === "arrayGet")
|
|
128
|
+
at = at.arr;
|
|
129
|
+
else if (at.kind === "unionNarrow" || at.kind === "upcast" || at.kind === "downcast")
|
|
130
|
+
at = at.value;
|
|
131
|
+
// A checked read (`entry.skus` on `entry | undefined`) throws on one side.
|
|
132
|
+
else if (at.kind === "ternary" && throws(at.then))
|
|
133
|
+
at = at.else_;
|
|
134
|
+
else if (at.kind === "ternary" && throws(at.else_))
|
|
135
|
+
at = at.then;
|
|
136
|
+
else
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
/** An expression that produces a value it allocates (a group member). */
|
|
142
|
+
export function source(e) {
|
|
143
|
+
if (!isExpr(e))
|
|
144
|
+
return false;
|
|
145
|
+
if (ALLOCATIONS.has(e.kind))
|
|
146
|
+
return true;
|
|
147
|
+
if (e.kind === "arrIntrinsic")
|
|
148
|
+
return FRESH_ARRAY_METHODS.has(e.method);
|
|
149
|
+
if (e.kind === "strIntrinsic")
|
|
150
|
+
return e.method === "split";
|
|
151
|
+
if (e.kind === "libCall")
|
|
152
|
+
return e.fn === "json.parse";
|
|
153
|
+
if (e.kind === "dynCheck")
|
|
154
|
+
return e.value.kind === "libCall" && e.value.fn === "json.parse";
|
|
155
|
+
if (e.kind === "call" || e.kind === "callValue")
|
|
156
|
+
return refType(e.type);
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
/** Store-like uses: the value goes into the graph of `target`'s value. */
|
|
160
|
+
export function storeOf(value, parent) {
|
|
161
|
+
switch (parent.kind) {
|
|
162
|
+
case "fieldSet":
|
|
163
|
+
case "recordSet":
|
|
164
|
+
case "recordKeySet":
|
|
165
|
+
return same(parent.value, value) ? parent.obj : undefined;
|
|
166
|
+
case "arraySet":
|
|
167
|
+
return same(parent.value, value) ? parent.arr : undefined;
|
|
168
|
+
case "arrIntrinsic":
|
|
169
|
+
return (parent.method === "push" || parent.method === "unshift") &&
|
|
170
|
+
indexOfNode(parent.args, value) >= 0
|
|
171
|
+
? parent.receiver
|
|
172
|
+
: undefined;
|
|
173
|
+
case "mapIntrinsic":
|
|
174
|
+
return parent.method === "set" && indexOfNode(parent.args, value) >= 0
|
|
175
|
+
? parent.receiver
|
|
176
|
+
: undefined;
|
|
177
|
+
case "setIntrinsic":
|
|
178
|
+
return parent.method === "add" && indexOfNode(parent.args, value) >= 0
|
|
179
|
+
? parent.receiver
|
|
180
|
+
: undefined;
|
|
181
|
+
default:
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/** Content positions: the value becomes part of the new value `parent`. */
|
|
186
|
+
export function contentOf(value, parent) {
|
|
187
|
+
switch (parent.kind) {
|
|
188
|
+
case "arrayLit":
|
|
189
|
+
case "recordLit":
|
|
190
|
+
case "new":
|
|
191
|
+
case "mapNew":
|
|
192
|
+
case "setNew":
|
|
193
|
+
return !same(parent, value);
|
|
194
|
+
case "recordClone":
|
|
195
|
+
return !same(parent.source, value);
|
|
196
|
+
default:
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/** Whether `parent` is a fresh array holding the elements of `child`, an
|
|
201
|
+
* array of references (`xs.slice()`, `a.concat(b)`): the elements share the
|
|
202
|
+
* fate of the copy. Strings are leaves, not members. */
|
|
203
|
+
function copiesElements(child, parent) {
|
|
204
|
+
if (parent === undefined || parent.kind !== "arrIntrinsic" || !isExpr(child))
|
|
205
|
+
return false;
|
|
206
|
+
if (!FRESH_ARRAY_METHODS.has(parent.method) && !SPREAD_METHODS.has(parent.method))
|
|
207
|
+
return false;
|
|
208
|
+
if (!same(parent.receiver, child) &&
|
|
209
|
+
!(parent.method === "concatSpread" && indexOfNode(parent.args, child) >= 0))
|
|
210
|
+
return false;
|
|
211
|
+
const t = child.type;
|
|
212
|
+
return t.kind === "array" && refType(t.elem);
|
|
213
|
+
}
|
|
214
|
+
/** Array intrinsics that copy their array arguments' elements. */
|
|
215
|
+
const SPREAD_METHODS = new Set(["pushSpread", "unshiftSpread", "concatSpread"]);
|
|
216
|
+
/** Array intrinsics that call their function-typed arguments natively. */
|
|
217
|
+
const CALLBACK_INTRINSICS = new Set(["sortDense", "sortValues"]);
|
|
218
|
+
const callbackArg = (child, parent) => parent !== undefined &&
|
|
219
|
+
parent.kind === "arrIntrinsic" &&
|
|
220
|
+
CALLBACK_INTRINSICS.has(parent.method) &&
|
|
221
|
+
indexOfNode(parent.args, child) >= 0 &&
|
|
222
|
+
isExpr(child) &&
|
|
223
|
+
child.type.kind === "func";
|
|
224
|
+
export function analyzeRegionGroups(mod) {
|
|
225
|
+
const fns = new Map();
|
|
226
|
+
for (const fn of mod.functions)
|
|
227
|
+
fns.set(fn.name, fn);
|
|
228
|
+
const vt = new VirtualTargets(mod.classes ?? []);
|
|
229
|
+
const suspends = (fn) => fn.async === true || fn.generator !== undefined;
|
|
230
|
+
// Who refers to each function: by calls (direct, virtual, constructions),
|
|
231
|
+
// and by closures too. A function's summaries depend only on those of
|
|
232
|
+
// the functions it refers to, so the fixpoints below revisit just the
|
|
233
|
+
// referrers of a function whose summary changed.
|
|
234
|
+
const callers = new Map();
|
|
235
|
+
const referrers = new Map();
|
|
236
|
+
const directAlloc = new Set();
|
|
237
|
+
for (const fn of mod.functions) {
|
|
238
|
+
const note = (map, name) => {
|
|
239
|
+
let set = map.get(name);
|
|
240
|
+
if (set === undefined)
|
|
241
|
+
map.set(name, (set = new Set()));
|
|
242
|
+
set.add(fn.name);
|
|
243
|
+
};
|
|
244
|
+
forEachNode(fn.body, (node) => {
|
|
245
|
+
if (node.kind === "call") {
|
|
246
|
+
note(callers, node.callee);
|
|
247
|
+
note(referrers, node.callee);
|
|
248
|
+
}
|
|
249
|
+
else if (node.kind === "virtualCall")
|
|
250
|
+
for (const t of virtualTargetsOf(vt, node) ?? []) {
|
|
251
|
+
note(callers, t);
|
|
252
|
+
note(referrers, t);
|
|
253
|
+
}
|
|
254
|
+
else if (node.kind === "new") {
|
|
255
|
+
const ctor = `%${node.className}.constructor`;
|
|
256
|
+
note(callers, ctor);
|
|
257
|
+
note(referrers, ctor);
|
|
258
|
+
}
|
|
259
|
+
else if (node.kind === "closure")
|
|
260
|
+
note(referrers, node.fnName);
|
|
261
|
+
if (source(node) && node.kind !== "call")
|
|
262
|
+
directAlloc.add(fn.name);
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
/** Runs `step` on the functions named, and again on the referrers of each
|
|
266
|
+
* whose summary it reports changed, until nothing changes. */
|
|
267
|
+
const solve = (names, by, step) => {
|
|
268
|
+
const queue = [...names];
|
|
269
|
+
const queued = new Set(queue);
|
|
270
|
+
while (queue.length > 0) {
|
|
271
|
+
const name = queue.pop();
|
|
272
|
+
queued.delete(name);
|
|
273
|
+
const fn = fns.get(name);
|
|
274
|
+
if (fn === undefined || !step(fn))
|
|
275
|
+
continue;
|
|
276
|
+
for (const r of by.get(name) ?? new Set())
|
|
277
|
+
if (!queued.has(r)) {
|
|
278
|
+
queued.add(r);
|
|
279
|
+
queue.push(r);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
// Deep summaries.
|
|
284
|
+
const deep = new Map();
|
|
285
|
+
// Internal parameters: ones a leak-free function only borrows, returns, or
|
|
286
|
+
// stores into the graphs of values it allocates (so an argument a caller
|
|
287
|
+
// allocated stays inside the caller's group). Optimistic, refined below.
|
|
288
|
+
const internal = new Map();
|
|
289
|
+
// Callback parameters (see below), and the function being analyzed.
|
|
290
|
+
const callbacks = new Map();
|
|
291
|
+
let current = null;
|
|
292
|
+
// While finding roots: a value passed to the function's own callback
|
|
293
|
+
// parameter leaves the frame (its callers' callbacks are unknown here).
|
|
294
|
+
let framePass = false;
|
|
295
|
+
const keeps = (child, parent) => {
|
|
296
|
+
if (parent?.kind === "virtualCall") {
|
|
297
|
+
const index = indexOfNode(parent.args, child);
|
|
298
|
+
const targets = virtualTargetsOf(vt, parent);
|
|
299
|
+
return (index >= 0 &&
|
|
300
|
+
targets !== null &&
|
|
301
|
+
targets.length > 0 &&
|
|
302
|
+
targets.every((t) => deep.get(t)?.has(index) === true));
|
|
303
|
+
}
|
|
304
|
+
// A spread copies the array's elements into another array: they
|
|
305
|
+
// escape with it.
|
|
306
|
+
if (parent?.kind === "arrIntrinsic" &&
|
|
307
|
+
SPREAD_METHODS.has(parent.method) &&
|
|
308
|
+
!same(parent.receiver, child) &&
|
|
309
|
+
isExpr(child)) {
|
|
310
|
+
const t = child.type;
|
|
311
|
+
return t.kind !== "array" || !refType(t.elem);
|
|
312
|
+
}
|
|
313
|
+
if (callbackArg(child, parent))
|
|
314
|
+
return true;
|
|
315
|
+
if (parent?.kind === "jsonStringify")
|
|
316
|
+
return true;
|
|
317
|
+
// Comparisons only read their operands.
|
|
318
|
+
if (parent?.kind === "strCmp" || parent?.kind === "strEq")
|
|
319
|
+
return true;
|
|
320
|
+
if (parent?.kind === "bin" && !refType(parent.type))
|
|
321
|
+
return true;
|
|
322
|
+
return keepsInFrame(child, parent, deep);
|
|
323
|
+
};
|
|
324
|
+
/** How the value of `node` (`parents` its ancestors) is used, after the
|
|
325
|
+
* expressions that pass it on (and, with `projections`, the reads of a
|
|
326
|
+
* reference out of it). */
|
|
327
|
+
const useOf = (node, parents, projections, out) => {
|
|
328
|
+
let value = node;
|
|
329
|
+
let at = parents.length - 1;
|
|
330
|
+
while (at >= 0 &&
|
|
331
|
+
(transparent(value, parents[at]) ||
|
|
332
|
+
copiesElements(value, parents[at]) ||
|
|
333
|
+
(projections && projection(value, parents[at]))))
|
|
334
|
+
value = parents[at--];
|
|
335
|
+
const p = at >= 0 ? parents[at] : undefined;
|
|
336
|
+
if (p === undefined)
|
|
337
|
+
return "escapes";
|
|
338
|
+
if ((p.kind === "varDecl" && p.init !== null && same(p.init, value)) ||
|
|
339
|
+
(p.kind === "assign" && same(p.value, value))) {
|
|
340
|
+
out.bound = p.localId;
|
|
341
|
+
return "bound";
|
|
342
|
+
}
|
|
343
|
+
if (p.kind === "return")
|
|
344
|
+
return "returned";
|
|
345
|
+
if (p.kind === "throw")
|
|
346
|
+
return "thrown";
|
|
347
|
+
if (p.kind === "exprStmt")
|
|
348
|
+
return "kept";
|
|
349
|
+
const target = storeOf(value, p);
|
|
350
|
+
if (target !== undefined) {
|
|
351
|
+
out.target = storeTarget(target);
|
|
352
|
+
return "stored";
|
|
353
|
+
}
|
|
354
|
+
if (contentOf(value, p))
|
|
355
|
+
return "content";
|
|
356
|
+
if (keeps(value, p))
|
|
357
|
+
return "kept";
|
|
358
|
+
if (p.kind === "callValue" && current !== null && !framePass) {
|
|
359
|
+
const i = indexOfNode(p.args, value) >= 0 ? paramIndex(current, p.callee) : -1;
|
|
360
|
+
if (i >= 0 && callbacks.get(current.name).has(i))
|
|
361
|
+
return "kept";
|
|
362
|
+
}
|
|
363
|
+
if (p.kind === "call") {
|
|
364
|
+
const c = p;
|
|
365
|
+
const i = indexOfNode(c.args, value);
|
|
366
|
+
// The callee may hand the value to the callbacks it is passed, which
|
|
367
|
+
// must keep it too.
|
|
368
|
+
if (i >= 0 &&
|
|
369
|
+
internal.get(c.callee)?.has(i) === true &&
|
|
370
|
+
[...(callbacks.get(c.callee) ?? new Set())].every((j) => callbackClean(c.args[j]))) {
|
|
371
|
+
out.at = at;
|
|
372
|
+
return "internal";
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return "escapes";
|
|
376
|
+
};
|
|
377
|
+
/** How the result of the call at `parents[at]` is used, through calls
|
|
378
|
+
* that keep it in their own results (`report(select(load()))`). */
|
|
379
|
+
const resultUse = (at, parents, out) => {
|
|
380
|
+
let index = at;
|
|
381
|
+
for (let i = 0; i < 64; i++) {
|
|
382
|
+
const info = {};
|
|
383
|
+
const use = useOf(parents[index], parents.slice(0, index), false, info);
|
|
384
|
+
if (use !== "internal") {
|
|
385
|
+
// Field by field: an Object.assign onto a record makes the
|
|
386
|
+
// self-hosted compiler read class and record properties dynamically.
|
|
387
|
+
if (info.bound !== undefined)
|
|
388
|
+
out.bound = info.bound;
|
|
389
|
+
if (info.at !== undefined)
|
|
390
|
+
out.at = info.at;
|
|
391
|
+
if (info.target !== undefined)
|
|
392
|
+
out.target = info.target;
|
|
393
|
+
return use;
|
|
394
|
+
}
|
|
395
|
+
index = info.at;
|
|
396
|
+
}
|
|
397
|
+
return "escapes";
|
|
398
|
+
};
|
|
399
|
+
const flats = new Map();
|
|
400
|
+
const flatOf = (fn) => {
|
|
401
|
+
let flat = flats.get(fn.name);
|
|
402
|
+
if (flat !== undefined)
|
|
403
|
+
return flat;
|
|
404
|
+
flat = { nodes: [], parent: [], refs: [], sources: [] };
|
|
405
|
+
const f = flat;
|
|
406
|
+
// Parents come before their children, so each node's parent is indexed.
|
|
407
|
+
const index = new Map();
|
|
408
|
+
forEachNode(fn.body, (node, parent) => {
|
|
409
|
+
const i = f.nodes.length;
|
|
410
|
+
index.set(node, i);
|
|
411
|
+
f.nodes.push(node);
|
|
412
|
+
f.parent.push(parent === undefined ? -1 : index.get(parent));
|
|
413
|
+
if (source(node))
|
|
414
|
+
f.sources.push(i);
|
|
415
|
+
if (node.kind === "varRef" && (refType(node.type) || node.type.kind === "string"))
|
|
416
|
+
f.refs.push(i);
|
|
417
|
+
});
|
|
418
|
+
flats.set(fn.name, flat);
|
|
419
|
+
return flat;
|
|
420
|
+
};
|
|
421
|
+
/** The ancestors of node `i` of `flat`, outermost first, into `out`. */
|
|
422
|
+
const ancestors = (flat, i, out) => {
|
|
423
|
+
out.length = 0;
|
|
424
|
+
for (let p = flat.parent[i]; p >= 0; p = flat.parent[p])
|
|
425
|
+
out.push(flat.nodes[p]);
|
|
426
|
+
out.reverse();
|
|
427
|
+
return out;
|
|
428
|
+
};
|
|
429
|
+
/** Locals of `fn` whose value (or a reference read out of it) escapes.
|
|
430
|
+
* With `members` (the locals bound to group members), a value may also be
|
|
431
|
+
* returned, be content of a new value, or be stored into a member's
|
|
432
|
+
* graph. */
|
|
433
|
+
const escapingLocals = (fn, members, classes) => {
|
|
434
|
+
const out = new Set();
|
|
435
|
+
const add = (id) => {
|
|
436
|
+
out.add(id);
|
|
437
|
+
};
|
|
438
|
+
const own = new Set(fn.locals.map((l) => l.id));
|
|
439
|
+
const group = new Map();
|
|
440
|
+
const find = (id) => {
|
|
441
|
+
let r = id;
|
|
442
|
+
while (group.has(r) && group.get(r) !== r)
|
|
443
|
+
r = group.get(r);
|
|
444
|
+
return r;
|
|
445
|
+
};
|
|
446
|
+
const unite = (a, b) => {
|
|
447
|
+
const ra = find(a), rb = find(b);
|
|
448
|
+
if (ra !== rb)
|
|
449
|
+
group.set(ra, rb);
|
|
450
|
+
};
|
|
451
|
+
// Copies: locals bound to a local or to a fresh copy of one (`slice`).
|
|
452
|
+
// A store of a value read out of a copy into the graph of another copy
|
|
453
|
+
// adds no reference into the group, unless a member went into a copy.
|
|
454
|
+
const copy = new Map();
|
|
455
|
+
const findCopy = (id) => {
|
|
456
|
+
let r = id;
|
|
457
|
+
while (copy.has(r) && copy.get(r) !== r)
|
|
458
|
+
r = copy.get(r);
|
|
459
|
+
return r;
|
|
460
|
+
};
|
|
461
|
+
const uniteCopy = (a, b) => {
|
|
462
|
+
const ra = findCopy(a), rb = findCopy(b);
|
|
463
|
+
if (ra !== rb)
|
|
464
|
+
copy.set(ra, rb);
|
|
465
|
+
};
|
|
466
|
+
const filled = new Set();
|
|
467
|
+
const selfStores = [];
|
|
468
|
+
const flat = flatOf(fn);
|
|
469
|
+
const parents = [];
|
|
470
|
+
if (members !== null)
|
|
471
|
+
for (const i of flat.sources) {
|
|
472
|
+
const node = flat.nodes[i];
|
|
473
|
+
ancestors(flat, i, parents);
|
|
474
|
+
// A copy class holds something new once a value it did not have
|
|
475
|
+
// goes into it: stored into its graph, or bound to one of its locals
|
|
476
|
+
// (`visited = new Map(); this.visited = visited`). A `slice` of a
|
|
477
|
+
// local in the class holds only what the class held.
|
|
478
|
+
const info = {};
|
|
479
|
+
const use = useOf(node, parents, false, info);
|
|
480
|
+
if (use === "stored" && info.target)
|
|
481
|
+
filled.add(info.target);
|
|
482
|
+
if (use === "bound" && !(node.kind === "arrIntrinsic" && node.method === "slice"))
|
|
483
|
+
filled.add(info.bound);
|
|
484
|
+
}
|
|
485
|
+
// Uses of locals that can hold references (a value without references
|
|
486
|
+
// cannot keep a member).
|
|
487
|
+
for (const i of flat.refs) {
|
|
488
|
+
const node = flat.nodes[i];
|
|
489
|
+
if (node.kind !== "varRef")
|
|
490
|
+
continue;
|
|
491
|
+
ancestors(flat, i, parents);
|
|
492
|
+
const id = node.localId;
|
|
493
|
+
const info = {};
|
|
494
|
+
const use = useOf(node, parents, true, info);
|
|
495
|
+
if (use === "bound") {
|
|
496
|
+
if (own.has(info.bound)) {
|
|
497
|
+
unite(id, info.bound);
|
|
498
|
+
uniteCopy(id, info.bound);
|
|
499
|
+
}
|
|
500
|
+
else
|
|
501
|
+
add(id);
|
|
502
|
+
}
|
|
503
|
+
else if (use === "internal" && members === null) {
|
|
504
|
+
// The callee keeps the value only in its result: the value stays
|
|
505
|
+
// in this frame while the result does (a module global needs no
|
|
506
|
+
// frame to hold it).
|
|
507
|
+
const result = {};
|
|
508
|
+
const r = resultUse(info.at, parents, result);
|
|
509
|
+
if (r === "bound" && own.has(result.bound)) {
|
|
510
|
+
if (own.has(id))
|
|
511
|
+
unite(id, result.bound);
|
|
512
|
+
}
|
|
513
|
+
else if (r !== "kept")
|
|
514
|
+
add(id);
|
|
515
|
+
}
|
|
516
|
+
else if (use === "thrown") {
|
|
517
|
+
// A thrown value leaves the frame and outlives the group.
|
|
518
|
+
add(id);
|
|
519
|
+
}
|
|
520
|
+
else if (use === "returned" || use === "content" || use === "internal") {
|
|
521
|
+
if (members === null)
|
|
522
|
+
add(id);
|
|
523
|
+
}
|
|
524
|
+
else if (use === "stored") {
|
|
525
|
+
if (members?.has(id) && info.target)
|
|
526
|
+
filled.add(info.target);
|
|
527
|
+
if (members !== null &&
|
|
528
|
+
info.target !== null &&
|
|
529
|
+
info.target !== undefined &&
|
|
530
|
+
!members.has(info.target) &&
|
|
531
|
+
own.has(info.target))
|
|
532
|
+
selfStores.push([id, info.target]);
|
|
533
|
+
else if (members === null ||
|
|
534
|
+
info.target === null ||
|
|
535
|
+
info.target === undefined ||
|
|
536
|
+
!members.has(info.target))
|
|
537
|
+
add(id);
|
|
538
|
+
}
|
|
539
|
+
else if (use === "escapes")
|
|
540
|
+
add(id);
|
|
541
|
+
// `const copy = id.slice()`.
|
|
542
|
+
// An optional chain on a Node, or a field read in the same condition
|
|
543
|
+
// as its kind test, tests every Node kind in turn: the kind is read
|
|
544
|
+
// after an undefined check, and the fields in a statement of their own.
|
|
545
|
+
const p = parents[parents.length - 1];
|
|
546
|
+
if (members !== null && p !== undefined && p.kind === "arrIntrinsic") {
|
|
547
|
+
if (same(p.receiver, node) && p.method === "slice") {
|
|
548
|
+
const copied = {};
|
|
549
|
+
if (useOf(p, parents.slice(0, -1), false, copied) === "bound" && own.has(copied.bound))
|
|
550
|
+
uniteCopy(id, copied.bound);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
const filledCopies = new Set([...filled].map(findCopy));
|
|
555
|
+
for (const [id, target] of selfStores)
|
|
556
|
+
if (findCopy(id) !== findCopy(target) || filledCopies.has(findCopy(id)))
|
|
557
|
+
add(id);
|
|
558
|
+
for (const local of fn.locals)
|
|
559
|
+
if (local.boxed === true)
|
|
560
|
+
out.add(local.id);
|
|
561
|
+
const roots = new Set();
|
|
562
|
+
for (const id of out)
|
|
563
|
+
roots.add(find(id));
|
|
564
|
+
for (const local of fn.locals)
|
|
565
|
+
if (roots.has(find(local.id)))
|
|
566
|
+
out.add(local.id);
|
|
567
|
+
if (classes !== undefined)
|
|
568
|
+
for (const local of fn.locals)
|
|
569
|
+
classes.set(local.id, find(local.id));
|
|
570
|
+
return out;
|
|
571
|
+
};
|
|
572
|
+
const solveDeep = () => {
|
|
573
|
+
for (const fn of mod.functions) {
|
|
574
|
+
const safe = new Set();
|
|
575
|
+
if (!suspends(fn))
|
|
576
|
+
fn.params.forEach((param, i) => {
|
|
577
|
+
const local = fn.locals.find((l) => l.id === param.localId);
|
|
578
|
+
if ((refType(param.type) || param.type.kind === "string") && local?.boxed !== true)
|
|
579
|
+
safe.add(i);
|
|
580
|
+
});
|
|
581
|
+
deep.set(fn.name, safe);
|
|
582
|
+
}
|
|
583
|
+
solve(fns.keys(), referrers, (fn) => {
|
|
584
|
+
const safe = deep.get(fn.name);
|
|
585
|
+
if (safe.size === 0)
|
|
586
|
+
return false;
|
|
587
|
+
const esc = escapingLocals(fn, null);
|
|
588
|
+
let changed = false;
|
|
589
|
+
fn.params.forEach((param, i) => {
|
|
590
|
+
if (safe.has(i) && esc.has(param.localId)) {
|
|
591
|
+
safe.delete(i);
|
|
592
|
+
changed = true;
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
return changed;
|
|
596
|
+
});
|
|
597
|
+
};
|
|
598
|
+
solveDeep();
|
|
599
|
+
// Leak-free and fresh functions, optimistic.
|
|
600
|
+
const leakFree = new Set();
|
|
601
|
+
const fresh = new Set();
|
|
602
|
+
for (const fn of mod.functions) {
|
|
603
|
+
if (suspends(fn))
|
|
604
|
+
continue;
|
|
605
|
+
leakFree.add(fn.name);
|
|
606
|
+
if (refType(fn.returnType))
|
|
607
|
+
fresh.add(fn.name);
|
|
608
|
+
const inner = new Set();
|
|
609
|
+
fn.params.forEach((param, i) => {
|
|
610
|
+
const local = fn.locals.find((l) => l.id === param.localId);
|
|
611
|
+
if ((refType(param.type) || param.type.kind === "string") && local?.boxed !== true)
|
|
612
|
+
inner.add(i);
|
|
613
|
+
});
|
|
614
|
+
internal.set(fn.name, inner);
|
|
615
|
+
}
|
|
616
|
+
let internalChanged = false;
|
|
617
|
+
const unwrap = (e) => {
|
|
618
|
+
let at = e;
|
|
619
|
+
for (let i = 0; i < 16; i++) {
|
|
620
|
+
if (at.kind === "unionWrap" ||
|
|
621
|
+
at.kind === "upcast" ||
|
|
622
|
+
at.kind === "downcast" ||
|
|
623
|
+
at.kind === "unionRetype")
|
|
624
|
+
at = at.value;
|
|
625
|
+
else
|
|
626
|
+
break;
|
|
627
|
+
}
|
|
628
|
+
return at;
|
|
629
|
+
};
|
|
630
|
+
// Callback parameters: parameters a function calls (or passes on to a
|
|
631
|
+
// callback parameter). Each argument for one must be a leak-free closure,
|
|
632
|
+
// or a callback parameter of the caller.
|
|
633
|
+
const reassignedMemo = new Map();
|
|
634
|
+
const reassignedIn = (fn) => {
|
|
635
|
+
let out = reassignedMemo.get(fn.name);
|
|
636
|
+
if (out !== undefined)
|
|
637
|
+
return out;
|
|
638
|
+
out = new Set();
|
|
639
|
+
for (const node of flatOf(fn).nodes)
|
|
640
|
+
if (node.kind === "assign")
|
|
641
|
+
out.add(node.localId);
|
|
642
|
+
for (const l of fn.locals)
|
|
643
|
+
if (l.boxed === true)
|
|
644
|
+
out.add(l.id);
|
|
645
|
+
reassignedMemo.set(fn.name, out);
|
|
646
|
+
return out;
|
|
647
|
+
};
|
|
648
|
+
const paramIndex = (fn, e) => {
|
|
649
|
+
const u = unwrap(e);
|
|
650
|
+
if (u.kind !== "varRef")
|
|
651
|
+
return -1;
|
|
652
|
+
const id = u.localId;
|
|
653
|
+
if (reassignedIn(fn).has(id))
|
|
654
|
+
return -1;
|
|
655
|
+
return fn.params.findIndex((p) => p.localId === id);
|
|
656
|
+
};
|
|
657
|
+
for (const fn of mod.functions)
|
|
658
|
+
callbacks.set(fn.name, new Set());
|
|
659
|
+
solve(fns.keys(), callers, (fn) => {
|
|
660
|
+
const set = callbacks.get(fn.name);
|
|
661
|
+
const before = set.size;
|
|
662
|
+
for (const node of flatOf(fn).nodes) {
|
|
663
|
+
if (node.kind === "callValue") {
|
|
664
|
+
const i = paramIndex(fn, node.callee);
|
|
665
|
+
if (i >= 0)
|
|
666
|
+
set.add(i);
|
|
667
|
+
}
|
|
668
|
+
else if (node.kind === "arrIntrinsic" && CALLBACK_INTRINSICS.has(node.method)) {
|
|
669
|
+
for (const a of node.args)
|
|
670
|
+
if (a.type.kind === "func") {
|
|
671
|
+
const i = paramIndex(fn, a);
|
|
672
|
+
if (i >= 0)
|
|
673
|
+
set.add(i);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
else if (node.kind === "call") {
|
|
677
|
+
for (const j of callbacks.get(node.callee) ?? new Set()) {
|
|
678
|
+
const arg = node.args[j];
|
|
679
|
+
const i = arg === undefined ? -1 : paramIndex(fn, arg);
|
|
680
|
+
if (i >= 0)
|
|
681
|
+
set.add(i);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
return set.size !== before;
|
|
686
|
+
});
|
|
687
|
+
const callbackClean = (arg) => {
|
|
688
|
+
if (arg === undefined)
|
|
689
|
+
return true;
|
|
690
|
+
const u = unwrap(arg);
|
|
691
|
+
if (u.kind === "closure") {
|
|
692
|
+
// The callee passes the callback values it borrows (or that came from
|
|
693
|
+
// its caller): its parameters must stay internal.
|
|
694
|
+
const name = u.fnName;
|
|
695
|
+
const target = fns.get(name);
|
|
696
|
+
if (target === undefined || !leakFree.has(name))
|
|
697
|
+
return false;
|
|
698
|
+
const inner = internal.get(name);
|
|
699
|
+
return target.params.every((p, i) => !refType(p.type) || inner.has(i));
|
|
700
|
+
}
|
|
701
|
+
if (current === null || framePass)
|
|
702
|
+
return false;
|
|
703
|
+
const i = paramIndex(current, u);
|
|
704
|
+
return i >= 0 && callbacks.get(current.name).has(i);
|
|
705
|
+
};
|
|
706
|
+
const calleesClean = (node) => {
|
|
707
|
+
if (node.kind === "call") {
|
|
708
|
+
if (!leakFree.has(node.callee))
|
|
709
|
+
return false;
|
|
710
|
+
for (const j of callbacks.get(node.callee) ?? new Set())
|
|
711
|
+
if (!callbackClean(node.args[j]))
|
|
712
|
+
return false;
|
|
713
|
+
return true;
|
|
714
|
+
}
|
|
715
|
+
if (node.kind === "callValue" && current !== null) {
|
|
716
|
+
const i = paramIndex(current, node.callee);
|
|
717
|
+
return i >= 0 && callbacks.get(current.name).has(i);
|
|
718
|
+
}
|
|
719
|
+
if (node.kind === "arrIntrinsic" && CALLBACK_INTRINSICS.has(node.method))
|
|
720
|
+
return node.args.every((a) => a.type.kind !== "func" || callbackClean(a));
|
|
721
|
+
if (node.kind === "virtualCall") {
|
|
722
|
+
const t = virtualTargetsOf(vt, node);
|
|
723
|
+
return t !== null && t.length > 0 && t.every((x) => leakFree.has(x));
|
|
724
|
+
}
|
|
725
|
+
if (node.kind === "callValue" ||
|
|
726
|
+
node.kind === "newValue" ||
|
|
727
|
+
node.kind === "dynCall" ||
|
|
728
|
+
node.kind === "dynInvoke")
|
|
729
|
+
return false;
|
|
730
|
+
if (node.kind === "new")
|
|
731
|
+
return leakFree.has(`%${node.className}.constructor`);
|
|
732
|
+
return true;
|
|
733
|
+
};
|
|
734
|
+
/** The values `e` can produce, through casts and conditionals. */
|
|
735
|
+
const leaves = (e, out = []) => {
|
|
736
|
+
const u = unwrap(e);
|
|
737
|
+
if (u.kind === "ternary") {
|
|
738
|
+
// A side that throws produces no value.
|
|
739
|
+
if (!throws(u.then))
|
|
740
|
+
leaves(u.then, out);
|
|
741
|
+
if (!throws(u.else_))
|
|
742
|
+
leaves(u.else_, out);
|
|
743
|
+
}
|
|
744
|
+
else
|
|
745
|
+
out.push(u);
|
|
746
|
+
return out;
|
|
747
|
+
};
|
|
748
|
+
/** A source whose value is a new group member (a call result only when
|
|
749
|
+
* the callee is fresh). */
|
|
750
|
+
const memberSource = (u) => source(u) && u.kind !== "callValue" && (u.kind !== "call" || fresh.has(u.callee));
|
|
751
|
+
/** What analyze reads of `fn` that no summary changes: the values bound
|
|
752
|
+
* to each local, the stores into locals' graphs, and the locals that are
|
|
753
|
+
* not closed (see analyze). */
|
|
754
|
+
const bodyFacts = new Map();
|
|
755
|
+
const factsOf = (fn) => {
|
|
756
|
+
const memo = bodyFacts.get(fn.name);
|
|
757
|
+
if (memo !== undefined)
|
|
758
|
+
return memo;
|
|
759
|
+
const bindings = new Map();
|
|
760
|
+
const scan = (node) => {
|
|
761
|
+
if (node.kind === "varDecl" || node.kind === "assign") {
|
|
762
|
+
const v = node.kind === "varDecl" ? node.init : node.value;
|
|
763
|
+
if (v !== null)
|
|
764
|
+
bindings.set(node.localId, [...(bindings.get(node.localId) ?? []), v]);
|
|
765
|
+
}
|
|
766
|
+
const kids = [];
|
|
767
|
+
children(node, kids);
|
|
768
|
+
for (const k of kids)
|
|
769
|
+
scan(k);
|
|
770
|
+
};
|
|
771
|
+
for (const s of fn.body)
|
|
772
|
+
scan(s);
|
|
773
|
+
const stores = [];
|
|
774
|
+
const open = new Set();
|
|
775
|
+
{
|
|
776
|
+
const parents = [];
|
|
777
|
+
const walk = (node) => {
|
|
778
|
+
const parent = parents[parents.length - 1];
|
|
779
|
+
if (parent !== undefined) {
|
|
780
|
+
const t = storeOf(node, parent);
|
|
781
|
+
if (t !== undefined) {
|
|
782
|
+
const target = storeTarget(t);
|
|
783
|
+
if (target !== null)
|
|
784
|
+
stores.push([target, node]);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
if (node.kind === "varRef") {
|
|
788
|
+
const id = node.localId;
|
|
789
|
+
let value = node;
|
|
790
|
+
let at = parents.length - 1;
|
|
791
|
+
while (at >= 0 && (transparent(value, parents[at]) || projection(value, parents[at])))
|
|
792
|
+
value = parents[at--];
|
|
793
|
+
const p = parents[at];
|
|
794
|
+
if (p !== undefined && isExpr(p)) {
|
|
795
|
+
const x = p;
|
|
796
|
+
if (x.kind === "call" ||
|
|
797
|
+
x.kind === "virtualCall" ||
|
|
798
|
+
x.kind === "callValue" ||
|
|
799
|
+
x.kind === "new" ||
|
|
800
|
+
x.kind === "newValue" ||
|
|
801
|
+
x.kind === "dynCall" ||
|
|
802
|
+
x.kind === "dynInvoke" ||
|
|
803
|
+
x.kind === "libCall")
|
|
804
|
+
open.add(id);
|
|
805
|
+
else if ((x.kind === "arrIntrinsic" ||
|
|
806
|
+
x.kind === "mapIntrinsic" ||
|
|
807
|
+
x.kind === "setIntrinsic") &&
|
|
808
|
+
same(x.receiver, value) &&
|
|
809
|
+
!READ_RECEIVER.has(x.method) &&
|
|
810
|
+
!x.method.startsWith("iter") &&
|
|
811
|
+
storeOf(x.args[0] ?? x, x) === undefined)
|
|
812
|
+
open.add(id);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
const kids = [];
|
|
816
|
+
children(node, kids);
|
|
817
|
+
parents.push(node);
|
|
818
|
+
for (const kid of kids)
|
|
819
|
+
walk(kid);
|
|
820
|
+
parents.pop();
|
|
821
|
+
};
|
|
822
|
+
for (const st of fn.body)
|
|
823
|
+
walk(st);
|
|
824
|
+
}
|
|
825
|
+
const facts = { bindings, stores, open };
|
|
826
|
+
bodyFacts.set(fn.name, facts);
|
|
827
|
+
return facts;
|
|
828
|
+
};
|
|
829
|
+
const analyze = (fn) => {
|
|
830
|
+
current = fn;
|
|
831
|
+
// Member locals: bound only to sources, other members, or non-references.
|
|
832
|
+
const members = new Set(fn.locals.filter((l) => l.boxed !== true).map((l) => l.id));
|
|
833
|
+
for (const p of fn.params)
|
|
834
|
+
members.delete(p.localId);
|
|
835
|
+
// A constructor's `this` is the object its `new` allocated.
|
|
836
|
+
const ctor = fn.name.endsWith(".constructor") && fn.params.length > 0;
|
|
837
|
+
const thisId = ctor ? fn.params[0].localId : null;
|
|
838
|
+
// Closed members: members whose graph holds only members and leaves
|
|
839
|
+
// (values without a graph: numbers, strings). A reference read out of a
|
|
840
|
+
// closed member is a member too. A local is not closed when it is passed
|
|
841
|
+
// to a call (which may store into its graph) or used as the receiver of
|
|
842
|
+
// a method that adds what this analysis does not see.
|
|
843
|
+
const { bindings, stores, open } = factsOf(fn);
|
|
844
|
+
const closed = new Set([...members].filter((id) => !open.has(id) && id !== thisId));
|
|
845
|
+
const leaf = (u) => isExpr(u) && !refType(u.type);
|
|
846
|
+
const closedSource = (u) => {
|
|
847
|
+
if (u.kind === "libCall")
|
|
848
|
+
return u.fn === "json.parse";
|
|
849
|
+
if (u.kind === "dynCheck")
|
|
850
|
+
return closedSource(u.value);
|
|
851
|
+
if (u.kind === "strIntrinsic")
|
|
852
|
+
return u.method === "split";
|
|
853
|
+
if (u.kind !== "arrayLit" &&
|
|
854
|
+
u.kind !== "recordLit" &&
|
|
855
|
+
u.kind !== "mapNew" &&
|
|
856
|
+
u.kind !== "setNew")
|
|
857
|
+
return false;
|
|
858
|
+
const kids = [];
|
|
859
|
+
children(u, kids);
|
|
860
|
+
return kids.every((k) => !isExpr(k) || closedValue(k));
|
|
861
|
+
};
|
|
862
|
+
const closedValue = (v) => leaves(v).every((u) => {
|
|
863
|
+
if (leaf(u) || closedSource(u))
|
|
864
|
+
return true;
|
|
865
|
+
const base = isExpr(u) ? projectionBase(u) : null;
|
|
866
|
+
return base !== null && closed.has(base);
|
|
867
|
+
});
|
|
868
|
+
for (let again = true; again;) {
|
|
869
|
+
again = false;
|
|
870
|
+
for (const id of [...members]) {
|
|
871
|
+
const list = bindings.get(id) ?? [];
|
|
872
|
+
if (id === thisId)
|
|
873
|
+
continue;
|
|
874
|
+
const ok = list.length > 0 &&
|
|
875
|
+
list.every((v) => leaves(v).every((u) => {
|
|
876
|
+
if (memberSource(u) || leaf(u))
|
|
877
|
+
return true;
|
|
878
|
+
if (u.kind === "varRef")
|
|
879
|
+
return members.has(u.localId);
|
|
880
|
+
const base = isExpr(u) ? projectionBase(u) : null;
|
|
881
|
+
return base !== null && closed.has(base);
|
|
882
|
+
}));
|
|
883
|
+
if (!ok) {
|
|
884
|
+
members.delete(id);
|
|
885
|
+
closed.delete(id);
|
|
886
|
+
again = true;
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
for (const id of [...closed]) {
|
|
890
|
+
const ok = members.has(id) &&
|
|
891
|
+
(bindings.get(id) ?? []).every(closedValue) &&
|
|
892
|
+
stores.every(([target, value]) => target !== id || closedValue(value));
|
|
893
|
+
if (!ok) {
|
|
894
|
+
closed.delete(id);
|
|
895
|
+
again = true;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
// A local bound to a reference read out of another shares its graph.
|
|
899
|
+
for (const [id, list] of bindings)
|
|
900
|
+
if (!closed.has(id))
|
|
901
|
+
for (const v of list)
|
|
902
|
+
for (const u of leaves(v)) {
|
|
903
|
+
const base = isExpr(u) ? projectionBase(u) : null;
|
|
904
|
+
if (base !== null && base !== id && closed.delete(base))
|
|
905
|
+
again = true;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
if (thisId !== null)
|
|
909
|
+
members.add(thisId);
|
|
910
|
+
// Members that escape (other than by return or into a member's graph)
|
|
911
|
+
// are no longer members; repeat, since a store into a former member's
|
|
912
|
+
// graph now escapes too.
|
|
913
|
+
let esc = escapingLocals(fn, members);
|
|
914
|
+
for (let again = true; again;) {
|
|
915
|
+
again = false;
|
|
916
|
+
for (const id of esc)
|
|
917
|
+
if (members.delete(id))
|
|
918
|
+
again = true;
|
|
919
|
+
if (again)
|
|
920
|
+
esc = escapingLocals(fn, members);
|
|
921
|
+
}
|
|
922
|
+
// Every source must die, be returned, or go into a member's graph; a
|
|
923
|
+
// constructor's `this` must stay a member.
|
|
924
|
+
const inner = internal.get(fn.name);
|
|
925
|
+
fn.params.forEach((param, i) => {
|
|
926
|
+
if (inner.has(i) && esc.has(param.localId)) {
|
|
927
|
+
inner.delete(i);
|
|
928
|
+
internalChanged = true;
|
|
929
|
+
}
|
|
930
|
+
});
|
|
931
|
+
let clean = thisId === null || members.has(thisId);
|
|
932
|
+
let returnsFresh = true;
|
|
933
|
+
const parents = [];
|
|
934
|
+
const walk = (node) => {
|
|
935
|
+
if (!calleesClean(node))
|
|
936
|
+
clean = false;
|
|
937
|
+
if (source(node)) {
|
|
938
|
+
const info = {};
|
|
939
|
+
const use = useOf(node, parents, false, info);
|
|
940
|
+
if (use === "bound") {
|
|
941
|
+
if (esc.has(info.bound) || !fn.locals.some((l) => l.id === info.bound)) {
|
|
942
|
+
clean = false;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
else if (use === "stored") {
|
|
946
|
+
if (info.target === null || info.target === undefined || !members.has(info.target)) {
|
|
947
|
+
clean = false;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
else if (use === "escapes") {
|
|
951
|
+
clean = false;
|
|
952
|
+
}
|
|
953
|
+
else if (use === "thrown") {
|
|
954
|
+
// A thrown value outlives the group, so it may hold no member and
|
|
955
|
+
// nothing allocated with it (a message string is fine).
|
|
956
|
+
const kids = [];
|
|
957
|
+
children(node, kids);
|
|
958
|
+
for (const k of kids)
|
|
959
|
+
if (isExpr(k) &&
|
|
960
|
+
refType(k.type) &&
|
|
961
|
+
leaves(k).some((u) => {
|
|
962
|
+
if (source(u))
|
|
963
|
+
return true;
|
|
964
|
+
const base = isExpr(u) ? projectionBase(u) : null;
|
|
965
|
+
return base !== null && members.has(base);
|
|
966
|
+
}))
|
|
967
|
+
clean = false;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
if (node.kind === "return") {
|
|
971
|
+
const v = node.value;
|
|
972
|
+
if (v !== null && refType(v.type)) {
|
|
973
|
+
for (const u of leaves(v)) {
|
|
974
|
+
if (!(memberSource(u) || (u.kind === "varRef" && members.has(u.localId))))
|
|
975
|
+
returnsFresh = false;
|
|
976
|
+
if (u.kind === "call" && !fresh.has(u.callee))
|
|
977
|
+
returnsFresh = false;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
const kids = [];
|
|
982
|
+
children(node, kids);
|
|
983
|
+
parents.push(node);
|
|
984
|
+
for (const kid of kids)
|
|
985
|
+
walk(kid);
|
|
986
|
+
parents.pop();
|
|
987
|
+
};
|
|
988
|
+
for (const s of fn.body)
|
|
989
|
+
walk(s);
|
|
990
|
+
current = null;
|
|
991
|
+
return { leakFree: clean, fresh: clean && returnsFresh };
|
|
992
|
+
};
|
|
993
|
+
solve(leakFree, referrers, (fn) => {
|
|
994
|
+
if (!leakFree.has(fn.name))
|
|
995
|
+
return false;
|
|
996
|
+
internalChanged = false;
|
|
997
|
+
const r = analyze(fn);
|
|
998
|
+
if (!r.leakFree) {
|
|
999
|
+
leakFree.delete(fn.name);
|
|
1000
|
+
fresh.delete(fn.name);
|
|
1001
|
+
internal.get(fn.name).clear();
|
|
1002
|
+
return true;
|
|
1003
|
+
}
|
|
1004
|
+
return (!r.fresh && fresh.delete(fn.name)) || internalChanged;
|
|
1005
|
+
});
|
|
1006
|
+
// With internal parameters known, a value passed to one stays in the
|
|
1007
|
+
// frame while the call's result does: solve the deep summaries again.
|
|
1008
|
+
solveDeep();
|
|
1009
|
+
// Functions that allocate, directly or through what they call.
|
|
1010
|
+
const allocates = new Set();
|
|
1011
|
+
solve(directAlloc, callers, (fn) => {
|
|
1012
|
+
if (allocates.has(fn.name))
|
|
1013
|
+
return false;
|
|
1014
|
+
allocates.add(fn.name);
|
|
1015
|
+
return true;
|
|
1016
|
+
});
|
|
1017
|
+
// Roots, and call regions: calls of leak-free functions that allocate and
|
|
1018
|
+
// return no reference, so all they allocate is dead when they return.
|
|
1019
|
+
const roots = new Set();
|
|
1020
|
+
const calls = new Set();
|
|
1021
|
+
/** Whether the operands of `node` (evaluated inside its group) are clean:
|
|
1022
|
+
* every call in them is leak-free, no library call returns a reference
|
|
1023
|
+
* (the runtime may keep it: `process.argv`'s cached array), and every value they
|
|
1024
|
+
* allocate goes to `node` as an internal or borrowed argument, or into the
|
|
1025
|
+
* value of another operand. */
|
|
1026
|
+
const operandsClean = (node, parents) => {
|
|
1027
|
+
const stack = [...parents, node];
|
|
1028
|
+
let ok = true;
|
|
1029
|
+
const visit = (n) => {
|
|
1030
|
+
if (!ok)
|
|
1031
|
+
return;
|
|
1032
|
+
if (!same(n, node)) {
|
|
1033
|
+
if (!calleesClean(n))
|
|
1034
|
+
ok = false;
|
|
1035
|
+
if (n.kind === "libCall" && n.fn !== "json.parse" && refType(n.type))
|
|
1036
|
+
ok = false;
|
|
1037
|
+
// `JSON.parse(text) as T`: the parse is the checked value itself.
|
|
1038
|
+
const checked = node.kind === "dynCheck" && same(node.value, n);
|
|
1039
|
+
if (source(n) && !checked) {
|
|
1040
|
+
const info = {};
|
|
1041
|
+
const use = useOf(n, stack, false, info);
|
|
1042
|
+
const at = info.at ?? -1;
|
|
1043
|
+
if (!(use === "kept" || use === "content" || (use === "internal" && at >= parents.length)))
|
|
1044
|
+
ok = false;
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
const kids = [];
|
|
1048
|
+
children(n, kids);
|
|
1049
|
+
const inner = !same(n, node);
|
|
1050
|
+
if (inner)
|
|
1051
|
+
stack.push(n);
|
|
1052
|
+
for (const k of kids)
|
|
1053
|
+
visit(k);
|
|
1054
|
+
if (inner)
|
|
1055
|
+
stack.pop();
|
|
1056
|
+
};
|
|
1057
|
+
visit(node);
|
|
1058
|
+
return ok;
|
|
1059
|
+
};
|
|
1060
|
+
const drops = new Map();
|
|
1061
|
+
const rootLocals = new Map();
|
|
1062
|
+
const rootFunction = new Map();
|
|
1063
|
+
framePass = true;
|
|
1064
|
+
for (const fn of mod.functions) {
|
|
1065
|
+
if (suspends(fn))
|
|
1066
|
+
continue;
|
|
1067
|
+
current = fn;
|
|
1068
|
+
const classes = new Map();
|
|
1069
|
+
const esc = escapingLocals(fn, null, classes);
|
|
1070
|
+
const own = new Set(fn.locals.map((l) => l.id));
|
|
1071
|
+
const paths = declarationPaths(fn);
|
|
1072
|
+
/** The local of `bound`'s class whose scope holds every other one's,
|
|
1073
|
+
* or undefined when no one does. */
|
|
1074
|
+
const classOf = (bound) => {
|
|
1075
|
+
const cls = classes.get(bound);
|
|
1076
|
+
return fn.locals.filter((l) => classes.get(l.id) === cls).map((l) => l.id);
|
|
1077
|
+
};
|
|
1078
|
+
const dropLocal = (bound) => {
|
|
1079
|
+
const members = classOf(bound);
|
|
1080
|
+
const path = (id) => paths.get(id) ?? [];
|
|
1081
|
+
return members.find((m) => members.every((o) => {
|
|
1082
|
+
const a = path(m);
|
|
1083
|
+
const b = path(o);
|
|
1084
|
+
return a.length <= b.length && a.every((x, i) => b[i] === x);
|
|
1085
|
+
}));
|
|
1086
|
+
};
|
|
1087
|
+
const parents = [];
|
|
1088
|
+
const walk = (node) => {
|
|
1089
|
+
const isRoot = isExpr(node) &&
|
|
1090
|
+
((node.kind === "call" && fresh.has(node.callee)) ||
|
|
1091
|
+
(node.kind === "new" && leakFree.has(`%${node.className}.constructor`)) ||
|
|
1092
|
+
((node.kind === "libCall" || node.kind === "dynCheck" || node.kind === "strIntrinsic") &&
|
|
1093
|
+
source(node)) ||
|
|
1094
|
+
(node.kind === "arrIntrinsic" && source(node)));
|
|
1095
|
+
const callbacksClean = node.kind !== "call" ||
|
|
1096
|
+
[...(callbacks.get(node.callee) ?? new Set())].every((j) => callbackClean(node.args[j]));
|
|
1097
|
+
const clean = (isRoot || node.kind === "call") && callbacksClean && operandsClean(node, parents);
|
|
1098
|
+
if (node.kind === "call" &&
|
|
1099
|
+
clean &&
|
|
1100
|
+
!refType(node.type) &&
|
|
1101
|
+
// A constructor (a `super(...)` call) stores into `this`, which its
|
|
1102
|
+
// caller holds: it is leak-free only as part of a `new`.
|
|
1103
|
+
!node.callee.endsWith(".constructor") &&
|
|
1104
|
+
leakFree.has(node.callee) &&
|
|
1105
|
+
allocates.has(node.callee)) {
|
|
1106
|
+
calls.add(node);
|
|
1107
|
+
rootFunction.set(node, fn);
|
|
1108
|
+
}
|
|
1109
|
+
if (isRoot && clean) {
|
|
1110
|
+
const info = {};
|
|
1111
|
+
let use = useOf(node, parents, false, info);
|
|
1112
|
+
if (use === "internal")
|
|
1113
|
+
use = resultUse(info.at, parents, info);
|
|
1114
|
+
rootFunction.set(node, fn);
|
|
1115
|
+
if (use === "kept") {
|
|
1116
|
+
roots.add(node);
|
|
1117
|
+
drops.set(node, null);
|
|
1118
|
+
rootLocals.set(node, new Set());
|
|
1119
|
+
}
|
|
1120
|
+
else if (use === "bound" && own.has(info.bound) && !esc.has(info.bound)) {
|
|
1121
|
+
const local = dropLocal(info.bound);
|
|
1122
|
+
// An assignment in a loop would add a group per iteration to a
|
|
1123
|
+
// list that is dropped only when the local's scope exits.
|
|
1124
|
+
let binding = parents.length - 1;
|
|
1125
|
+
while (binding >= 0 &&
|
|
1126
|
+
parents[binding].kind !== "varDecl" &&
|
|
1127
|
+
parents[binding].kind !== "assign")
|
|
1128
|
+
binding--;
|
|
1129
|
+
const reassignedInLoop = binding >= 0 &&
|
|
1130
|
+
parents[binding].kind === "assign" &&
|
|
1131
|
+
parents.slice(0, binding).some((p) => LOOP_KINDS.has(p.kind));
|
|
1132
|
+
if (local !== undefined && !reassignedInLoop) {
|
|
1133
|
+
roots.add(node);
|
|
1134
|
+
drops.set(node, local);
|
|
1135
|
+
rootLocals.set(node, new Set(classOf(info.bound)));
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
const kids = [];
|
|
1140
|
+
children(node, kids);
|
|
1141
|
+
parents.push(node);
|
|
1142
|
+
for (const kid of kids)
|
|
1143
|
+
walk(kid);
|
|
1144
|
+
parents.pop();
|
|
1145
|
+
};
|
|
1146
|
+
for (const s of fn.body)
|
|
1147
|
+
walk(s);
|
|
1148
|
+
}
|
|
1149
|
+
current = null;
|
|
1150
|
+
// Functions that run inside an arena: what roots and call regions call,
|
|
1151
|
+
// and what those call, with the closures they pass.
|
|
1152
|
+
const reachable = new Set();
|
|
1153
|
+
const queue = [];
|
|
1154
|
+
const reach = (name) => {
|
|
1155
|
+
if (fns.has(name) && !reachable.has(name)) {
|
|
1156
|
+
reachable.add(name);
|
|
1157
|
+
queue.push(name);
|
|
1158
|
+
}
|
|
1159
|
+
};
|
|
1160
|
+
const callees = (node) => {
|
|
1161
|
+
if (node.kind === "call")
|
|
1162
|
+
reach(node.callee);
|
|
1163
|
+
else if (node.kind === "virtualCall")
|
|
1164
|
+
for (const t of virtualTargetsOf(vt, node) ?? [])
|
|
1165
|
+
reach(t);
|
|
1166
|
+
else if (node.kind === "new")
|
|
1167
|
+
reach(`%${node.className}.constructor`);
|
|
1168
|
+
else if (node.kind === "closure")
|
|
1169
|
+
reach(node.fnName);
|
|
1170
|
+
};
|
|
1171
|
+
const scanAll = (node, visit) => {
|
|
1172
|
+
visit(node);
|
|
1173
|
+
const kids = [];
|
|
1174
|
+
children(node, kids);
|
|
1175
|
+
for (const k of kids)
|
|
1176
|
+
scanAll(k, visit);
|
|
1177
|
+
};
|
|
1178
|
+
for (const r of [...roots, ...calls])
|
|
1179
|
+
scanAll(r, callees);
|
|
1180
|
+
while (queue.length > 0) {
|
|
1181
|
+
const fn = fns.get(queue.pop());
|
|
1182
|
+
for (const st of fn.body)
|
|
1183
|
+
scanAll(st, callees);
|
|
1184
|
+
}
|
|
1185
|
+
const closed = new Set();
|
|
1186
|
+
return {
|
|
1187
|
+
roots,
|
|
1188
|
+
calls,
|
|
1189
|
+
drops,
|
|
1190
|
+
rootLocals,
|
|
1191
|
+
rootFunction,
|
|
1192
|
+
reachable,
|
|
1193
|
+
closed,
|
|
1194
|
+
fresh,
|
|
1195
|
+
leakFree,
|
|
1196
|
+
allocates,
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
/** For each local declared in `fn`, the statement lists that enclose its
|
|
1200
|
+
* declaration, outermost first (the body included); a declaration inside an
|
|
1201
|
+
* expression (a sequence's statements) is nested in the statement that
|
|
1202
|
+
* holds it. Parameters and locals without a declaration have none: the
|
|
1203
|
+
* function's own scope. A `for…of` variable counts as declared in the list
|
|
1204
|
+
* holding the loop. */
|
|
1205
|
+
function declarationPaths(fn) {
|
|
1206
|
+
const out = new Map();
|
|
1207
|
+
// Each statement list (and each expression holding one) gets an id.
|
|
1208
|
+
let next = 0;
|
|
1209
|
+
const walk = (list, path) => {
|
|
1210
|
+
if (list.length === 0)
|
|
1211
|
+
return;
|
|
1212
|
+
const here = [...path, next++];
|
|
1213
|
+
for (const stmt of list) {
|
|
1214
|
+
if (stmt.kind === "varDecl" || stmt.kind === "forOf")
|
|
1215
|
+
out.set(stmt.localId, here);
|
|
1216
|
+
for (const inner of stmtLists(stmt))
|
|
1217
|
+
walk(inner, here);
|
|
1218
|
+
// Statements inside the statement's expressions, one level deeper.
|
|
1219
|
+
const visit = (e) => {
|
|
1220
|
+
if (e.kind === "seqExpr")
|
|
1221
|
+
walk(e.stmts, [...here, next++]);
|
|
1222
|
+
everyExprChild(e, visit, () => true);
|
|
1223
|
+
return true;
|
|
1224
|
+
};
|
|
1225
|
+
everyStmtChild(stmt, visit, () => true);
|
|
1226
|
+
}
|
|
1227
|
+
};
|
|
1228
|
+
walk(fn.body, []);
|
|
1229
|
+
return out;
|
|
1230
|
+
}
|
|
1231
|
+
/** The statement lists directly inside `stmt`. */
|
|
1232
|
+
function stmtLists(stmt) {
|
|
1233
|
+
switch (stmt.kind) {
|
|
1234
|
+
case "if":
|
|
1235
|
+
return stmt.else_ === null ? [stmt.then] : [stmt.then, stmt.else_];
|
|
1236
|
+
case "while":
|
|
1237
|
+
case "doWhile":
|
|
1238
|
+
case "for":
|
|
1239
|
+
case "forOf":
|
|
1240
|
+
case "block":
|
|
1241
|
+
return [stmt.body];
|
|
1242
|
+
case "switch":
|
|
1243
|
+
return stmt.cases.map((c) => c.body);
|
|
1244
|
+
case "tryCatch":
|
|
1245
|
+
return [stmt.tryBody, stmt.catchBody ?? [], stmt.finallyBody ?? []];
|
|
1246
|
+
default:
|
|
1247
|
+
return [];
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
/**
|
|
1251
|
+
* The roots and call regions whose groups are closed: every reference an
|
|
1252
|
+
* arena object of the group holds is to an arena object of the group or an
|
|
1253
|
+
* immortal value, so dropping the arena releases nothing.
|
|
1254
|
+
*
|
|
1255
|
+
* `arenaType(t)` says whether a value of type `t` is a plain reference to
|
|
1256
|
+
* an object the arena-aware constructors allocate (no box around it).
|
|
1257
|
+
*
|
|
1258
|
+
* A function is closed when every reference it stores (into a field, an
|
|
1259
|
+
* element, a collection, or the content of a new object) is closed:
|
|
1260
|
+
* - a value without references, an immortal literal, or null/undefined;
|
|
1261
|
+
* - an object of an arena type it allocates, or the result of a call of a
|
|
1262
|
+
* closed function whose results are closed;
|
|
1263
|
+
* - a local bound only to closed values, or a reference of an arena type
|
|
1264
|
+
* read out of one;
|
|
1265
|
+
* - a constructor's `this`;
|
|
1266
|
+
* - a parameter, or a reference read out of one: its callers must pass a
|
|
1267
|
+
* closed value (the function's stored parameters).
|
|
1268
|
+
* Every function it calls must be closed and get closed values for their
|
|
1269
|
+
* stored parameters. A root's group is then closed when its callee is,
|
|
1270
|
+
* its arguments for stored parameters are closed in its caller, and the
|
|
1271
|
+
* caller stores only closed values into the root's graph afterwards (there,
|
|
1272
|
+
* only values without references, literals, and references read out of the
|
|
1273
|
+
* root's own locals are closed: the caller's own allocations are on the
|
|
1274
|
+
* heap). Solved optimistically to a fixpoint.
|
|
1275
|
+
*/
|
|
1276
|
+
export function analyzeClosedGroups(mod, groups, arenaType,
|
|
1277
|
+
/** Whether an allocation or call site's objects take the arena. */
|
|
1278
|
+
kept = () => true) {
|
|
1279
|
+
const fns = new Map();
|
|
1280
|
+
for (const fn of mod.functions)
|
|
1281
|
+
fns.set(fn.name, fn);
|
|
1282
|
+
const vt = new VirtualTargets(mod.classes ?? []);
|
|
1283
|
+
const closedFn = new Set([...groups.reachable].filter((f) => groups.leakFree.has(f)));
|
|
1284
|
+
const closedFresh = new Set([...closedFn].filter((f) => groups.fresh.has(f)));
|
|
1285
|
+
const stored = new Map();
|
|
1286
|
+
const storedOf = (name) => stored.get(name) ?? new Set();
|
|
1287
|
+
const leavesOf = (e, out = []) => {
|
|
1288
|
+
let at = e;
|
|
1289
|
+
for (let i = 0; i < 16; i++)
|
|
1290
|
+
if (at.kind === "unionWrap" ||
|
|
1291
|
+
at.kind === "upcast" ||
|
|
1292
|
+
at.kind === "downcast" ||
|
|
1293
|
+
at.kind === "unionRetype")
|
|
1294
|
+
at = at.value;
|
|
1295
|
+
else
|
|
1296
|
+
break;
|
|
1297
|
+
if (at.kind === "ternary") {
|
|
1298
|
+
if (!throws(at.then))
|
|
1299
|
+
leavesOf(at.then, out);
|
|
1300
|
+
if (!throws(at.else_))
|
|
1301
|
+
leavesOf(at.else_, out);
|
|
1302
|
+
}
|
|
1303
|
+
else
|
|
1304
|
+
out.push(at);
|
|
1305
|
+
return out;
|
|
1306
|
+
};
|
|
1307
|
+
// Functions that return only references read out of one parameter (or
|
|
1308
|
+
// null/undefined), such as the checked element read `%arr.idxOr`: a call
|
|
1309
|
+
// of one reads out of that argument.
|
|
1310
|
+
const projects = new Map();
|
|
1311
|
+
for (const fn of mod.functions) {
|
|
1312
|
+
const assigned = new Set();
|
|
1313
|
+
let index = null;
|
|
1314
|
+
let ok = true;
|
|
1315
|
+
const visit = (node) => {
|
|
1316
|
+
if (!ok)
|
|
1317
|
+
return;
|
|
1318
|
+
if (node.kind === "assign")
|
|
1319
|
+
assigned.add(node.localId);
|
|
1320
|
+
if (node.kind === "return") {
|
|
1321
|
+
const v = node.value;
|
|
1322
|
+
if (v === null)
|
|
1323
|
+
ok = false;
|
|
1324
|
+
else
|
|
1325
|
+
for (const u of leavesOf(v)) {
|
|
1326
|
+
if (u.kind === "unitLit")
|
|
1327
|
+
continue;
|
|
1328
|
+
const base = projectionBase(u);
|
|
1329
|
+
const i = base === null ? -1 : fn.params.findIndex((p) => p.localId === base);
|
|
1330
|
+
if (i < 0 || (index !== null && index !== i))
|
|
1331
|
+
ok = false;
|
|
1332
|
+
else
|
|
1333
|
+
index = i;
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
const kids = [];
|
|
1337
|
+
children(node, kids);
|
|
1338
|
+
for (const k of kids)
|
|
1339
|
+
visit(k);
|
|
1340
|
+
};
|
|
1341
|
+
if (!refType(fn.returnType))
|
|
1342
|
+
continue;
|
|
1343
|
+
for (const st of fn.body)
|
|
1344
|
+
visit(st);
|
|
1345
|
+
if (ok && index !== null && !assigned.has(fn.params[index].localId))
|
|
1346
|
+
projects.set(fn.name, index);
|
|
1347
|
+
}
|
|
1348
|
+
const through = (call) => {
|
|
1349
|
+
if (call.kind !== "call")
|
|
1350
|
+
return null;
|
|
1351
|
+
const i = projects.get(call.callee);
|
|
1352
|
+
return i === undefined ? null : (call.args[i] ?? null);
|
|
1353
|
+
};
|
|
1354
|
+
/** Whether `e` (in `fn`, `own` its closed locals, `inArena` whether its
|
|
1355
|
+
* allocations are arena objects) is a closed value; parameters it reads
|
|
1356
|
+
* go into `params`. */
|
|
1357
|
+
const closedValue = (e, fn, own, inArena, params) => {
|
|
1358
|
+
if (!isExpr(e))
|
|
1359
|
+
return false;
|
|
1360
|
+
const t = e.type;
|
|
1361
|
+
if (t.kind === "string")
|
|
1362
|
+
return e.kind === "strLit";
|
|
1363
|
+
// Any other counted value (a typed array, a promise) is a heap object.
|
|
1364
|
+
if (!refType(t) && !isRefCounted(t))
|
|
1365
|
+
return true;
|
|
1366
|
+
if (!arenaType(t))
|
|
1367
|
+
return false;
|
|
1368
|
+
return leavesOf(e).every((u) => {
|
|
1369
|
+
if (u.kind === "unitLit")
|
|
1370
|
+
return true;
|
|
1371
|
+
if (u.kind === "recordLit" || u.kind === "new" || u.kind === "arrayLit")
|
|
1372
|
+
return inArena && arenaType(u.type) && kept(u);
|
|
1373
|
+
if (u.kind === "call" && !projects.has(u.callee))
|
|
1374
|
+
return inArena && closedFresh.has(u.callee) && arenaType(u.type) && kept(u);
|
|
1375
|
+
const base = projectionBase(u, through);
|
|
1376
|
+
if (base === null)
|
|
1377
|
+
return false;
|
|
1378
|
+
const i = fn.params.findIndex((p) => p.localId === base);
|
|
1379
|
+
if (i >= 0) {
|
|
1380
|
+
if (i === 0 && fn.name.endsWith(".constructor") && u.kind === "varRef")
|
|
1381
|
+
return true;
|
|
1382
|
+
params.add(i);
|
|
1383
|
+
return arenaType(u.type);
|
|
1384
|
+
}
|
|
1385
|
+
return own.has(base) && arenaType(u.type);
|
|
1386
|
+
});
|
|
1387
|
+
};
|
|
1388
|
+
/** Every reference store and content position in `fn`'s body, and every
|
|
1389
|
+
* call with the arguments its callee stores. */
|
|
1390
|
+
const siteMemo = new Map();
|
|
1391
|
+
const sites = (fn) => {
|
|
1392
|
+
const memo = siteMemo.get(fn.name);
|
|
1393
|
+
if (memo !== undefined)
|
|
1394
|
+
return memo;
|
|
1395
|
+
const out = [];
|
|
1396
|
+
siteMemo.set(fn.name, out);
|
|
1397
|
+
const walk = (node, parent) => {
|
|
1398
|
+
if (parent !== undefined && isExpr(node)) {
|
|
1399
|
+
const target = storeOf(node, parent);
|
|
1400
|
+
if (target !== undefined)
|
|
1401
|
+
out.push({ value: node, target: storeTarget(target) });
|
|
1402
|
+
else if (contentOf(node, parent) && parent.kind !== "new")
|
|
1403
|
+
out.push({ value: node, target: null });
|
|
1404
|
+
}
|
|
1405
|
+
const kids = [];
|
|
1406
|
+
children(node, kids);
|
|
1407
|
+
for (const k of kids)
|
|
1408
|
+
walk(k, node);
|
|
1409
|
+
};
|
|
1410
|
+
for (const st of fn.body)
|
|
1411
|
+
walk(st, undefined);
|
|
1412
|
+
return out;
|
|
1413
|
+
};
|
|
1414
|
+
const bindingMemo = new Map();
|
|
1415
|
+
const bindingsOf = (fn) => {
|
|
1416
|
+
const memo = bindingMemo.get(fn.name);
|
|
1417
|
+
if (memo !== undefined)
|
|
1418
|
+
return memo;
|
|
1419
|
+
const out = new Map();
|
|
1420
|
+
bindingMemo.set(fn.name, out);
|
|
1421
|
+
const scan = (node) => {
|
|
1422
|
+
if (node.kind === "varDecl" || node.kind === "assign") {
|
|
1423
|
+
const v = node.kind === "varDecl" ? node.init : node.value;
|
|
1424
|
+
if (v !== null)
|
|
1425
|
+
out.set(node.localId, [...(out.get(node.localId) ?? []), v]);
|
|
1426
|
+
}
|
|
1427
|
+
// A loop variable holds elements read out of the iterable.
|
|
1428
|
+
if (node.kind === "forOf")
|
|
1429
|
+
out.set(node.localId, [...(out.get(node.localId) ?? []), node.iterable]);
|
|
1430
|
+
const kids = [];
|
|
1431
|
+
children(node, kids);
|
|
1432
|
+
for (const k of kids)
|
|
1433
|
+
scan(k);
|
|
1434
|
+
};
|
|
1435
|
+
for (const st of fn.body)
|
|
1436
|
+
scan(st);
|
|
1437
|
+
return out;
|
|
1438
|
+
};
|
|
1439
|
+
// Written parameters: those whose graph a function may store into, itself
|
|
1440
|
+
// or through what it calls (any function, not only arena-aware ones).
|
|
1441
|
+
const writes = new Map();
|
|
1442
|
+
/** The parameter whose graph `local` reaches into, through bindings to
|
|
1443
|
+
* references read out of it, or -1. */
|
|
1444
|
+
const paramOf = (fn, bindings, local) => {
|
|
1445
|
+
let at = local;
|
|
1446
|
+
for (let i = 0; i < 16; i++) {
|
|
1447
|
+
const p = fn.params.findIndex((q) => q.localId === at);
|
|
1448
|
+
if (p >= 0)
|
|
1449
|
+
return p;
|
|
1450
|
+
const list = bindings.get(at);
|
|
1451
|
+
if (list === undefined || list.length !== 1)
|
|
1452
|
+
return -1;
|
|
1453
|
+
const base = projectionBase(list[0]);
|
|
1454
|
+
if (base === null || base === at)
|
|
1455
|
+
return -1;
|
|
1456
|
+
at = base;
|
|
1457
|
+
}
|
|
1458
|
+
return -1;
|
|
1459
|
+
};
|
|
1460
|
+
// Each function's own writes, and the parameters it passes to calls: a
|
|
1461
|
+
// parameter passed where the callee writes is written too.
|
|
1462
|
+
const passed = new Map();
|
|
1463
|
+
const writers = new Map();
|
|
1464
|
+
// Only what the functions holding roots call, transitively, is asked.
|
|
1465
|
+
const asked = new Set();
|
|
1466
|
+
{
|
|
1467
|
+
const queue = [
|
|
1468
|
+
...new Set([...groups.roots, ...groups.calls].flatMap((r) => groups.rootFunction.get(r)?.name ?? [])),
|
|
1469
|
+
];
|
|
1470
|
+
for (const name of queue)
|
|
1471
|
+
asked.add(name);
|
|
1472
|
+
while (queue.length > 0) {
|
|
1473
|
+
const fn = fns.get(queue.pop());
|
|
1474
|
+
if (fn === undefined)
|
|
1475
|
+
continue;
|
|
1476
|
+
const visit = (n) => {
|
|
1477
|
+
const targets = n.kind === "call"
|
|
1478
|
+
? [n.callee]
|
|
1479
|
+
: n.kind === "virtualCall"
|
|
1480
|
+
? (virtualTargetsOf(vt, n) ?? [])
|
|
1481
|
+
: [];
|
|
1482
|
+
for (const t of targets)
|
|
1483
|
+
if (fns.has(t) && !asked.has(t)) {
|
|
1484
|
+
asked.add(t);
|
|
1485
|
+
queue.push(t);
|
|
1486
|
+
}
|
|
1487
|
+
const kids = [];
|
|
1488
|
+
children(n, kids);
|
|
1489
|
+
for (const k of kids)
|
|
1490
|
+
visit(k);
|
|
1491
|
+
};
|
|
1492
|
+
for (const st of fn.body)
|
|
1493
|
+
visit(st);
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
for (const fn of mod.functions) {
|
|
1497
|
+
if (!asked.has(fn.name))
|
|
1498
|
+
continue;
|
|
1499
|
+
const bindings = bindingsOf(fn);
|
|
1500
|
+
const set = new Set();
|
|
1501
|
+
for (const { target } of sites(fn))
|
|
1502
|
+
if (target !== null) {
|
|
1503
|
+
const i = paramOf(fn, bindings, target);
|
|
1504
|
+
if (i >= 0)
|
|
1505
|
+
set.add(i);
|
|
1506
|
+
}
|
|
1507
|
+
const list = [];
|
|
1508
|
+
const visit = (n) => {
|
|
1509
|
+
const args = argsOf(n);
|
|
1510
|
+
if (args !== null) {
|
|
1511
|
+
const callees = n.kind === "call"
|
|
1512
|
+
? [n.callee]
|
|
1513
|
+
: n.kind === "virtualCall"
|
|
1514
|
+
? (virtualTargetsOf(vt, n) ?? [])
|
|
1515
|
+
: null;
|
|
1516
|
+
args.forEach((a, j) => {
|
|
1517
|
+
const base = projectionBase(a);
|
|
1518
|
+
const i = base === null ? -1 : paramOf(fn, bindings, base);
|
|
1519
|
+
if (i < 0)
|
|
1520
|
+
return;
|
|
1521
|
+
if (callees === null || callees.length === 0 || callees.some((c) => !fns.has(c)))
|
|
1522
|
+
set.add(i);
|
|
1523
|
+
else {
|
|
1524
|
+
list.push({ param: i, callees, index: j });
|
|
1525
|
+
for (const c of callees) {
|
|
1526
|
+
let w = writers.get(c);
|
|
1527
|
+
if (w === undefined)
|
|
1528
|
+
writers.set(c, (w = new Set()));
|
|
1529
|
+
w.add(fn.name);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
const kids = [];
|
|
1535
|
+
children(n, kids);
|
|
1536
|
+
for (const k of kids)
|
|
1537
|
+
visit(k);
|
|
1538
|
+
};
|
|
1539
|
+
for (const st of fn.body)
|
|
1540
|
+
visit(st);
|
|
1541
|
+
writes.set(fn.name, set);
|
|
1542
|
+
passed.set(fn.name, list);
|
|
1543
|
+
}
|
|
1544
|
+
{
|
|
1545
|
+
const queue = [...asked];
|
|
1546
|
+
const queued = new Set(queue);
|
|
1547
|
+
while (queue.length > 0) {
|
|
1548
|
+
const name = queue.pop();
|
|
1549
|
+
queued.delete(name);
|
|
1550
|
+
const set = writes.get(name);
|
|
1551
|
+
const before = set.size;
|
|
1552
|
+
for (const { param, callees, index } of passed.get(name))
|
|
1553
|
+
if (callees.some((c) => writes.get(c)?.has(index) === true))
|
|
1554
|
+
set.add(param);
|
|
1555
|
+
if (set.size !== before)
|
|
1556
|
+
for (const r of writers.get(name) ?? new Set())
|
|
1557
|
+
if (!queued.has(r)) {
|
|
1558
|
+
queued.add(r);
|
|
1559
|
+
queue.push(r);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
/** The locals of `fn` bound only to closed values. */
|
|
1564
|
+
const closedLocals = (fn, inArena, seed) => {
|
|
1565
|
+
const bindings = bindingsOf(fn);
|
|
1566
|
+
const own = new Set(fn.locals
|
|
1567
|
+
.filter((l) => l.boxed !== true && !fn.params.some((p) => p.localId === l.id))
|
|
1568
|
+
.map((l) => l.id));
|
|
1569
|
+
for (const id of seed ?? new Set())
|
|
1570
|
+
own.add(id);
|
|
1571
|
+
for (let again = true; again;) {
|
|
1572
|
+
again = false;
|
|
1573
|
+
for (const id of [...own]) {
|
|
1574
|
+
if (seed?.has(id) === true)
|
|
1575
|
+
continue;
|
|
1576
|
+
const list = bindings.get(id) ?? [];
|
|
1577
|
+
if (!list.every((v) => closedValue(v, fn, own, inArena, new Set()))) {
|
|
1578
|
+
own.delete(id);
|
|
1579
|
+
again = true;
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
return own;
|
|
1584
|
+
};
|
|
1585
|
+
/** Whether the calls in `node`'s subtree are of closed functions with
|
|
1586
|
+
* closed arguments for their stored parameters. */
|
|
1587
|
+
const callsClosed = (node, fn, own, inArena, params) => {
|
|
1588
|
+
let ok = true;
|
|
1589
|
+
const visit = (n) => {
|
|
1590
|
+
if (!ok)
|
|
1591
|
+
return;
|
|
1592
|
+
if (n.kind === "call" || n.kind === "new" || n.kind === "virtualCall") {
|
|
1593
|
+
const targets = n.kind === "call"
|
|
1594
|
+
? [n.callee]
|
|
1595
|
+
: n.kind === "new"
|
|
1596
|
+
? [`%${n.className}.constructor`]
|
|
1597
|
+
: (virtualTargetsOf(vt, n) ?? []);
|
|
1598
|
+
if (targets.length === 0)
|
|
1599
|
+
ok = false;
|
|
1600
|
+
const shift = n.kind === "new" ? 1 : 0;
|
|
1601
|
+
for (const t of targets) {
|
|
1602
|
+
if (!closedFn.has(t))
|
|
1603
|
+
ok = false;
|
|
1604
|
+
for (const j of storedOf(t)) {
|
|
1605
|
+
const arg = n.args[j - shift];
|
|
1606
|
+
if (arg !== undefined && !closedValue(arg, fn, own, inArena, params))
|
|
1607
|
+
ok = false;
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
else if (n.kind === "callValue" || n.kind === "dynCall" || n.kind === "dynInvoke")
|
|
1612
|
+
ok = false;
|
|
1613
|
+
else if ((n.kind === "arrIntrinsic" || n.kind === "mapIntrinsic" || n.kind === "setIntrinsic") &&
|
|
1614
|
+
!READ_RECEIVER.has(n.method) &&
|
|
1615
|
+
!ADDING_METHODS.has(n.method) &&
|
|
1616
|
+
n.args.some((a) => refType(a.type) || isRefCounted(a.type)))
|
|
1617
|
+
ok = false;
|
|
1618
|
+
const kids = [];
|
|
1619
|
+
children(n, kids);
|
|
1620
|
+
for (const k of kids)
|
|
1621
|
+
visit(k);
|
|
1622
|
+
};
|
|
1623
|
+
visit(node);
|
|
1624
|
+
return ok;
|
|
1625
|
+
};
|
|
1626
|
+
for (let changed = true; changed;) {
|
|
1627
|
+
changed = false;
|
|
1628
|
+
for (const name of [...closedFn]) {
|
|
1629
|
+
const fn = fns.get(name);
|
|
1630
|
+
const params = new Set();
|
|
1631
|
+
const own = closedLocals(fn, true);
|
|
1632
|
+
let ok = sites(fn).every(({ value }) => closedValue(value, fn, own, true, params));
|
|
1633
|
+
for (const st of fn.body)
|
|
1634
|
+
if (ok)
|
|
1635
|
+
ok = callsClosed(st, fn, own, true, params);
|
|
1636
|
+
let returnsClosed = true;
|
|
1637
|
+
const scanReturns = (node) => {
|
|
1638
|
+
if (node.kind === "return") {
|
|
1639
|
+
const v = node.value;
|
|
1640
|
+
if (v !== null && !closedValue(v, fn, own, true, params))
|
|
1641
|
+
returnsClosed = false;
|
|
1642
|
+
}
|
|
1643
|
+
const kids = [];
|
|
1644
|
+
children(node, kids);
|
|
1645
|
+
for (const k of kids)
|
|
1646
|
+
scanReturns(k);
|
|
1647
|
+
};
|
|
1648
|
+
for (const st of fn.body)
|
|
1649
|
+
scanReturns(st);
|
|
1650
|
+
const before = storedOf(name);
|
|
1651
|
+
if ([...params].some((i) => !before.has(i))) {
|
|
1652
|
+
stored.set(name, new Set([...before, ...params]));
|
|
1653
|
+
changed = true;
|
|
1654
|
+
}
|
|
1655
|
+
if (!ok) {
|
|
1656
|
+
closedFn.delete(name);
|
|
1657
|
+
closedFresh.delete(name);
|
|
1658
|
+
changed = true;
|
|
1659
|
+
}
|
|
1660
|
+
else if (!returnsClosed && closedFresh.delete(name))
|
|
1661
|
+
changed = true;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
const out = new Set();
|
|
1665
|
+
for (const root of [...groups.roots, ...groups.calls]) {
|
|
1666
|
+
const fn = groups.rootFunction.get(root);
|
|
1667
|
+
if (fn === undefined)
|
|
1668
|
+
continue;
|
|
1669
|
+
const locals = groups.rootLocals.get(root) ?? new Set();
|
|
1670
|
+
const bindings = bindingsOf(fn);
|
|
1671
|
+
/** Whether `local` reaches into the root's graph: one of its locals,
|
|
1672
|
+
* or bound (a loop variable included) to a reference read out of one. */
|
|
1673
|
+
const intoRoot = (local, depth = 0) => locals.has(local) ||
|
|
1674
|
+
(depth < 16 &&
|
|
1675
|
+
(bindings.get(local) ?? []).some((v) => {
|
|
1676
|
+
const base = projectionBase(v);
|
|
1677
|
+
return base !== null && base !== local && intoRoot(base, depth + 1);
|
|
1678
|
+
}));
|
|
1679
|
+
// In the caller only the root's own locals and what is read out of them
|
|
1680
|
+
// are closed references.
|
|
1681
|
+
const params = new Set();
|
|
1682
|
+
let ok = callsClosed(root, fn, locals, false, params) && params.size === 0;
|
|
1683
|
+
// After the arena closes, a call that is passed the root's value (or a
|
|
1684
|
+
// reference read out of it) must not write into it.
|
|
1685
|
+
const passes = (n, parent) => {
|
|
1686
|
+
if (!ok)
|
|
1687
|
+
return;
|
|
1688
|
+
if (parent !== undefined && isExpr(n)) {
|
|
1689
|
+
const args = argsOf(parent);
|
|
1690
|
+
const j = args === null ? -1 : indexOfNode(args, n);
|
|
1691
|
+
const base = projectionBase(n);
|
|
1692
|
+
if (j >= 0 && refType(n.type) && (same(n, root) || (base !== null && intoRoot(base)))) {
|
|
1693
|
+
const callees = parent.kind === "call"
|
|
1694
|
+
? [parent.callee]
|
|
1695
|
+
: parent.kind === "virtualCall"
|
|
1696
|
+
? (virtualTargetsOf(vt, parent) ?? [])
|
|
1697
|
+
: [];
|
|
1698
|
+
if (callees.length === 0 || callees.some((c) => writes.get(c)?.has(j) !== false))
|
|
1699
|
+
ok = false;
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
const kids = [];
|
|
1703
|
+
children(n, kids);
|
|
1704
|
+
for (const k of kids)
|
|
1705
|
+
passes(k, n);
|
|
1706
|
+
};
|
|
1707
|
+
if (ok && !groups.calls.has(root))
|
|
1708
|
+
for (const st of fn.body)
|
|
1709
|
+
passes(st, undefined);
|
|
1710
|
+
if (ok && locals.size > 0)
|
|
1711
|
+
ok = sites(fn).every(({ value, target }) => target === null ||
|
|
1712
|
+
!intoRoot(target) ||
|
|
1713
|
+
(closedValue(value, fn, locals, false, params) && params.size === 0));
|
|
1714
|
+
if (ok)
|
|
1715
|
+
out.add(root);
|
|
1716
|
+
}
|
|
1717
|
+
return out;
|
|
1718
|
+
}
|
|
1719
|
+
//# sourceMappingURL=region-groups.js.map
|