@scriptc/compiler 0.4.1 → 0.4.3
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/scriptc-node-fallback.d.ts +977 -113
- package/dist/backend/cycle-analysis.d.ts +5 -1
- package/dist/backend/cycle-analysis.js +6 -4
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +55 -0
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/cycle-mutability.d.ts +9 -1
- package/dist/backend/cycle-mutability.js +21 -3
- package/dist/backend/cycle-mutability.js.map +1 -1
- package/dist/backend/executable-features.js +6 -1
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/immutability.d.ts +7 -3
- package/dist/backend/immutability.js +33 -29
- package/dist/backend/immutability.js.map +1 -1
- package/dist/backend/library-pack.js +5 -0
- package/dist/backend/library-pack.js.map +1 -1
- package/dist/backend/llvm/alloc.d.ts +23 -4
- package/dist/backend/llvm/alloc.js +61 -8
- package/dist/backend/llvm/alloc.js.map +1 -1
- package/dist/backend/llvm/appended-array-literals.d.ts +2 -1
- package/dist/backend/llvm/appended-array-literals.js +44 -36
- package/dist/backend/llvm/appended-array-literals.js.map +1 -1
- package/dist/backend/llvm/appended-array-literals.test.js +4 -3
- package/dist/backend/llvm/appended-array-literals.test.js.map +1 -1
- package/dist/backend/llvm/array-search.d.ts +4 -3
- package/dist/backend/llvm/array-search.js +23 -10
- package/dist/backend/llvm/array-search.js.map +1 -1
- package/dist/backend/llvm/blocks.d.ts +1 -1
- package/dist/backend/llvm/blocks.js +2 -2
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/byte-windows.js +2 -0
- package/dist/backend/llvm/byte-windows.js.map +1 -1
- package/dist/backend/llvm/bytes-alias.d.ts +6 -1
- package/dist/backend/llvm/bytes-alias.js +8 -2
- package/dist/backend/llvm/bytes-alias.js.map +1 -1
- package/dist/backend/llvm/bytes-loop-versions.d.ts +70 -7
- package/dist/backend/llvm/bytes-loop-versions.js +567 -30
- package/dist/backend/llvm/bytes-loop-versions.js.map +1 -1
- package/dist/backend/llvm/bytes-loop-versions.test.js +389 -2
- package/dist/backend/llvm/bytes-loop-versions.test.js.map +1 -1
- package/dist/backend/llvm/checked-value-lifetimes.js +2 -0
- package/dist/backend/llvm/checked-value-lifetimes.js.map +1 -1
- package/dist/backend/llvm/classes.d.ts +74 -1
- package/dist/backend/llvm/classes.js +364 -54
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +384 -17
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +10 -6
- package/dist/backend/llvm/common.js +10 -6
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.d.ts +2 -1
- package/dist/backend/llvm/constant-callbacks.js +91 -56
- package/dist/backend/llvm/constant-callbacks.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.test.js +4 -4
- package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
- package/dist/backend/llvm/counted-loops.d.ts +11 -1
- package/dist/backend/llvm/counted-loops.js +80 -23
- package/dist/backend/llvm/counted-loops.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.d.ts +39 -8
- package/dist/backend/llvm/dense-array-access.js +222 -52
- package/dist/backend/llvm/dense-array-access.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.test.js +36 -0
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
- package/dist/backend/llvm/dense-array-loops.d.ts +35 -16
- package/dist/backend/llvm/dense-array-loops.js +237 -12
- package/dist/backend/llvm/dense-array-loops.js.map +1 -1
- package/dist/backend/llvm/dense-array-loops.test.js +140 -15
- package/dist/backend/llvm/dense-array-loops.test.js.map +1 -1
- package/dist/backend/llvm/dyn-handle-tags.test.js +6 -1
- package/dist/backend/llvm/dyn-handle-tags.test.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +51 -1
- package/dist/backend/llvm/dyn.js +683 -69
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emit-function.js +33 -26
- package/dist/backend/llvm/emit-function.js.map +1 -1
- package/dist/backend/llvm/emit-journal.d.ts +93 -0
- package/dist/backend/llvm/emit-journal.js +170 -0
- package/dist/backend/llvm/emit-journal.js.map +1 -0
- package/dist/backend/llvm/emit-module.js +208 -34
- package/dist/backend/llvm/emit-module.js.map +1 -1
- package/dist/backend/llvm/emit-statements.d.ts +0 -27
- package/dist/backend/llvm/emit-statements.js +577 -93
- package/dist/backend/llvm/emit-statements.js.map +1 -1
- package/dist/backend/llvm/emitter-state.d.ts +7 -0
- package/dist/backend/llvm/emitter-state.js +14 -0
- package/dist/backend/llvm/emitter-state.js.map +1 -0
- package/dist/backend/llvm/emitter.d.ts +314 -49
- package/dist/backend/llvm/emitter.js +1241 -129
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +54 -5
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +19 -0
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +5 -2
- package/dist/backend/llvm/expr-bytes.js +144 -52
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.js +47 -0
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.d.ts +1 -1
- package/dist/backend/llvm/expr-calls.js +62 -36
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +14 -2
- package/dist/backend/llvm/expr-containers.js +148 -40
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +14 -0
- package/dist/backend/llvm/expr-control.js +2 -3
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +71 -16
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +126 -36
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +11 -6
- package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
- package/dist/backend/llvm/expr-records.d.ts +12 -0
- package/dist/backend/llvm/expr-records.js +106 -0
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.d.ts +2 -2
- package/dist/backend/llvm/expr-stream-bridges.js +225 -64
- 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.d.ts +2 -2
- package/dist/backend/llvm/expr-stream-callbacks.js +200 -50
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/int32-kind-loops.d.ts +39 -0
- package/dist/backend/llvm/int32-kind-loops.js +106 -0
- package/dist/backend/llvm/int32-kind-loops.js.map +1 -0
- package/dist/backend/llvm/integer-or-nan-indexes.test.d.ts +1 -0
- package/dist/backend/llvm/integer-or-nan-indexes.test.js +118 -0
- package/dist/backend/llvm/integer-or-nan-indexes.test.js.map +1 -0
- package/dist/backend/llvm/integer-values.d.ts +20 -1
- package/dist/backend/llvm/integer-values.js +71 -0
- package/dist/backend/llvm/integer-values.js.map +1 -1
- package/dist/backend/llvm/js-ic.d.ts +1 -1
- package/dist/backend/llvm/js-ic.js +1 -1
- package/dist/backend/llvm/js-ic.js.map +1 -1
- package/dist/backend/llvm/key-orders.d.ts +7 -0
- package/dist/backend/llvm/key-orders.js +33 -0
- package/dist/backend/llvm/key-orders.js.map +1 -0
- package/dist/backend/llvm/lib-connect.js +4 -0
- package/dist/backend/llvm/lib-connect.js.map +1 -1
- package/dist/backend/llvm/lib-datagram.js +11 -0
- package/dist/backend/llvm/lib-datagram.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +90 -2
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +65 -4
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.d.ts +4 -0
- package/dist/backend/llvm/lib-http2.js +24 -17
- package/dist/backend/llvm/lib-http2.js.map +1 -1
- package/dist/backend/llvm/lib-lookup.js +16 -6
- package/dist/backend/llvm/lib-lookup.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +65 -14
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +126 -3
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +97 -30
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-tls.js +23 -0
- package/dist/backend/llvm/lib-tls.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +181 -64
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +28 -0
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
- package/dist/backend/llvm/loop-state.d.ts +33 -0
- package/dist/backend/llvm/loop-state.js +42 -0
- package/dist/backend/llvm/loop-state.js.map +1 -0
- package/dist/backend/llvm/map-number-lookup.d.ts +26 -8
- package/dist/backend/llvm/map-number-lookup.js +91 -31
- package/dist/backend/llvm/map-number-lookup.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.test.js +55 -0
- package/dist/backend/llvm/map-number-lookup.test.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.js +4 -2
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/nullable-unions.d.ts +2 -1
- package/dist/backend/llvm/nullable-unions.js +15 -3
- package/dist/backend/llvm/nullable-unions.js.map +1 -1
- package/dist/backend/llvm/publish.d.ts +18 -1
- package/dist/backend/llvm/publish.js +76 -25
- package/dist/backend/llvm/publish.js.map +1 -1
- package/dist/backend/llvm/publish.test.js +3 -0
- package/dist/backend/llvm/publish.test.js.map +1 -1
- package/dist/backend/llvm/receivers.js +7 -2
- package/dist/backend/llvm/receivers.js.map +1 -1
- package/dist/backend/llvm/record-results.d.ts +1 -9
- package/dist/backend/llvm/record-results.js +2 -11
- package/dist/backend/llvm/record-results.js.map +1 -1
- package/dist/backend/llvm/reference-writes.d.ts +7 -2
- package/dist/backend/llvm/reference-writes.js +91 -72
- package/dist/backend/llvm/reference-writes.js.map +1 -1
- package/dist/backend/llvm/regex-matchers.js +161 -14
- package/dist/backend/llvm/regex-matchers.js.map +1 -1
- package/dist/backend/llvm/regex-matchers.test.js +18 -0
- package/dist/backend/llvm/regex-matchers.test.js.map +1 -1
- package/dist/backend/llvm/running-extrema.d.ts +11 -0
- package/dist/backend/llvm/running-extrema.js +115 -0
- package/dist/backend/llvm/running-extrema.js.map +1 -0
- package/dist/backend/llvm/running-extrema.test.d.ts +1 -0
- package/dist/backend/llvm/running-extrema.test.js +89 -0
- package/dist/backend/llvm/running-extrema.test.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +79 -21
- package/dist/backend/llvm/shapes.js +233 -42
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +53 -7
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/speculative-integers.d.ts +6 -0
- package/dist/backend/llvm/speculative-integers.js +2 -2
- package/dist/backend/llvm/speculative-integers.js.map +1 -1
- package/dist/backend/llvm/stack-objects.d.ts +3 -2
- package/dist/backend/llvm/stack-objects.js +5 -2
- package/dist/backend/llvm/stack-objects.js.map +1 -1
- package/dist/backend/llvm/string-lifetimes.test.js +2 -1
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/string-reads.d.ts +15 -0
- package/dist/backend/llvm/string-reads.js +128 -0
- package/dist/backend/llvm/string-reads.js.map +1 -1
- package/dist/backend/llvm/walk-borrows.d.ts +3 -0
- package/dist/backend/llvm/walk-borrows.js +46 -41
- package/dist/backend/llvm/walk-borrows.js.map +1 -1
- package/dist/backend/llvm/walkers.d.ts +3 -0
- package/dist/backend/llvm/walkers.js +88 -65
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/llvm/wasm-modules.d.ts +6 -5
- package/dist/backend/llvm/wasm-modules.js +32 -9
- package/dist/backend/llvm/wasm-modules.js.map +1 -1
- package/dist/backend/llvm/wrapping-sums.d.ts +16 -1
- package/dist/backend/llvm/wrapping-sums.js +126 -0
- package/dist/backend/llvm/wrapping-sums.js.map +1 -1
- package/dist/backend/mangle.d.ts +3 -0
- package/dist/backend/mangle.js +5 -0
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/may-throw.d.ts +8 -10
- package/dist/backend/may-throw.js +14 -10
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +27 -4
- package/dist/backend/native/executable.js +31 -8
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/library.js +1 -0
- package/dist/backend/native/library.js.map +1 -1
- package/dist/backend/native/runtime-inputs.d.ts +1 -1
- package/dist/backend/native/runtime-inputs.js +1 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +11 -6
- package/dist/backend/native-codegen.js +36 -9
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +0 -23
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +18 -4
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/optimization.d.ts +2 -2
- package/dist/backend/publication.d.ts +12 -1
- package/dist/backend/publication.js +37 -14
- package/dist/backend/publication.js.map +1 -1
- package/dist/backend/publication.test.js +30 -0
- package/dist/backend/publication.test.js.map +1 -1
- package/dist/backend/result-slots.d.ts +16 -0
- package/dist/backend/result-slots.js +23 -0
- package/dist/backend/result-slots.js.map +1 -0
- 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 +2 -1
- package/dist/backend/runtime-pack-core.js +2 -1
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +5 -1
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.d.ts +0 -21
- package/dist/backend/runtime-pack.js +0 -29
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +10 -69
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/stack-observations.d.ts +2 -1
- package/dist/backend/stack-observations.js +67 -42
- package/dist/backend/stack-observations.js.map +1 -1
- package/dist/backend/target-diagnostics.js +33 -1
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/warm-cache.js +4 -0
- package/dist/backend/warm-cache.js.map +1 -1
- package/dist/cli/command.js +26 -6
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/usage.d.ts +5 -1
- package/dist/cli/usage.js +10 -5
- package/dist/cli/usage.js.map +1 -1
- package/dist/compat/fetch-profile.js +1 -1
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/contracts/check.js +5 -4
- package/dist/contracts/check.js.map +1 -1
- package/dist/contracts/int32-elements.js +10 -2
- package/dist/contracts/int32-elements.js.map +1 -1
- package/dist/coverage/report.d.ts +7 -2
- package/dist/coverage/report.js +30 -3
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/verdict-cache.d.ts +1 -0
- package/dist/coverage/verdict-cache.js +4 -0
- package/dist/coverage/verdict-cache.js.map +1 -1
- package/dist/coverage/verdict-semantic.js +4 -0
- package/dist/coverage/verdict-semantic.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +4 -0
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/dynamic-tier.d.ts +40 -0
- package/dist/diagnostics/dynamic-tier.js +57 -0
- package/dist/diagnostics/dynamic-tier.js.map +1 -0
- package/dist/diagnostics/envelope.d.ts +5 -1
- package/dist/diagnostics/envelope.js +6 -2
- package/dist/diagnostics/envelope.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +25 -1
- package/dist/executable/executable-cache.js +60 -7
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +46 -3
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.js +3 -1
- 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/decl-projection.d.ts +41 -0
- package/dist/frontend/decl-projection.js +854 -0
- package/dist/frontend/decl-projection.js.map +1 -0
- package/dist/frontend/decl-projection.test.d.ts +1 -0
- package/dist/frontend/decl-projection.test.js +30 -0
- package/dist/frontend/decl-projection.test.js.map +1 -0
- package/dist/frontend/dispose-hook.d.ts +2 -0
- package/dist/frontend/dispose-hook.js +14 -0
- package/dist/frontend/dispose-hook.js.map +1 -0
- package/dist/frontend/dts-paths.d.ts +15 -0
- package/dist/frontend/dts-paths.js +25 -0
- package/dist/frontend/dts-paths.js.map +1 -1
- package/dist/frontend/input-tracker.d.ts +6 -0
- package/dist/frontend/input-tracker.js +51 -28
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +19 -0
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/jsx-entities.d.ts +4 -0
- package/dist/frontend/jsx-entities.js +259 -0
- package/dist/frontend/jsx-entities.js.map +1 -0
- package/dist/frontend/jsx-source.d.ts +71 -0
- package/dist/frontend/jsx-source.js +781 -0
- package/dist/frontend/jsx-source.js.map +1 -0
- package/dist/frontend/jsx-source.test.d.ts +1 -0
- package/dist/frontend/jsx-source.test.js +200 -0
- package/dist/frontend/jsx-source.test.js.map +1 -0
- package/dist/frontend/literal-values.test.js +8 -9
- package/dist/frontend/literal-values.test.js.map +1 -1
- package/dist/frontend/lowering/array-indexed-mutation.js +2 -1
- package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
- package/dist/frontend/lowering/array-values.js +103 -4
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/binding-analysis.d.ts +1 -1
- package/dist/frontend/lowering/binding-analysis.js +2 -2
- package/dist/frontend/lowering/binding-analysis.js.map +1 -1
- package/dist/frontend/lowering/builtins/arguments.d.ts +3 -0
- package/dist/frontend/lowering/builtins/arguments.js +30 -15
- package/dist/frontend/lowering/builtins/arguments.js.map +1 -1
- package/dist/frontend/lowering/builtins/atomics.js +10 -6
- package/dist/frontend/lowering/builtins/atomics.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-async.js +2 -1
- package/dist/frontend/lowering/builtins/child-process-async.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-methods.js +46 -15
- package/dist/frontend/lowering/builtins/child-process-methods.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-sync.js +2 -1
- package/dist/frontend/lowering/builtins/child-process-sync.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process.js +13 -2
- package/dist/frontend/lowering/builtins/child-process.js.map +1 -1
- package/dist/frontend/lowering/builtins/crypto.d.ts +4 -2
- package/dist/frontend/lowering/builtins/crypto.js +136 -5
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
- package/dist/frontend/lowering/builtins/date-classes.d.ts +46 -0
- package/dist/frontend/lowering/builtins/date-classes.js +477 -0
- package/dist/frontend/lowering/builtins/date-classes.js.map +1 -0
- package/dist/frontend/lowering/builtins/dates.d.ts +11 -1
- package/dist/frontend/lowering/builtins/dates.js +55 -26
- package/dist/frontend/lowering/builtins/dates.js.map +1 -1
- package/dist/frontend/lowering/builtins/dh.d.ts +15 -0
- package/dist/frontend/lowering/builtins/dh.js +151 -0
- package/dist/frontend/lowering/builtins/dh.js.map +1 -0
- package/dist/frontend/lowering/builtins/disposable-stack.js +2 -1
- package/dist/frontend/lowering/builtins/disposable-stack.js.map +1 -1
- package/dist/frontend/lowering/builtins/ecdh.d.ts +12 -1
- package/dist/frontend/lowering/builtins/ecdh.js +7 -7
- package/dist/frontend/lowering/builtins/ecdh.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.d.ts +15 -0
- package/dist/frontend/lowering/builtins/errors.js +110 -0
- package/dist/frontend/lowering/builtins/errors.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.js +23 -17
- package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem.js +6 -4
- package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
- package/dist/frontend/lowering/builtins/fs-paths.d.ts +15 -0
- package/dist/frontend/lowering/builtins/fs-paths.js +209 -0
- package/dist/frontend/lowering/builtins/fs-paths.js.map +1 -0
- package/dist/frontend/lowering/builtins/global-namespace-keys.d.ts +3 -0
- package/dist/frontend/lowering/builtins/global-namespace-keys.js +122 -0
- package/dist/frontend/lowering/builtins/global-namespace-keys.js.map +1 -0
- package/dist/frontend/lowering/builtins/hash-stream.d.ts +16 -4
- package/dist/frontend/lowering/builtins/hash-stream.js +86 -23
- package/dist/frontend/lowering/builtins/hash-stream.js.map +1 -1
- package/dist/frontend/lowering/builtins/json.js +2 -1
- package/dist/frontend/lowering/builtins/json.js.map +1 -1
- package/dist/frontend/lowering/builtins/key-object.d.ts +2 -1
- package/dist/frontend/lowering/builtins/key-object.js +20 -7
- package/dist/frontend/lowering/builtins/key-object.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-calls.js +11 -4
- package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/numbers.js +18 -6
- package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
- package/dist/frontend/lowering/builtins/operating-system.js +4 -3
- package/dist/frontend/lowering/builtins/operating-system.js.map +1 -1
- package/dist/frontend/lowering/builtins/performance.js +3 -2
- package/dist/frontend/lowering/builtins/performance.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.js +3 -2
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/builtins/promises.d.ts +6 -0
- package/dist/frontend/lowering/builtins/promises.js +91 -4
- package/dist/frontend/lowering/builtins/promises.js.map +1 -1
- package/dist/frontend/lowering/builtins/promisify-callback.js +2 -1
- package/dist/frontend/lowering/builtins/promisify-callback.js.map +1 -1
- package/dist/frontend/lowering/builtins/readline.d.ts +7 -2
- package/dist/frontend/lowering/builtins/readline.js +58 -9
- package/dist/frontend/lowering/builtins/readline.js.map +1 -1
- package/dist/frontend/lowering/builtins/strings.js +13 -5
- package/dist/frontend/lowering/builtins/strings.js.map +1 -1
- package/dist/frontend/lowering/builtins/text-codecs.js +2 -1
- package/dist/frontend/lowering/builtins/text-codecs.js.map +1 -1
- package/dist/frontend/lowering/builtins/timers.js +1 -1
- package/dist/frontend/lowering/builtins/timers.js.map +1 -1
- package/dist/frontend/lowering/builtins/url.js +28 -4
- package/dist/frontend/lowering/builtins/url.js.map +1 -1
- package/dist/frontend/lowering/builtins/v8.js +2 -1
- package/dist/frontend/lowering/builtins/v8.js.map +1 -1
- package/dist/frontend/lowering/builtins/webassembly.js +6 -3
- package/dist/frontend/lowering/builtins/webassembly.js.map +1 -1
- package/dist/frontend/lowering/builtins/webcrypto.js +39 -20
- package/dist/frontend/lowering/builtins/webcrypto.js.map +1 -1
- package/dist/frontend/lowering/call-arguments.js +2 -1
- package/dist/frontend/lowering/call-arguments.js.map +1 -1
- package/dist/frontend/lowering/call-signatures.js +13 -6
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/caught-value-dispatch.d.ts +18 -1
- package/dist/frontend/lowering/caught-value-dispatch.js +201 -32
- package/dist/frontend/lowering/caught-value-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-assertions.js +3 -2
- package/dist/frontend/lowering/class-assertions.js.map +1 -1
- package/dist/frontend/lowering/class-callbacks.d.ts +5 -2
- package/dist/frontend/lowering/class-callbacks.js +82 -12
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-construction.d.ts +6 -2
- package/dist/frontend/lowering/class-construction.js +25 -16
- package/dist/frontend/lowering/class-construction.js.map +1 -1
- package/dist/frontend/lowering/class-descriptors.js +1 -1
- package/dist/frontend/lowering/class-descriptors.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +73 -2
- package/dist/frontend/lowering/class-dynamic-dispatch.js +1334 -259
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +124 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
- package/dist/frontend/lowering/class-iterables.d.ts +2 -1
- package/dist/frontend/lowering/class-iterables.js +9 -1
- package/dist/frontend/lowering/class-iterables.js.map +1 -1
- package/dist/frontend/lowering/class-method-mutations.js +35 -9
- package/dist/frontend/lowering/class-method-mutations.js.map +1 -1
- package/dist/frontend/lowering/class-method-values.js +1 -1
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-protocols.d.ts +7 -0
- package/dist/frontend/lowering/class-protocols.js +64 -4
- package/dist/frontend/lowering/class-protocols.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.d.ts +5 -0
- package/dist/frontend/lowering/class-prototypes.js +67 -5
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-runtime-statics.d.ts +9 -3
- package/dist/frontend/lowering/class-runtime-statics.js +29 -4
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
- package/dist/frontend/lowering/class-to-primitive.js +25 -5
- package/dist/frontend/lowering/class-to-primitive.js.map +1 -1
- package/dist/frontend/lowering/class-unions.js +2 -1
- package/dist/frontend/lowering/class-unions.js.map +1 -1
- package/dist/frontend/lowering/coercions/function-adapters.js +6 -5
- package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural-plans.js +48 -1
- package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural.js +99 -8
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/coercions/unions.js +8 -7
- package/dist/frontend/lowering/coercions/unions.js.map +1 -1
- package/dist/frontend/lowering/collection-ingestion.js +2 -1
- package/dist/frontend/lowering/collection-ingestion.js.map +1 -1
- package/dist/frontend/lowering/containers/array-callback-call.js +2 -2
- package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.d.ts +7 -0
- package/dist/frontend/lowering/containers/array-callbacks.js +352 -31
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-concat.js +12 -1
- package/dist/frontend/lowering/containers/array-concat.js.map +1 -1
- package/dist/frontend/lowering/containers/array-construction.js +25 -4
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.js +21 -5
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/array-pipelines.js +21 -9
- package/dist/frontend/lowering/containers/array-pipelines.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.d.ts +1 -1
- package/dist/frontend/lowering/containers/bytes.js +131 -29
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.js +55 -2
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-grouping.js +3 -2
- package/dist/frontend/lowering/containers/collection-grouping.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +15 -9
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/filter-predicates.d.ts +6 -0
- package/dist/frontend/lowering/containers/filter-predicates.js +205 -0
- package/dist/frontend/lowering/containers/filter-predicates.js.map +1 -0
- package/dist/frontend/lowering/containers/indexed-objects.d.ts +0 -12
- package/dist/frontend/lowering/containers/indexed-objects.js +54 -14
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/containers/iterator-helpers.d.ts +32 -1
- package/dist/frontend/lowering/containers/iterator-helpers.js +6 -5
- package/dist/frontend/lowering/containers/iterator-helpers.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +87 -14
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.js +45 -20
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -1
- package/dist/frontend/lowering/cycle-initialization.js +25 -4
- package/dist/frontend/lowering/cycle-initialization.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.d.ts +18 -1
- package/dist/frontend/lowering/deferred-module-initializers.js +226 -115
- package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.test.js +28 -0
- package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -1
- package/dist/frontend/lowering/dispatch-sites.d.ts +59 -0
- package/dist/frontend/lowering/dispatch-sites.js +218 -0
- package/dist/frontend/lowering/dispatch-sites.js.map +1 -0
- package/dist/frontend/lowering/dispatch-sites.test.d.ts +1 -0
- package/dist/frontend/lowering/dispatch-sites.test.js +59 -0
- package/dist/frontend/lowering/dispatch-sites.test.js.map +1 -0
- package/dist/frontend/lowering/divergences.js +9 -1
- package/dist/frontend/lowering/divergences.js.map +1 -1
- package/dist/frontend/lowering/dyn-streams.d.ts +3 -0
- package/dist/frontend/lowering/dyn-streams.js +1 -1
- package/dist/frontend/lowering/dyn-streams.js.map +1 -1
- package/dist/frontend/lowering/dynamic-tier.d.ts +25 -0
- package/dist/frontend/lowering/dynamic-tier.js +327 -0
- package/dist/frontend/lowering/dynamic-tier.js.map +1 -0
- package/dist/frontend/lowering/error-methods.js +51 -2
- package/dist/frontend/lowering/error-methods.js.map +1 -1
- package/dist/frontend/lowering/expressions/array-literals.js +62 -0
- package/dist/frontend/lowering/expressions/array-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/binary.js +81 -5
- package/dist/frontend/lowering/expressions/binary.js.map +1 -1
- package/dist/frontend/lowering/expressions/element-access.js +107 -14
- package/dist/frontend/lowering/expressions/element-access.js.map +1 -1
- package/dist/frontend/lowering/expressions/identifiers.js +79 -11
- package/dist/frontend/lowering/expressions/identifiers.js.map +1 -1
- package/dist/frontend/lowering/expressions/narrowing.js +130 -6
- package/dist/frontend/lowering/expressions/narrowing.js.map +1 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js +3 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.d.ts +10 -3
- package/dist/frontend/lowering/expressions/object-literals.js +164 -56
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.js +17 -5
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/property-access.d.ts +0 -4
- package/dist/frontend/lowering/expressions/property-access.js +211 -17
- package/dist/frontend/lowering/expressions/property-access.js.map +1 -1
- package/dist/frontend/lowering/expressions/relational.js +267 -30
- package/dist/frontend/lowering/expressions/relational.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-fields.js +4 -0
- package/dist/frontend/lowering/expressions/union-fields.js.map +1 -1
- package/dist/frontend/lowering/expressions/updates.js +85 -12
- package/dist/frontend/lowering/expressions/updates.js.map +1 -1
- package/dist/frontend/lowering/frozen-records.d.ts +28 -0
- package/dist/frontend/lowering/frozen-records.js +322 -0
- package/dist/frontend/lowering/frozen-records.js.map +1 -0
- package/dist/frontend/lowering/function-returns.js +49 -0
- package/dist/frontend/lowering/function-returns.js.map +1 -1
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +6 -1
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +20 -30
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/generic-functions.d.ts +42 -1
- package/dist/frontend/lowering/generic-functions.js +455 -20
- package/dist/frontend/lowering/generic-functions.js.map +1 -1
- package/dist/frontend/lowering/intern-tables.js +2 -1
- package/dist/frontend/lowering/intern-tables.js.map +1 -1
- package/dist/frontend/lowering/iterable-values.d.ts +49 -0
- package/dist/frontend/lowering/iterable-values.js +297 -0
- package/dist/frontend/lowering/iterable-values.js.map +1 -0
- package/dist/frontend/lowering/iterator-adapters.js +195 -9
- package/dist/frontend/lowering/iterator-adapters.js.map +1 -1
- package/dist/frontend/lowering/js-class-fields.d.ts +8 -0
- package/dist/frontend/lowering/js-class-fields.js +45 -10
- package/dist/frontend/lowering/js-class-fields.js.map +1 -1
- package/dist/frontend/lowering/js-dynamic-objects.js +3 -2
- package/dist/frontend/lowering/js-dynamic-objects.js.map +1 -1
- package/dist/frontend/lowering/json-require.js +2 -1
- package/dist/frontend/lowering/json-require.js.map +1 -1
- package/dist/frontend/lowering/key-order-witness.d.ts +24 -4
- package/dist/frontend/lowering/key-order-witness.js +790 -25
- package/dist/frontend/lowering/key-order-witness.js.map +1 -1
- package/dist/frontend/lowering/key-order-witness.test.js +466 -10
- package/dist/frontend/lowering/key-order-witness.test.js.map +1 -1
- package/dist/frontend/lowering/lifetime-regions.js +2 -1
- package/dist/frontend/lowering/lifetime-regions.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +6 -5
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js +7 -2
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +11 -0
- package/dist/frontend/lowering/lower-calls.js +776 -126
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +29 -2
- package/dist/frontend/lowering/lower-classes.js +581 -46
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.js +6 -3
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.d.ts +14 -0
- package/dist/frontend/lowering/lower-event-emitter.js +267 -20
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +19 -2
- package/dist/frontend/lowering/lower-exprs.js +126 -13
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.d.ts +11 -0
- package/dist/frontend/lowering/lower-functions.js +387 -72
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.js +41 -31
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.js +6 -3
- package/dist/frontend/lowering/lower-global-value.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +28 -12
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +2 -1
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-mock.js +2 -1
- package/dist/frontend/lowering/lower-mock.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +47 -5
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.js +2 -2
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +2 -1
- package/dist/frontend/lowering/lower-namespaces.js +9 -4
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +10 -0
- package/dist/frontend/lowering/lower-server.js +239 -61
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stdlib.d.ts +5 -0
- package/dist/frontend/lowering/lower-stdlib.js +42 -10
- package/dist/frontend/lowering/lower-stdlib.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +23 -0
- package/dist/frontend/lowering/lower-stmts.js +622 -68
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.test.js +1 -1
- package/dist/frontend/lowering/lower-stmts.test.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +20 -2
- package/dist/frontend/lowering/lower-stream.js +2055 -318
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-timers.js +4 -3
- package/dist/frontend/lowering/lower-timers.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +197 -29
- package/dist/frontend/lowering/lowerer.js +862 -84
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +21 -9
- package/dist/frontend/lowering/lowerer.test.js.map +1 -1
- package/dist/frontend/lowering/module-namespace-elements.d.ts +11 -1
- package/dist/frontend/lowering/module-namespace-elements.js +82 -5
- package/dist/frontend/lowering/module-namespace-elements.js.map +1 -1
- package/dist/frontend/lowering/narrowing-stability.js +5 -0
- package/dist/frontend/lowering/narrowing-stability.js.map +1 -1
- package/dist/frontend/lowering/native-ffi.js +1 -1
- package/dist/frontend/lowering/native-ffi.js.map +1 -1
- package/dist/frontend/lowering/new-target.d.ts +12 -0
- package/dist/frontend/lowering/new-target.js +280 -0
- package/dist/frontend/lowering/new-target.js.map +1 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js +2 -1
- package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.js +2 -1
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
- package/dist/frontend/lowering/private-brands.d.ts +9 -0
- package/dist/frontend/lowering/private-brands.js +66 -15
- package/dist/frontend/lowering/private-brands.js.map +1 -1
- package/dist/frontend/lowering/promise-executor-adapter.js +2 -1
- package/dist/frontend/lowering/promise-executor-adapter.js.map +1 -1
- package/dist/frontend/lowering/require-initialization.js +2 -1
- package/dist/frontend/lowering/require-initialization.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-elements.d.ts +5 -0
- package/dist/frontend/lowering/runtime-optional-elements.js +17 -1
- package/dist/frontend/lowering/runtime-optional-elements.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-records.d.ts +2 -0
- package/dist/frontend/lowering/runtime-optional-records.js +18 -5
- package/dist/frontend/lowering/runtime-optional-records.js.map +1 -1
- package/dist/frontend/lowering/site-dependencies.d.ts +35 -0
- package/dist/frontend/lowering/site-dependencies.js +84 -0
- package/dist/frontend/lowering/site-dependencies.js.map +1 -0
- package/dist/frontend/lowering/site-dependencies.test.d.ts +1 -0
- package/dist/frontend/lowering/site-dependencies.test.js +53 -0
- package/dist/frontend/lowering/site-dependencies.test.js.map +1 -0
- package/dist/frontend/lowering/stable-names.d.ts +11 -0
- package/dist/frontend/lowering/stable-names.js +35 -0
- package/dist/frontend/lowering/stable-names.js.map +1 -0
- package/dist/frontend/lowering/static-typeof.d.ts +2 -2
- package/dist/frontend/lowering/static-typeof.js +42 -3
- package/dist/frontend/lowering/static-typeof.js.map +1 -1
- package/dist/frontend/lowering/strict-equality.js +2 -1
- package/dist/frontend/lowering/strict-equality.js.map +1 -1
- package/dist/frontend/lowering/structural-positions.d.ts +32 -0
- package/dist/frontend/lowering/structural-positions.js +108 -0
- package/dist/frontend/lowering/structural-positions.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +3 -0
- package/dist/frontend/lowering/surfaces.js +60 -32
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/undefined-index.d.ts +27 -0
- package/dist/frontend/lowering/undefined-index.js +82 -0
- package/dist/frontend/lowering/undefined-index.js.map +1 -0
- package/dist/frontend/lowering/var-hoisting.js +66 -16
- package/dist/frontend/lowering/var-hoisting.js.map +1 -1
- package/dist/frontend/lowering/width-lift.d.ts +18 -0
- package/dist/frontend/npm-static-bundled-chunks.js +9 -11
- package/dist/frontend/npm-static-bundled-chunks.js.map +1 -1
- package/dist/frontend/npm-static-bundled-chunks.test.js +6 -5
- package/dist/frontend/npm-static-bundled-chunks.test.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-syntax.js +9 -1
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -1
- package/dist/frontend/npm-static-tsc-helpers.d.ts +5 -0
- package/dist/frontend/npm-static-tsc-helpers.js +106 -0
- package/dist/frontend/npm-static-tsc-helpers.js.map +1 -0
- package/dist/frontend/npm-static-tsc-helpers.test.d.ts +1 -0
- package/dist/frontend/npm-static-tsc-helpers.test.js +58 -0
- package/dist/frontend/npm-static-tsc-helpers.test.js.map +1 -0
- package/dist/frontend/npm-static-type-exports-host.d.ts +8 -0
- package/dist/frontend/npm-static-type-exports-host.js +214 -0
- package/dist/frontend/npm-static-type-exports-host.js.map +1 -0
- package/dist/frontend/npm-static-type-exports-host.test.d.ts +1 -0
- package/dist/frontend/npm-static-type-exports-host.test.js +53 -0
- package/dist/frontend/npm-static-type-exports-host.test.js.map +1 -0
- package/dist/frontend/npm-static-type-exports.d.ts +52 -0
- package/dist/frontend/npm-static-type-exports.js +261 -0
- package/dist/frontend/npm-static-type-exports.js.map +1 -0
- package/dist/frontend/npm-static-type-exports.test.d.ts +1 -0
- package/dist/frontend/npm-static-type-exports.test.js +103 -0
- package/dist/frontend/npm-static-type-exports.test.js.map +1 -0
- package/dist/frontend/npm-static-umd.d.ts +6 -0
- package/dist/frontend/npm-static-umd.js +203 -0
- package/dist/frontend/npm-static-umd.js.map +1 -0
- package/dist/frontend/npm-static-umd.test.d.ts +1 -0
- package/dist/frontend/npm-static-umd.test.js +105 -0
- package/dist/frontend/npm-static-umd.test.js.map +1 -0
- package/dist/frontend/npm-static.d.ts +8 -0
- package/dist/frontend/npm-static.js +51 -22
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/package-shims.d.ts +3 -0
- package/dist/frontend/package-shims.js +71 -8
- package/dist/frontend/package-shims.js.map +1 -1
- package/dist/frontend/pipeline.js +18 -10
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/process-fork.d.ts +25 -0
- package/dist/frontend/process-fork.js +2 -0
- package/dist/frontend/process-fork.js.map +1 -0
- package/dist/frontend/program.d.ts +21 -1
- package/dist/frontend/program.js +586 -74
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +44 -4
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/services.d.ts +6 -0
- package/dist/frontend/services.js +18 -0
- package/dist/frontend/services.js.map +1 -1
- package/dist/frontend/token-equivalence.d.ts +3 -0
- package/dist/frontend/token-equivalence.js +409 -0
- package/dist/frontend/token-equivalence.js.map +1 -0
- package/dist/frontend/token-equivalence.test.d.ts +1 -0
- package/dist/frontend/token-equivalence.test.js +67 -0
- package/dist/frontend/token-equivalence.test.js.map +1 -0
- package/dist/frontend/ts7/ast-node.d.ts +43 -7
- package/dist/frontend/ts7/ast-node.js +1176 -129
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-node.test.js +84 -0
- package/dist/frontend/ts7/ast-node.test.js.map +1 -1
- package/dist/frontend/ts7/ast-wire.d.ts +29 -3
- package/dist/frontend/ts7/ast-wire.js +144 -31
- package/dist/frontend/ts7/ast-wire.js.map +1 -1
- package/dist/frontend/ts7/ast-wire.test.js +23 -0
- package/dist/frontend/ts7/ast-wire.test.js.map +1 -1
- package/dist/frontend/ts7/ast.d.ts +23 -2
- package/dist/frontend/ts7/ast.js +143 -2
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/checker-backend.d.ts +3 -4
- package/dist/frontend/ts7/checker-backend.js +2 -2
- package/dist/frontend/ts7/checker-backend.js.map +1 -1
- package/dist/frontend/ts7/checker-backend.test.js +5 -9
- package/dist/frontend/ts7/checker-backend.test.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +17 -1
- package/dist/frontend/ts7/checker.js +82 -1
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.js +9 -6
- package/dist/frontend/ts7/checker.test.js.map +1 -1
- package/dist/frontend/ts7/enums.d.ts +3 -3
- package/dist/frontend/ts7/enums.generated.d.ts +10 -0
- package/dist/frontend/ts7/enums.generated.js +21 -0
- package/dist/frontend/ts7/enums.generated.js.map +1 -1
- package/dist/frontend/ts7/enums.js +19 -0
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/lib-diagnostics.d.ts +24 -0
- package/dist/frontend/ts7/lib-diagnostics.js +307 -0
- package/dist/frontend/ts7/lib-diagnostics.js.map +1 -0
- package/dist/frontend/ts7/lib-diagnostics.test.d.ts +1 -0
- package/dist/frontend/ts7/lib-diagnostics.test.js +199 -0
- package/dist/frontend/ts7/lib-diagnostics.test.js.map +1 -0
- package/dist/frontend/ts7/program-host.d.ts +7 -0
- package/dist/frontend/ts7/program-host.js +30 -4
- package/dist/frontend/ts7/program-host.js.map +1 -1
- package/dist/frontend/ts7/semantic-checker.d.ts +10 -0
- package/dist/frontend/ts7/semantic-checker.js +25 -20
- package/dist/frontend/ts7/semantic-checker.js.map +1 -1
- package/dist/frontend/ts7/semantic-json.d.ts +13 -0
- package/dist/frontend/ts7/semantic-json.js +146 -0
- package/dist/frontend/ts7/semantic-json.js.map +1 -1
- package/dist/frontend/ts7/semantic-json.test.js +57 -1
- package/dist/frontend/ts7/semantic-json.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.d.ts +15 -0
- package/dist/frontend/ts7/semantic-model.js +67 -19
- package/dist/frontend/ts7/semantic-model.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.test.js +3 -2
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -1
- package/dist/frontend/ts7/session.d.ts +14 -1
- package/dist/frontend/ts7/session.js +23 -1
- package/dist/frontend/ts7/session.js.map +1 -1
- package/dist/frontend/tsc-codes.d.ts +1 -1
- package/dist/frontend/tsc-codes.js +7 -0
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +51 -7
- package/dist/frontend/type-mapper.js +456 -43
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +1 -1
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/frontend-process-args.d.ts +4 -0
- package/dist/frontend-process-args.js +52 -0
- package/dist/frontend-process-args.js.map +1 -0
- package/dist/frontend-process-args.test.d.ts +1 -0
- package/dist/frontend-process-args.test.js +47 -0
- package/dist/frontend-process-args.test.js.map +1 -0
- package/dist/frontend-process.d.ts +1 -0
- package/dist/frontend-process.js +23 -0
- package/dist/frontend-process.js.map +1 -0
- package/dist/heap-collection.d.ts +16 -0
- package/dist/heap-collection.js +42 -0
- package/dist/heap-collection.js.map +1 -0
- package/dist/heap-collection.test.d.ts +1 -0
- package/dist/heap-collection.test.js +59 -0
- package/dist/heap-collection.test.js.map +1 -0
- package/dist/heap-pressure.d.ts +2 -0
- package/dist/heap-pressure.js +12 -0
- package/dist/heap-pressure.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +435 -89
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js +5 -3
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/array-length-stability.d.ts +4 -0
- package/dist/ir/array-length-stability.js +26 -6
- package/dist/ir/array-length-stability.js.map +1 -1
- package/dist/ir/array-length-stability.test.js +49 -0
- package/dist/ir/array-length-stability.test.js.map +1 -1
- package/dist/ir/builtin-effects.d.ts +7 -0
- package/dist/ir/builtin-effects.js +80 -0
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +7 -1
- package/dist/ir/builtin-signatures.js +303 -21
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/callback-specialization.d.ts +2 -1
- package/dist/ir/callback-specialization.js +23 -18
- package/dist/ir/callback-specialization.js.map +1 -1
- package/dist/ir/char-unit-locals.d.ts +19 -0
- package/dist/ir/char-unit-locals.js +185 -0
- package/dist/ir/char-unit-locals.js.map +1 -0
- package/dist/ir/char-unit-locals.test.d.ts +1 -0
- package/dist/ir/char-unit-locals.test.js +94 -0
- package/dist/ir/char-unit-locals.test.js.map +1 -0
- package/dist/ir/final-fields.d.ts +3 -1
- package/dist/ir/final-fields.js +15 -17
- package/dist/ir/final-fields.js.map +1 -1
- package/dist/ir/function-references.d.ts +2 -0
- package/dist/ir/function-references.js +2 -0
- package/dist/ir/function-references.js.map +1 -1
- package/dist/ir/function-references.test.js +5 -0
- package/dist/ir/function-references.test.js.map +1 -1
- package/dist/ir/initializer-bindings.d.ts +2 -1
- package/dist/ir/initializer-bindings.js +27 -20
- package/dist/ir/initializer-bindings.js.map +1 -1
- package/dist/ir/int32-arrays.d.ts +108 -0
- package/dist/ir/int32-arrays.js +831 -0
- package/dist/ir/int32-arrays.js.map +1 -0
- package/dist/ir/int32-slots.d.ts +36 -6
- package/dist/ir/int32-slots.js +370 -171
- package/dist/ir/int32-slots.js.map +1 -1
- package/dist/ir/int32-slots.test.js +3 -1
- package/dist/ir/int32-slots.test.js.map +1 -1
- package/dist/ir/integer-loop-facts.d.ts +9 -4
- package/dist/ir/integer-loop-facts.js +93 -18
- package/dist/ir/integer-loop-facts.js.map +1 -1
- package/dist/ir/integer-loops.d.ts +49 -0
- package/dist/ir/integer-loops.js +202 -40
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-loops.test.js +211 -1
- package/dist/ir/integer-loops.test.js.map +1 -1
- package/dist/ir/integer-ranges.d.ts +5 -0
- package/dist/ir/integer-ranges.js +125 -12
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/integer-ranges.test.js +94 -0
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/ir.d.ts +87 -9
- package/dist/ir/ir.js +61 -2
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +21 -1
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/js-ic.d.ts +19 -2
- package/dist/ir/js-ic.js +95 -11
- package/dist/ir/js-ic.js.map +1 -1
- package/dist/ir/js-ic.test.js +188 -0
- package/dist/ir/js-ic.test.js.map +1 -1
- package/dist/ir/node-index.d.ts +57 -0
- package/dist/ir/node-index.js +215 -0
- package/dist/ir/node-index.js.map +1 -0
- package/dist/ir/paired-while-loops.d.ts +25 -0
- package/dist/ir/paired-while-loops.js +335 -0
- package/dist/ir/paired-while-loops.js.map +1 -0
- package/dist/ir/paired-while-loops.test.d.ts +1 -0
- package/dist/ir/paired-while-loops.test.js +163 -0
- package/dist/ir/paired-while-loops.test.js.map +1 -0
- package/dist/ir/parameter-versions.d.ts +25 -0
- package/dist/ir/parameter-versions.js +300 -0
- package/dist/ir/parameter-versions.js.map +1 -0
- package/dist/ir/runtime-features.d.ts +60 -15
- package/dist/ir/runtime-features.js +276 -35
- package/dist/ir/runtime-features.js.map +1 -1
- package/dist/ir/serialize.d.ts +12 -2
- package/dist/ir/serialize.js +16 -3
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.js +17 -0
- package/dist/ir/serialize.test.js.map +1 -1
- package/dist/ir/tiers.js +1 -0
- package/dist/ir/tiers.js.map +1 -1
- package/dist/ir/traverse.d.ts +2 -0
- package/dist/ir/traverse.js +29 -5
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +171 -45
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/ir-policy.js +12 -0
- package/dist/library/ir-policy.js.map +1 -1
- package/dist/library/library-cache.d.ts +2 -0
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/prepare.js +2 -0
- package/dist/library/prepare.js.map +1 -1
- package/dist/native/cache.d.ts +6 -1
- package/dist/native/cache.js +28 -5
- package/dist/native/cache.js.map +1 -1
- package/dist/native/cache.test.js +16 -2
- package/dist/native/cache.test.js.map +1 -1
- package/dist/native/cli.js +26 -1
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.js +8 -6
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/executable-cache.d.ts +1 -1
- package/dist/native/executable-cache.js +2 -2
- package/dist/native/executable-cache.js.map +1 -1
- package/dist/native/prepare.d.ts +3 -1
- package/dist/native/prepare.js +123 -31
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/prepare.test.js +78 -18
- package/dist/native/prepare.test.js.map +1 -1
- package/dist/native/sanitizer.test.js +6 -1
- package/dist/native/sanitizer.test.js.map +1 -1
- package/dist/native/text-file.d.ts +13 -3
- package/dist/native/text-file.js +63 -9
- package/dist/native/text-file.js.map +1 -1
- package/dist/native/text-file.test.d.ts +1 -0
- package/dist/native/text-file.test.js +49 -0
- package/dist/native/text-file.test.js.map +1 -0
- package/dist/native/toolchain.js +4 -4
- package/dist/native/toolchain.js.map +1 -1
- package/dist/native/toolchain.test.js +3 -3
- package/dist/native/toolchain.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/dist/text-parts.d.ts +7 -0
- package/dist/text-parts.js +44 -0
- package/dist/text-parts.js.map +1 -1
- package/dist/text-parts.test.d.ts +1 -0
- package/dist/text-parts.test.js +46 -0
- package/dist/text-parts.test.js.map +1 -0
- package/dist/timing.d.ts +9 -2
- package/dist/timing.js +7 -4
- package/dist/timing.js.map +1 -1
- package/dist/wasm/translate.d.ts +4 -0
- package/dist/wasm/translate.js +2 -2
- package/dist/wasm/translate.js.map +1 -1
- package/package.json +21 -21
- package/shims/chalk/v5.ts +688 -0
- package/shims/hono-node-server/v2.ts +645 -0
- package/shims/hot-shots/client.ts +1126 -0
- package/shims/hot-shots/v8-unix-dgram.ts +8 -0
- package/shims/hot-shots/v8.ts +8 -0
- package/shims/undici/core/client.ts +4 -4
- package/surface-manifest.json +44 -52
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { relieveHeapPressure } from "../../heap-pressure.js";
|
|
1
2
|
import { wasmBoundsChecks } from "./wasm-modules.js";
|
|
2
3
|
import { jsTruthy } from "./jsval.js";
|
|
3
4
|
import { JsIcSites } from "../../ir/js-ic.js";
|
|
@@ -12,20 +13,23 @@ import { createHash } from "node:crypto";
|
|
|
12
13
|
import { endsWithJump, matchFieldSelfConcat, readsArraySlot, streamTypedRefEligible, undefinedArmTag, } from "../../ir/analysis.js";
|
|
13
14
|
import { loopTestsEveryIteration } from "../loop-polls.js";
|
|
14
15
|
import { isDynTypedRefType, isRefCounted, isUnitType, POINTER_KINDS, RUNTIME_EMITTER_CLASS, RUNTIME_EVENT_CLASS, RUNTIME_EVENT_TARGET_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, typeEquals, typeKey, VOID, classJsName, } from "../../ir/ir.js";
|
|
15
|
-
import { moduleRuntimeFeatures
|
|
16
|
+
import { moduleRuntimeFeatures } from "../../ir/runtime-features.js";
|
|
16
17
|
import { captureFreeFunctions, observesStacks } from "../stack-observations.js";
|
|
17
|
-
import {} from "./dense-array-loops.js";
|
|
18
18
|
import { findInitializedByteLoopBindings } from "./byte-windows.js";
|
|
19
19
|
import { matchBytesLoopVersion } from "./bytes-loop-versions.js";
|
|
20
20
|
import { globalSlotAlias } from "./bytes-alias.js";
|
|
21
21
|
import { materializeSplitPiece, } from "./split-loops.js";
|
|
22
22
|
import { scalarizeNumericRecords } from "../../ir/scalar-records.js";
|
|
23
|
-
import { addRecordResultEntries } from "./record-results.js";
|
|
23
|
+
import { addRecordResultEntries, resultEntryName } from "./record-results.js";
|
|
24
24
|
import { specializeCallbackCalls } from "../../ir/callback-specialization.js";
|
|
25
|
+
import { EmitJournal, registerReplay, renameChunk, replayJournal, } from "./emit-journal.js";
|
|
25
26
|
import { specializeNumericCalls } from "../../ir/numeric-call-specialization.js";
|
|
27
|
+
import { versionLoopBoundParameters } from "../../ir/parameter-versions.js";
|
|
28
|
+
import { allocatedLiteral, fillAllocationLength, int32ArrayKey, selectInt32Arrays, } from "../../ir/int32-arrays.js";
|
|
26
29
|
import { everyExpr, everyExprChild, everyStmtChild, everyStmtList } from "../../ir/traverse.js";
|
|
27
|
-
import { INT32_RANGE } from "../../ir/integer-ranges.js";
|
|
30
|
+
import { INT32_RANGE, withinInt32, } from "../../ir/integer-ranges.js";
|
|
28
31
|
import { unshareNodes } from "../../ir/unshare.js";
|
|
32
|
+
import { runPairedWhileLoopsAsFor } from "../../ir/paired-while-loops.js";
|
|
29
33
|
import { copyStableCaptures } from "../../ir/capture-values.js";
|
|
30
34
|
import { resolveSelfCaptures } from "../../ir/self-captures.js";
|
|
31
35
|
import { analyzeInt32Slots, dynamicFieldStores } from "../../ir/int32-slots.js";
|
|
@@ -34,10 +38,11 @@ import { foldConstantGlobals } from "../../ir/constant-globals.js";
|
|
|
34
38
|
import { dropUnwrittenPropertyBags } from "../../ir/property-bags.js";
|
|
35
39
|
import { freezeInitOnlyGlobals } from "../../ir/init-only-globals.js";
|
|
36
40
|
import { hoistFinalFieldReads } from "../../ir/field-values.js";
|
|
41
|
+
import { holdCharLocalsAsUnits } from "../../ir/char-unit-locals.js";
|
|
37
42
|
import { findInt32Abis, INT32_ABI_SUFFIX, SCALAR_UNION_DUMMY, SCALAR_UNION_RESULT, } from "./int32-abi.js";
|
|
38
43
|
import {} from "./int32-locals.js";
|
|
39
44
|
import { findIntegerClones, NO_INTEGER_CLONES } from "./integer-clones.js";
|
|
40
|
-
import { exactInteger, narrowInteger } from "./integer-values.js";
|
|
45
|
+
import { exactInteger, narrowInteger, widenInteger } from "./integer-values.js";
|
|
41
46
|
import { findInitializerBindings } from "../../ir/initializer-bindings.js";
|
|
42
47
|
import { findConstantNumericTables } from "../../ir/constant-tables.js";
|
|
43
48
|
import { allocateFfiCallbackAdapters, hasForeignFfiCallback, hasRetainedFfiCallback, } from "../ffi-callbacks.js";
|
|
@@ -51,12 +56,13 @@ import { NullableRefFields } from "./nullable-fields.js";
|
|
|
51
56
|
import { InlineUnionFields, loadInlineUnion, presentBits, stackUnionBox, storeInlineUnion, unionBoxBits, } from "./inline-unions.js";
|
|
52
57
|
import { OptionalArrayReads } from "./local-array-reads.js";
|
|
53
58
|
import { CheckedNarrows } from "./checked-narrows.js";
|
|
54
|
-
import { emitDenseArraySet, emitDenseSlotUnlink } from "./dense-array-access.js";
|
|
59
|
+
import { emitDenseArraySet, emitDenseSlotUnlink, SCR_ELEM_I32, } from "./dense-array-access.js";
|
|
55
60
|
import { matchMapRead } from "./map-read-lifetimes.js";
|
|
56
61
|
import {} from "./map-entry-fusion.js";
|
|
57
62
|
import { emitBorrowedFieldSequence, guardedValue } from "./borrowed-receivers.js";
|
|
58
63
|
import { emitBorrowedInputs } from "./borrowed-inputs.js";
|
|
59
64
|
import { findWalkBorrows } from "./walk-borrows.js";
|
|
65
|
+
import { IrNodeIndex } from "../../ir/node-index.js";
|
|
60
66
|
import { lastUseRead } from "./local-extents.js";
|
|
61
67
|
import { findReboundParameters } from "./rebound-parameters.js";
|
|
62
68
|
import { ReferenceEffects } from "./reference-effects.js";
|
|
@@ -68,7 +74,7 @@ import { AmbientReceiverReaders, findConstantCallbacks } from "./constant-callba
|
|
|
68
74
|
import { findLentStringParameters, } from "./string-slices.js";
|
|
69
75
|
import { LazyCaptures } from "./lazy-captures.js";
|
|
70
76
|
import { StackCaptures } from "./stack-captures.js";
|
|
71
|
-
import { emitFieldAbsentTest, f64Lit } from "./common.js";
|
|
77
|
+
import { emitFieldAbsentTest, f64Lit, SCR_ARR_FIELD, SCR_ARR_FROZEN } from "./common.js";
|
|
72
78
|
import { ffiExtendsNarrowIntegers } from "../targets.js";
|
|
73
79
|
import { emitLiteralExpr, emitOperatorExpr, emitStringExpr, emitContainerExpr, emitRecordExpr, } from "./expr-primitives.js";
|
|
74
80
|
import { emitControlExpr } from "./expr-control.js";
|
|
@@ -77,8 +83,10 @@ import { emitDynamicExpr } from "./expr-dynamic.js";
|
|
|
77
83
|
import { emitIntrinsicExpr, emitSerializationExpr, emitAsyncExpr } from "./expr-async.js";
|
|
78
84
|
import { PublishWalkers } from "./publish.js";
|
|
79
85
|
import { computeImmutableFields, stableGlobals } from "../immutability.js";
|
|
86
|
+
import { computeCycleMutability, hierarchyUnitOfClass } from "../cycle-mutability.js";
|
|
80
87
|
import { computePublishedTypes } from "../publication.js";
|
|
81
88
|
import { emitExpr } from "./expr-dispatch.js";
|
|
89
|
+
import { LOOPS } from "./loop-state.js";
|
|
82
90
|
import { dynKind, raceAdapterFor, genResultThunkFor, childExitThunkFor, childExitSignalThunkFor, childDataDynThunkFor, childDataThunkFor, execFileThunkFor, ipcMessageThunkFor, ipcSendThunkFor, emitterFixedAdapter, emitterOnceAdapter, wrapEmitterListener, unwrapNullableClosure, closeBindThunkFor, closeOverrideWrapFor, } from "./expr-callbacks.js";
|
|
83
91
|
import { streamDataAdapter, streamDoneFnFor, cryptoBytesThunkFor, cryptoIntThunkFor, fsRenameThunkFor, streamCbThunkFor, zlibBytesThunkFor, } from "./expr-stream-callbacks.js";
|
|
84
92
|
import { emitStableReceiver, resolveThunkFor, tagInSet, arrPush, emitArrayCopyLoop, emitStrIntrinsic, emitArrIntrinsic, wrapNullable, emitMapNew, mapSet, emitMapLikeIntrinsic, emitSetNew, } from "./expr-containers.js";
|
|
@@ -90,7 +98,7 @@ import { emitChildProcessLibCall, emitAsyncContextLibCall, emitProcessLibCall, e
|
|
|
90
98
|
import { emitStreamLibCall } from "./lib-stream.js";
|
|
91
99
|
import { emitNetworkHttpLibCall } from "./lib-network.js";
|
|
92
100
|
import { emitAssertInspectLibCall, emitIoLibCall, emitGenericLibCall, emitLibCall, } from "./lib-dispatch.js";
|
|
93
|
-
import { buildClassGraph, classMembershipIntervals, classFieldIndex, classPreLines, classStructSym, programLifetimeClass, } from "./classes.js";
|
|
101
|
+
import { assignCompactLayouts, buildClassGraph, classFieldTypes, classMembershipIntervals, classFieldIndex, compactRefLoadLines, compactRefStoreLines, classPreLines, classStructSym, programLifetimeClass, } from "./classes.js";
|
|
94
102
|
import { LifetimeRegions, REGION_TYPES } from "./regions.js";
|
|
95
103
|
import { LlDyn, recordDynKeepsIdentity } from "./dyn.js";
|
|
96
104
|
import { VirtualBorrows } from "./virtual-borrows.js";
|
|
@@ -99,7 +107,7 @@ import { LlWalkers } from "./walkers.js";
|
|
|
99
107
|
import { isObjectArm, NULLABLE_ABSENT, NULLABLE_NULL, NullableUnions } from "./nullable-unions.js";
|
|
100
108
|
import { emitNullablePresent, emitUnionPeek, emitUnionTag } from "./union-repr.js";
|
|
101
109
|
import { emitConcatInputs, emitMixedConcat, numberPart, stringParts, } from "./string-construction.js";
|
|
102
|
-
import { arrNewCall, boxAccess, boxNewCall, boxReleaseSym, computeTraced, emitInlineRcHelpers, emitNullableRetainWrappers, emitShapeUnionHelpers, FN_ATTRS, inlineRcDecls, llFieldType, mapFlagsOffset, releaseSym, retainSym, traceArg, vAdapters, } from "./shapes.js";
|
|
110
|
+
import { arrNewCall, boxAccess, elemAccess, boxNewCall, boxReleaseSym, computeTraced, emitInlineRcHelpers, emitNullableRetainWrappers, emitShapeUnionHelpers, FN_ATTRS, inlineRcDecls, llFieldType, mapFlagsOffset, releaseSym, retainSym, traceArg, vAdapters, } from "./shapes.js";
|
|
103
111
|
import { INLINE_LITERAL_BYTES } from "./string-literal-equality.js";
|
|
104
112
|
import { emitFfiCallbackDefs, emitLibDefs, emitModuleParts, emitParts, helperDefs, } from "./emit-module.js";
|
|
105
113
|
import { emitLoopCopies, emitSpeculativeWrite, emitStmtBody, emitStringSelfConcatAssign, emitSwitch, emitTryCatch, } from "./emit-statements.js";
|
|
@@ -131,21 +139,66 @@ export function ffiCallbackDummyLl(callback) {
|
|
|
131
139
|
return "i32 0";
|
|
132
140
|
}
|
|
133
141
|
}
|
|
134
|
-
|
|
142
|
+
/** LlvmTargetOptions.lowRegion for an executable: Linux targets without
|
|
143
|
+
* sanitizers, whose address space below 32 GiB is free (ASan keeps its
|
|
144
|
+
* shadow memory there; other systems map their own images and libraries
|
|
145
|
+
* there). `platform` is a target platform (`linux`, `darwin`, `win32`,
|
|
146
|
+
* `wasi`). */
|
|
147
|
+
export function lowRegionTarget(platform, sanitize) {
|
|
148
|
+
return platform === "linux" && !sanitize;
|
|
149
|
+
}
|
|
150
|
+
/** Function versions on loop-bounding number parameters
|
|
151
|
+
* (ir/parameter-versions.ts). Library builds have no int32 entries, and a
|
|
152
|
+
* module that observes call stacks could see the version's frame. */
|
|
153
|
+
function versionParameters(mod) {
|
|
154
|
+
if (mod.lib !== undefined || observesStacks(mod))
|
|
155
|
+
return mod;
|
|
156
|
+
return versionLoopBoundParameters(mod, mangleFunction);
|
|
157
|
+
}
|
|
158
|
+
/** The int32 arrays the int32 slot analysis keeps in `mod` (proven and
|
|
159
|
+
* checked), under the inputs LlEmitter gives it (selectInt32Arrays). */
|
|
160
|
+
function provenInt32Arrays(mod) {
|
|
161
|
+
const slots = analyzeInt32Slots(mod, {
|
|
162
|
+
dynamicStores: dynamicFieldStores(mod),
|
|
163
|
+
initializerBindings: findInitializerBindings(mod),
|
|
164
|
+
});
|
|
165
|
+
return new Set([...slots.int32Arrays, ...slots.checkedInt32Arrays]);
|
|
166
|
+
}
|
|
167
|
+
/** The functions whose calls the backend may emit as calls of their
|
|
168
|
+
* result-slot entries (record-results.ts). */
|
|
169
|
+
function resultEntryTargets(mod) {
|
|
170
|
+
const names = new Set(mod.functions.map((fn) => fn.name));
|
|
171
|
+
const targets = new Set();
|
|
172
|
+
for (const name of names)
|
|
173
|
+
if (names.has(resultEntryName(name)))
|
|
174
|
+
targets.add(name);
|
|
175
|
+
return targets;
|
|
176
|
+
}
|
|
177
|
+
/** The emitter for `input` after the module passes every emission runs. */
|
|
178
|
+
function moduleEmitter(input, options) {
|
|
135
179
|
// Facts are keyed by node identity: emit the same module whether it was
|
|
136
180
|
// lowered in memory or read back from its serialized form.
|
|
137
181
|
const mod = unshareNodes(input);
|
|
138
182
|
// Keep source storage intact for debugger inspection in dev builds.
|
|
139
183
|
return new LlEmitter(options.debugSources === undefined
|
|
140
|
-
? addRecordResultEntries(scalarizeNumericRecords(specializeCallbackCalls(specializeNumericCalls(foldConstantGlobals(copyStableCaptures(resolveSelfCaptures(hoistFinalFieldReads(freezeInitOnlyGlobals(dropUnwrittenPropertyBags(mod)))))), mangleFunction), mangleFunction)))
|
|
141
|
-
: mod, options)
|
|
184
|
+
? selectInt32Arrays(versionParameters(addRecordResultEntries(scalarizeNumericRecords(specializeCallbackCalls(specializeNumericCalls(foldConstantGlobals(copyStableCaptures(resolveSelfCaptures(hoistFinalFieldReads(freezeInitOnlyGlobals(holdCharLocalsAsUnits(dropUnwrittenPropertyBags(runPairedWhileLoopsAsFor(mod)))))))), mangleFunction), mangleFunction)))), provenInt32Arrays, resultEntryTargets)
|
|
185
|
+
: mod, options);
|
|
186
|
+
}
|
|
187
|
+
export function emitLlvmModule(input, options = {}) {
|
|
188
|
+
return moduleEmitter(input, options).emit();
|
|
189
|
+
}
|
|
190
|
+
/** emitLlvmModule's text as parts that concatenate to it, without the copy
|
|
191
|
+
* that joining them makes: a large program's text is 150 MB. */
|
|
192
|
+
export function emitLlvmModuleParts(input, options = {}) {
|
|
193
|
+
return moduleEmitter(input, options)
|
|
194
|
+
.emitParts()
|
|
195
|
+
.flatMap((part, index) => (index === 0 ? [part] : ["\n", part]));
|
|
142
196
|
}
|
|
143
197
|
/** Keep large translation units below the host's single-string limit. */
|
|
144
198
|
export function emitLlvmModuleSource(input, options = {}) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
: mod, options).emitParts();
|
|
199
|
+
// IR validation, contracts and the frontend's disposal run after lowering without checks.
|
|
200
|
+
relieveHeapPressure(true);
|
|
201
|
+
const parts = moduleEmitter(input, options).emitParts();
|
|
149
202
|
const length = parts.reduce((total, part) => total + part.length, Math.max(0, parts.length - 1));
|
|
150
203
|
if (length <= 256 * 1024 * 1024)
|
|
151
204
|
return parts.join("\n");
|
|
@@ -231,8 +284,38 @@ function mentionsLocal(e, localId) {
|
|
|
231
284
|
expr(e);
|
|
232
285
|
return found;
|
|
233
286
|
}
|
|
287
|
+
/** The IR nodes in `body` that name local `id`: its declaration, reads,
|
|
288
|
+
* writes and closure captures. */
|
|
289
|
+
function countLocalMentions(body, id) {
|
|
290
|
+
let count = 0;
|
|
291
|
+
const visit = (node) => {
|
|
292
|
+
if (node === null || typeof node !== "object")
|
|
293
|
+
return;
|
|
294
|
+
if (Array.isArray(node)) {
|
|
295
|
+
for (const item of node)
|
|
296
|
+
visit(item);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const record = node;
|
|
300
|
+
if (record["localId"] === id)
|
|
301
|
+
count++;
|
|
302
|
+
const captures = record["captures"];
|
|
303
|
+
if (Array.isArray(captures))
|
|
304
|
+
for (const c of captures)
|
|
305
|
+
if (c === id ||
|
|
306
|
+
(typeof c === "object" && c !== null && c.localId === id))
|
|
307
|
+
count++;
|
|
308
|
+
for (const [key, value] of Object.entries(record))
|
|
309
|
+
if (key !== "type" && key !== "loc" && key !== "captures")
|
|
310
|
+
visit(value);
|
|
311
|
+
};
|
|
312
|
+
visit(body);
|
|
313
|
+
return count;
|
|
314
|
+
}
|
|
234
315
|
export class LlEmitter {
|
|
235
316
|
mod;
|
|
317
|
+
/** Per-feature state (emitter-state.ts), indexed by each key's slot. */
|
|
318
|
+
moduleStates = [];
|
|
236
319
|
localArrayReads = new Map();
|
|
237
320
|
loopArrayBorrows = new Set();
|
|
238
321
|
scalarStringSlices = new Map();
|
|
@@ -254,6 +337,15 @@ export class LlEmitter {
|
|
|
254
337
|
integerArrayBindings = new Set();
|
|
255
338
|
fieldAliasTags = new Map();
|
|
256
339
|
fieldPointerTags = new Map();
|
|
340
|
+
/** The field pointers (classFieldPtr) of this function whose fields hold
|
|
341
|
+
* 32-bit references to compact class instances (LlClassMeta.compressed):
|
|
342
|
+
* loadField/loadRef decode them and storeField/storeRef encode them. */
|
|
343
|
+
compressedFieldPtrs = new Set();
|
|
344
|
+
/** Compact class instances live in the program-lifetime region below
|
|
345
|
+
* 32 GiB (LlvmTargetOptions.lowRegion, and the program has compact
|
|
346
|
+
* classes): main reserves it before compiled code runs (scr_plr_init), and
|
|
347
|
+
* fields and arrays of compactRefType hold 32-bit references. */
|
|
348
|
+
compactRegion = false;
|
|
257
349
|
/** Native class fields with different property names cannot occupy the
|
|
258
350
|
* same slot of one object. Inherited views of the same property share a
|
|
259
351
|
* tag. Array storage has its own disjoint categories; untagged runtime
|
|
@@ -269,6 +361,7 @@ export class LlEmitter {
|
|
|
269
361
|
tag = 2 + this.fieldAliasTags.size * 2;
|
|
270
362
|
this.fieldAliasTags.set(field, tag);
|
|
271
363
|
}
|
|
364
|
+
this.journal?.entry("tag", field, tag);
|
|
272
365
|
this.fieldPointerTags.set(ptr, tag);
|
|
273
366
|
}
|
|
274
367
|
/** The alias tag of a runtime word that emitted code reads and writes
|
|
@@ -281,19 +374,225 @@ export class LlEmitter {
|
|
|
281
374
|
tag = 2 + this.fieldAliasTags.size * 2;
|
|
282
375
|
this.fieldAliasTags.set(category, tag);
|
|
283
376
|
}
|
|
377
|
+
this.journal?.entry("tag", category, tag);
|
|
284
378
|
return `, !tbaa !${tag}`;
|
|
285
379
|
}
|
|
380
|
+
/** The current function's int32 array allocations: the array literals
|
|
381
|
+
* its int32 arrays are written with. They construct SCR_ELEM_I32 arrays. */
|
|
382
|
+
int32Allocations = new Set();
|
|
383
|
+
/** The fill temporaries (`new Array(n).fill(v)`) of those allocations:
|
|
384
|
+
* the same arrays, so int32 too. */
|
|
385
|
+
int32ArrayTemps = new Set();
|
|
386
|
+
/** The same for the current function's int32 arrays with checked stores,
|
|
387
|
+
* which are only allocated by fills (ir/int32-arrays.ts
|
|
388
|
+
* checkableInt32Allocations): their temporaries' literals, with the fill's
|
|
389
|
+
* length (a literal constructs SCR_ELEM_I32 storage when that length is at
|
|
390
|
+
* least CHECKED_INT32_MIN_LENGTH, SCR_ELEM_F64 otherwise), and their
|
|
391
|
+
* temporaries. */
|
|
392
|
+
checkedAllocations = new Map();
|
|
393
|
+
checkedArrayTemps = new Set();
|
|
394
|
+
/** The fill calls (`.fill(v)`) of those allocations: a value that is not
|
|
395
|
+
* an int32 widens the new array first. */
|
|
396
|
+
checkedFills = new Set();
|
|
397
|
+
/** Collect the int32 allocations of `fn`, about to be emitted. */
|
|
398
|
+
findInt32Allocations(fn) {
|
|
399
|
+
this.int32Allocations.clear();
|
|
400
|
+
this.int32ArrayTemps.clear();
|
|
401
|
+
this.checkedAllocations.clear();
|
|
402
|
+
this.checkedArrayTemps.clear();
|
|
403
|
+
this.checkedFills.clear();
|
|
404
|
+
const { int32Arrays, checkedInt32Arrays } = this.int32Slots;
|
|
405
|
+
if (int32Arrays.size === 0 && checkedInt32Arrays.size === 0)
|
|
406
|
+
return;
|
|
407
|
+
everyStmtList(fn.body, {
|
|
408
|
+
stmt: (s) => {
|
|
409
|
+
if (s.kind !== "varDecl" && s.kind !== "assign")
|
|
410
|
+
return true;
|
|
411
|
+
const key = int32ArrayKey(fn.name, s.localId);
|
|
412
|
+
const checked = checkedInt32Arrays.has(key);
|
|
413
|
+
if (!checked && !int32Arrays.has(key))
|
|
414
|
+
return true;
|
|
415
|
+
const value = s.kind === "varDecl" ? s.init : s.value;
|
|
416
|
+
const allocation = value && allocatedLiteral(value);
|
|
417
|
+
if (!allocation)
|
|
418
|
+
return true;
|
|
419
|
+
const length = checked ? fillAllocationLength(value) : null;
|
|
420
|
+
if (length !== null)
|
|
421
|
+
this.checkedAllocations.set(allocation.literal, length);
|
|
422
|
+
else if (!checked)
|
|
423
|
+
this.int32Allocations.add(allocation.literal);
|
|
424
|
+
if (allocation.temporary !== null)
|
|
425
|
+
(checked ? this.checkedArrayTemps : this.int32ArrayTemps).add(allocation.temporary);
|
|
426
|
+
if (checked && value !== allocation.literal)
|
|
427
|
+
this.checkedFills.add(value);
|
|
428
|
+
return true;
|
|
429
|
+
},
|
|
430
|
+
expr: () => true,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
/** Whether `arr` reads one of the int32 arrays (ir/int32-arrays.ts, kept
|
|
434
|
+
* by the int32 slot analysis): a local or parameter of the current
|
|
435
|
+
* function, or a module global. */
|
|
436
|
+
int32Array(arr) {
|
|
437
|
+
if (arr.kind !== "varRef")
|
|
438
|
+
return false;
|
|
439
|
+
if (this.int32KindArray(arr))
|
|
440
|
+
return true;
|
|
441
|
+
if (this.int32Slots.int32Arrays.size === 0)
|
|
442
|
+
return false;
|
|
443
|
+
return (this.int32ArrayTemps.has(arr.localId) ||
|
|
444
|
+
this.int32Slots.int32Arrays.has(int32ArrayKey(this.currentFunctionName, arr.localId)));
|
|
445
|
+
}
|
|
446
|
+
/** Whether `arr` is one of the current function's int32 arrays with
|
|
447
|
+
* checked stores: int32 slots until a store widens it to doubles. Every
|
|
448
|
+
* access tests its kind (emitByElementKind), except in the fast copy of
|
|
449
|
+
* an int32 kind loop, which reads and writes it as an int32 array. */
|
|
450
|
+
checkedInt32Array(arr) {
|
|
451
|
+
if (arr.kind !== "varRef" || this.int32KindArray(arr))
|
|
452
|
+
return false;
|
|
453
|
+
if (this.int32Kinds?.wide.has(`${this.currentFunctionName}\0${arr.localId}`))
|
|
454
|
+
return false;
|
|
455
|
+
return this.checkedInt32Local(arr.localId);
|
|
456
|
+
}
|
|
457
|
+
/** Whether the local `localId` holds one of the current function's int32
|
|
458
|
+
* arrays with checked stores. */
|
|
459
|
+
checkedInt32Local(localId) {
|
|
460
|
+
if (this.int32Slots.checkedInt32Arrays.size === 0)
|
|
461
|
+
return false;
|
|
462
|
+
return (this.checkedArrayTemps.has(localId) ||
|
|
463
|
+
this.int32Slots.checkedInt32Arrays.has(`${this.currentFunctionName}\0${localId}`));
|
|
464
|
+
}
|
|
465
|
+
/** Whether `arr` is an int32 array with checked stores that the fast copy
|
|
466
|
+
* of the int32 kind loop being emitted holds as an int32 array. */
|
|
467
|
+
int32KindArray(arr) {
|
|
468
|
+
return (this.int32Kinds !== null &&
|
|
469
|
+
arr.kind === "varRef" &&
|
|
470
|
+
this.int32Kinds.int32.has(`${this.currentFunctionName}\0${arr.localId}`));
|
|
471
|
+
}
|
|
472
|
+
/** Before a store of `value` (of `expr`) into `arr`, in the fast copy of
|
|
473
|
+
* an int32 kind loop: continue when it is an int32 that is not -0, and
|
|
474
|
+
* otherwise leave for the statement's resume point, where it re-executes
|
|
475
|
+
* with kind tests. Returns the value as an i32 when it is at hand as an
|
|
476
|
+
* integer, or null when the store converts the double itself. */
|
|
477
|
+
emitInt32KindStoreCheck(arr, value, expr) {
|
|
478
|
+
if (!this.int32KindArray(arr) || withinInt32(this.integerRanges.get(expr)))
|
|
479
|
+
return null;
|
|
480
|
+
const integer = exactInteger(this, value, expr);
|
|
481
|
+
if (integer !== null && withinInt32(integer.range))
|
|
482
|
+
return narrowInteger(this, integer);
|
|
483
|
+
const resume = this.int32KindResume;
|
|
484
|
+
if (resume === null)
|
|
485
|
+
throw new InternalCompilerError("llvm emitter bug: an int32 kind store without a resume");
|
|
486
|
+
const B = this.B;
|
|
487
|
+
const ok = B.tmp(), int = B.tmp();
|
|
488
|
+
if (integer !== null) {
|
|
489
|
+
// An exact integer: a range test on its 64-bit form.
|
|
490
|
+
const wide = widenInteger(this, integer), low = B.tmp(), high = B.tmp();
|
|
491
|
+
B.line(`${low} = icmp sge i64 ${wide}, -2147483648`);
|
|
492
|
+
B.line(`${high} = icmp sle i64 ${wide}, 2147483647`);
|
|
493
|
+
B.line(`${ok} = and i1 ${low}, ${high}`);
|
|
494
|
+
const store = B.newLabel("arr.store.i32");
|
|
495
|
+
B.condBr(ok, store, resume);
|
|
496
|
+
B.startBlock(store);
|
|
497
|
+
B.line(`${int} = trunc i64 ${wide} to i32`);
|
|
498
|
+
return int;
|
|
499
|
+
}
|
|
500
|
+
this.declare("declare i32 @llvm.fptosi.sat.i32.f64(double)");
|
|
501
|
+
const back = B.tmp(), exact = B.tmp(), bits = B.tmp(), notNegativeZero = B.tmp();
|
|
502
|
+
B.line(`${int} = call i32 @llvm.fptosi.sat.i32.f64(double ${value.name})`);
|
|
503
|
+
B.line(`${back} = sitofp i32 ${int} to double`);
|
|
504
|
+
B.line(`${exact} = fcmp oeq double ${back}, ${value.name}`);
|
|
505
|
+
B.line(`${bits} = bitcast double ${value.name} to i64`);
|
|
506
|
+
B.line(`${notNegativeZero} = icmp ne i64 ${bits}, -9223372036854775808`);
|
|
507
|
+
B.line(`${ok} = and i1 ${exact}, ${notNegativeZero}`);
|
|
508
|
+
const store = B.newLabel("arr.store.i32");
|
|
509
|
+
B.condBr(ok, store, resume);
|
|
510
|
+
B.startBlock(store);
|
|
511
|
+
return int;
|
|
512
|
+
}
|
|
513
|
+
/** Emit an access to the checked int32 array `array` once per element
|
|
514
|
+
* kind: `arm("i32", widened)` while it holds int32 slots and
|
|
515
|
+
* `arm("f64", widened)` after it widened, joined after both. `widened` is
|
|
516
|
+
* the label of the double arm, where an int32 arm's store of a value that
|
|
517
|
+
* is not an int32 continues after widening the array. Returns the phi of
|
|
518
|
+
* the arms' results (of LLVM type `ty`), or null when `ty` is null. */
|
|
519
|
+
emitByElementKind(array, ty, arm) {
|
|
520
|
+
const B = this.B;
|
|
521
|
+
const narrow = B.newLabel("arr.kind.i32"), wide = B.newLabel("arr.kind.f64"), join = B.newLabel("arr.kind.join");
|
|
522
|
+
const kindPtr = B.tmp(), kind = B.tmp(), isInt32 = B.tmp();
|
|
523
|
+
B.line(`${kindPtr} = getelementptr inbounds %ScrArr, ptr ${array}, i32 0, i32 ${SCR_ARR_FIELD.elem}`);
|
|
524
|
+
this.markMemoryPointer(kindPtr, "array:header");
|
|
525
|
+
B.line(`${kind} = load i8, ptr ${kindPtr}${this.fieldAliasAttachment(kindPtr)}`);
|
|
526
|
+
B.line(`${isInt32} = icmp eq i8 ${kind}, ${SCR_ELEM_I32}`);
|
|
527
|
+
B.condBr(isInt32, narrow, wide);
|
|
528
|
+
B.startBlock(narrow);
|
|
529
|
+
const narrowValue = arm("i32", wide);
|
|
530
|
+
const narrowEnd = B.isTerminated() ? null : B.currentLabel();
|
|
531
|
+
if (narrowEnd !== null)
|
|
532
|
+
B.br(join);
|
|
533
|
+
B.startBlock(wide);
|
|
534
|
+
const wideValue = arm("f64", wide);
|
|
535
|
+
const wideEnd = B.isTerminated() ? null : B.currentLabel();
|
|
536
|
+
if (wideEnd !== null)
|
|
537
|
+
B.br(join);
|
|
538
|
+
B.startBlock(join);
|
|
539
|
+
// Arms that end in their own branches (a read's shared join) leave this
|
|
540
|
+
// join without predecessors.
|
|
541
|
+
if (narrowEnd === null && wideEnd === null)
|
|
542
|
+
B.terminate("unreachable");
|
|
543
|
+
if (ty === null)
|
|
544
|
+
return null;
|
|
545
|
+
const arms = [];
|
|
546
|
+
if (narrowEnd !== null)
|
|
547
|
+
arms.push(`[ ${narrowValue}, %${narrowEnd} ]`);
|
|
548
|
+
if (wideEnd !== null)
|
|
549
|
+
arms.push(`[ ${wideValue}, %${wideEnd} ]`);
|
|
550
|
+
const result = B.tmp();
|
|
551
|
+
B.line(`${result} = phi ${ty} ${arms.join(", ")}`);
|
|
552
|
+
return result;
|
|
553
|
+
}
|
|
554
|
+
/** Before storing the double `value` (of `expr`) into an int32 arm
|
|
555
|
+
* (emitByElementKind) of the checked int32 array `array`: continue in this
|
|
556
|
+
* arm when it is an int32 that is not -0, or widen the array and continue
|
|
557
|
+
* at `widened`. A value proven an int32 needs no test. */
|
|
558
|
+
emitCheckedInt32Store(array, value, expr, widened) {
|
|
559
|
+
if (withinInt32(this.integerRanges.get(expr)))
|
|
560
|
+
return;
|
|
561
|
+
const B = this.B;
|
|
562
|
+
this.declare("declare i32 @llvm.fptosi.sat.i32.f64(double)");
|
|
563
|
+
this.declare("declare void @scr_arr_widen_i32(ptr)");
|
|
564
|
+
const int = B.tmp(), back = B.tmp(), exact = B.tmp(), bits = B.tmp(), notNegativeZero = B.tmp(), ok = B.tmp();
|
|
565
|
+
B.line(`${int} = call i32 @llvm.fptosi.sat.i32.f64(double ${value})`);
|
|
566
|
+
B.line(`${back} = sitofp i32 ${int} to double`);
|
|
567
|
+
B.line(`${exact} = fcmp oeq double ${back}, ${value}`);
|
|
568
|
+
B.line(`${bits} = bitcast double ${value} to i64`);
|
|
569
|
+
B.line(`${notNegativeZero} = icmp ne i64 ${bits}, -9223372036854775808`);
|
|
570
|
+
B.line(`${ok} = and i1 ${exact}, ${notNegativeZero}`);
|
|
571
|
+
const store = B.newLabel("arr.store.i32"), widen = B.newLabel("arr.widen");
|
|
572
|
+
B.condBr(ok, store, widen);
|
|
573
|
+
B.startBlock(widen);
|
|
574
|
+
B.line(`call void @scr_arr_widen_i32(ptr ${array})`);
|
|
575
|
+
B.br(widened);
|
|
576
|
+
B.startBlock(store);
|
|
577
|
+
}
|
|
578
|
+
/** The access an element operation on `arr` (of element type `elem`)
|
|
579
|
+
* takes: int32 arrays read and write their 4-byte slots. */
|
|
580
|
+
arrayAccess(arr, elem) {
|
|
581
|
+
if (this.checkedInt32Array(arr))
|
|
582
|
+
throw new InternalCompilerError("llvm emitter bug: a checked int32 array without its kind test");
|
|
583
|
+
return this.int32Array(arr) ? "i32" : elemAccess(elem);
|
|
584
|
+
}
|
|
286
585
|
/** Whether an element access at `index` of `arr` lies in the hole-free
|
|
287
|
-
* prefix:
|
|
288
|
-
*
|
|
586
|
+
* prefix: a counter of a dense array loop's fast copy indexing one of the
|
|
587
|
+
* arrays its entry test covered. */
|
|
289
588
|
provenDenseIndex(arr, index) {
|
|
290
|
-
const loop = this.denseLoop;
|
|
589
|
+
const loop = LOOPS.of(this).denseLoop;
|
|
291
590
|
return (loop !== null &&
|
|
292
591
|
arr.kind === "varRef" &&
|
|
293
592
|
loop.arrays.has(arr.localId) &&
|
|
294
593
|
index.kind === "varRef" &&
|
|
295
|
-
index.localId === loop.counter &&
|
|
296
|
-
this.integerLoopBindings.has(
|
|
594
|
+
(index.localId === loop.counter || index.localId === loop.pair?.high) &&
|
|
595
|
+
this.integerLoopBindings.has(index.localId));
|
|
297
596
|
}
|
|
298
597
|
fieldAliasAttachment(ptr) {
|
|
299
598
|
const tag = this.fieldPointerTags.get(ptr);
|
|
@@ -384,6 +683,10 @@ export class LlEmitter {
|
|
|
384
683
|
cstrs = new Map();
|
|
385
684
|
/** Interned ScrMapOps descriptors (scr_map.h): initializer → symbol. */
|
|
386
685
|
mapOpsConsts = new Map();
|
|
686
|
+
/** Method-id slots of checked-dynamic method calls
|
|
687
|
+
* (scr_dyn_invoke_prepared_id): method name → symbol of an i32 the
|
|
688
|
+
* runtime fills with the name's id on the first call. */
|
|
689
|
+
methodIdSlots = new Map();
|
|
387
690
|
/** Type-directed walker functions (JSON serializers, the indent
|
|
388
691
|
* rewriter, union ToString/join) — interned per typeKey/unionId, defs
|
|
389
692
|
* flushed with the shape helpers. */
|
|
@@ -432,6 +735,15 @@ export class LlEmitter {
|
|
|
432
735
|
callLifetimes;
|
|
433
736
|
constantCallbacks;
|
|
434
737
|
currentConstantCallbacks = new Map();
|
|
738
|
+
/** The current function's running maximum and minimum updates, whose
|
|
739
|
+
* branches are weighted as rarely taken (running-extrema.ts). */
|
|
740
|
+
runningExtrema = new Set();
|
|
741
|
+
/** Callback bindings whose closures an enclosing callback loop version
|
|
742
|
+
* proved to hold their known function: calls take the direct entry with
|
|
743
|
+
* no fallback (emitCallbackVersionedLoop). */
|
|
744
|
+
knownCallbacks = new Set();
|
|
745
|
+
callbackVersioning = new Set();
|
|
746
|
+
callbackVersionsEnabled = false;
|
|
435
747
|
stackCallbacks;
|
|
436
748
|
receiverReaders;
|
|
437
749
|
stackCaptures;
|
|
@@ -474,6 +786,9 @@ export class LlEmitter {
|
|
|
474
786
|
/** Module constants that keep one value once initialized
|
|
475
787
|
* (immutability.ts stableGlobals). */
|
|
476
788
|
stableGlobals = new Set();
|
|
789
|
+
/** Every function body's nodes in walk order (ir/node-index.ts), for the
|
|
790
|
+
* constructor's analyses. */
|
|
791
|
+
nodeIndex;
|
|
477
792
|
tdzGlobals = new Map();
|
|
478
793
|
constantNumericTables;
|
|
479
794
|
/** Constant-key reads on checked-dynamic objects, each with its own
|
|
@@ -513,9 +828,15 @@ export class LlEmitter {
|
|
|
513
828
|
/** Fiberless async functions a stackless coroutine body awaits directly;
|
|
514
829
|
* each gets an inline await entry (emitCoroInlineAwait). */
|
|
515
830
|
inlineAwaitCallees = new Set();
|
|
831
|
+
/** Stackless async functions some coroutine body awaits directly: each
|
|
832
|
+
* gets a direct spawn entry (emitCoroDirectAwait). */
|
|
833
|
+
directAwaitCallees = new Set();
|
|
516
834
|
/** The async functions whose bodies never suspend and that a direct
|
|
517
835
|
* await may enter in place (selectStacklessAsync). */
|
|
518
836
|
inlineAwaitable = new Set();
|
|
837
|
+
/** Locals whose array literal emitStmts left for the `await Promise.all`
|
|
838
|
+
* that reads them (deferredPromiseAllLocal). */
|
|
839
|
+
deferredPromiseAllEntries = new Map();
|
|
519
840
|
/** The promise a `return` emitted past its finally regions already
|
|
520
841
|
* produced for its adopting await (borrowed from the return's parked
|
|
521
842
|
* slot); that await takes it instead of evaluating its operand. */
|
|
@@ -531,13 +852,16 @@ export class LlEmitter {
|
|
|
531
852
|
/** The program calls mock.timers members (moduleUsesMockTimers): timer
|
|
532
853
|
* calls emit scr_test.c's mock-aware entry points. */
|
|
533
854
|
mockTimers;
|
|
534
|
-
|
|
855
|
+
runtimeFeaturesValue;
|
|
856
|
+
/** The module's runtime features (moduleRuntimeFeatures), found with one
|
|
857
|
+
* walk of the module the first time any of them is read. */
|
|
858
|
+
get runtimeFeatures() {
|
|
859
|
+
return (this.runtimeFeaturesValue ??= moduleRuntimeFeatures(this.mod, this.nodeIndex));
|
|
860
|
+
}
|
|
535
861
|
/** Whether timer and tick scheduling goes through the *_als entry
|
|
536
862
|
* points (RuntimeFeatures asyncContext). */
|
|
537
863
|
get schedulesInContext() {
|
|
538
|
-
|
|
539
|
-
this.schedulesInContextValue = moduleRuntimeFeatures(this.mod).asyncContext;
|
|
540
|
-
return this.schedulesInContextValue;
|
|
864
|
+
return this.runtimeFeatures.asyncContext;
|
|
541
865
|
}
|
|
542
866
|
/** Emitted ref-kind resolve thunks for new Promise, interned per inner
|
|
543
867
|
* typeKey → thunk symbol. */
|
|
@@ -553,10 +877,14 @@ export class LlEmitter {
|
|
|
553
877
|
/** Identity-preserving static→dyn capsules for program classes and Web
|
|
554
878
|
* APIs whose values remain directly observable. */
|
|
555
879
|
liveDynRefAdapters = new Map();
|
|
556
|
-
dynBuiltinStreamUse;
|
|
557
880
|
/** See moduleUsesDynBuiltinStream. */
|
|
558
881
|
get usesDynBuiltinStream() {
|
|
559
|
-
return
|
|
882
|
+
return this.runtimeFeatures.dynBuiltinStream;
|
|
883
|
+
}
|
|
884
|
+
/** A checked-dynamic for-await may hold a native stream: the program
|
|
885
|
+
* links the stream unit (and the dyn-async one the loop needs). */
|
|
886
|
+
get dynForAwaitStreams() {
|
|
887
|
+
return this.runtimeFeatures.stream && this.runtimeFeatures.dynAsync;
|
|
560
888
|
}
|
|
561
889
|
/** Runtime-arm dispatchers for live union values. */
|
|
562
890
|
liveDynUnionRefAdapters = new Map();
|
|
@@ -646,25 +974,38 @@ export class LlEmitter {
|
|
|
646
974
|
* immortal from construction (classes.ts programLifetimeClass). */
|
|
647
975
|
programLifetime;
|
|
648
976
|
numericLocals = new Map();
|
|
649
|
-
/** Local arrays of the current function that no other binding can hold
|
|
650
|
-
* (ir/array-length-stability.ts). */
|
|
651
|
-
unaliasedArrays = new Set();
|
|
652
|
-
/** Dense array loops (dense-array-loops.ts) run in this function. */
|
|
653
|
-
denseLoopsEnabled = false;
|
|
654
|
-
denseLoopEntries = new Map();
|
|
655
|
-
/** The fast copy of a dense array loop being emitted. */
|
|
656
|
-
denseLoop = null;
|
|
657
977
|
captureIds = new Set();
|
|
658
978
|
/** Active induction bindings retain their width independently of size_t. */
|
|
659
979
|
integerLoopBindings = new Map();
|
|
660
|
-
|
|
980
|
+
/** Constant number locals whose latest emitted declaration stored an
|
|
981
|
+
* exact integer beside the double, such as `const j = i * 4` in a
|
|
982
|
+
* typed-array loop version: an i64 slot and the integer's range. */
|
|
983
|
+
integerTemps = new Map();
|
|
984
|
+
/** Integer temps are kept only in optimized synchronous functions: an
|
|
985
|
+
* async or generator body resumes with its locals in its frame, which
|
|
986
|
+
* an entry alloca is not part of. */
|
|
987
|
+
integerTempsEnabled = false;
|
|
661
988
|
/** Speculative integer loops (speculative-integers.ts) run in this function. */
|
|
662
989
|
speculativeLoopsEnabled = false;
|
|
663
990
|
/** The fast copy of a speculative integer loop being emitted: its
|
|
664
991
|
* integer-computed writes and where each resumes in the ordinary copy. */
|
|
665
992
|
speculation = null;
|
|
993
|
+
/** Speculative loop sites numbered so far in the module. */
|
|
994
|
+
speculativeLoopSites = 0;
|
|
666
995
|
/** The ordinary copy being emitted: resume labels still to place. */
|
|
667
996
|
speculationResume = null;
|
|
997
|
+
/** Run once at the top of the next loop copy's header
|
|
998
|
+
* (`enterLoopHeader`): records the ordinary copy's header, or sends the
|
|
999
|
+
* third copy's header there. */
|
|
1000
|
+
speculationHeader = null;
|
|
1001
|
+
/** A copy of an int32 kind loop (int32-kind-loops.ts) being emitted: the
|
|
1002
|
+
* int32 arrays with checked stores it reads and writes as int32 arrays
|
|
1003
|
+
* (the fast copy) or as double arrays (an ordinary copy entered only
|
|
1004
|
+
* after they widened), as `function\0local` keys, and where each of the
|
|
1005
|
+
* fast copy's writes resumes in the third copy. */
|
|
1006
|
+
int32Kinds = null;
|
|
1007
|
+
/** The resume label of the fast-copy write being emitted. */
|
|
1008
|
+
int32KindResume = null;
|
|
668
1009
|
/** The function being emitted, for speculative globals. */
|
|
669
1010
|
speculativeFunction = "";
|
|
670
1011
|
/** Every function that writes each number global (computed on demand). */
|
|
@@ -682,20 +1023,17 @@ export class LlEmitter {
|
|
|
682
1023
|
int32Elements = null;
|
|
683
1024
|
/** Sums whose result only feeds 32-bit conversions (wrapping-sums.ts). */
|
|
684
1025
|
wrappingSums = new Set();
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
* function: off in debug and suspending functions and inside a copy. */
|
|
689
|
-
bytesLoopVersionsEnabled = false;
|
|
690
|
-
/** Loops being versioned around the statement being emitted: a loop is
|
|
691
|
-
* never versioned inside its own copies, and versions nest boundedly. */
|
|
692
|
-
bytesLoopVersioning = new Set();
|
|
693
|
-
bytesLoopEntries = null;
|
|
694
|
-
bytesLoopFunction = null;
|
|
695
|
-
/** Counted loops whose integer-form safety test an enclosing version
|
|
696
|
-
* guard already passed. */
|
|
697
|
-
provenCountedGuards = new Set();
|
|
1026
|
+
/** Number locals of the current function that hold exact integers or NaN
|
|
1027
|
+
* (findIntegerOrNaNLocals in wrapping-sums.ts). */
|
|
1028
|
+
integerOrNaNLocals = new Map();
|
|
698
1029
|
bytesBounds = new Set();
|
|
1030
|
+
/** The charCodeAt reads standing for charAt reads the emitter rewrote
|
|
1031
|
+
* (one-unit tests and switches, charAtUnitRead), with the charAt each
|
|
1032
|
+
* stands for: a loop version's proof for the charAt covers its read. */
|
|
1033
|
+
charAtUnitReads = new Map();
|
|
1034
|
+
/** Worker programs: typed-array accesses whose views an enclosing version
|
|
1035
|
+
* guard proved thread-owned. */
|
|
1036
|
+
bytesOwned = new Set();
|
|
699
1037
|
integerViews = new Map();
|
|
700
1038
|
/** Module globals the current function owns outright (initializer
|
|
701
1039
|
* bindings): their function-local slot, which stands in for the global. */
|
|
@@ -746,27 +1084,50 @@ export class LlEmitter {
|
|
|
746
1084
|
chainSlots = new Map();
|
|
747
1085
|
logArgSlots = 0;
|
|
748
1086
|
stackTraces;
|
|
1087
|
+
/** The options this emitter was built with (chunk emitters reuse them). */
|
|
1088
|
+
targetOptions;
|
|
1089
|
+
/** Records the module-level effects of emitting a range of functions,
|
|
1090
|
+
* which the emitter that merges the range replays (emit-journal.ts). Null
|
|
1091
|
+
* when this emitter emits the whole module itself. */
|
|
1092
|
+
journal;
|
|
1093
|
+
/** The emitter's hosts forward to `journal` (journal set, or workers). */
|
|
1094
|
+
journaled;
|
|
749
1095
|
/** Stack-trace mode: functions no capture can include (no frame push). */
|
|
750
1096
|
unframedFunctions;
|
|
751
|
-
constructor(mod, options) {
|
|
1097
|
+
constructor(mod, options, journal = null) {
|
|
752
1098
|
this.mod = mod;
|
|
753
|
-
this.
|
|
754
|
-
this.
|
|
755
|
-
this.
|
|
1099
|
+
this.targetOptions = options;
|
|
1100
|
+
this.journal = journal;
|
|
1101
|
+
this.journaled =
|
|
1102
|
+
journal !== null ||
|
|
1103
|
+
((options.functionWorkers ?? 1) > 1 &&
|
|
1104
|
+
options.forkPrimitives !== undefined &&
|
|
1105
|
+
options.debugSources === undefined);
|
|
1106
|
+
// One walk of every body, which the analyses below read instead of
|
|
1107
|
+
// walking the bodies themselves.
|
|
1108
|
+
this.nodeIndex = new IrNodeIndex(mod);
|
|
1109
|
+
this.stackTraces = observesStacks(mod, this.nodeIndex);
|
|
1110
|
+
this.nullableUnions = new NullableUnions(mod, options.debugSources === undefined, this.nodeIndex);
|
|
1111
|
+
this.mockTimers = this.runtimeFeatures.mockTimers;
|
|
756
1112
|
this.debug =
|
|
757
1113
|
options.debugSources === undefined
|
|
758
1114
|
? null
|
|
759
1115
|
: new LlvmDebugInfo(mod.sourceFile, options.debugSources, options.pointerBits, mod.unions, this.nullableUnions.armTypes());
|
|
760
1116
|
this.constantNumericTables = findConstantNumericTables(mod);
|
|
761
|
-
this.initializerBindings = findInitializerBindings(mod);
|
|
762
|
-
|
|
763
|
-
const dynamicStores = dynamicFieldStores(mod);
|
|
1117
|
+
this.initializerBindings = findInitializerBindings(mod, this.nodeIndex);
|
|
1118
|
+
// One walk finds the dynamic field stores every analysis below consults.
|
|
1119
|
+
const dynamicStores = dynamicFieldStores(mod, undefined, undefined, this.nodeIndex);
|
|
1120
|
+
this.int32Slots = analyzeInt32Slots(mod, {
|
|
1121
|
+
dynamicStores,
|
|
1122
|
+
initializerBindings: this.initializerBindings,
|
|
1123
|
+
nodes: this.nodeIndex,
|
|
1124
|
+
});
|
|
764
1125
|
this.liveViewsReadOnly =
|
|
765
1126
|
mod.lib === undefined && !dynamicStores.all && dynamicStores.names.size === 0;
|
|
766
1127
|
this.int32Abis = this.debug === null ? findInt32Abis(mod, this.int32Slots) : new Map();
|
|
767
1128
|
this.immortalGlobals = new Set(mod.contracts?.immortalGlobals ?? []);
|
|
768
1129
|
this.programLifetime = new Set(mod.contracts?.programLifetime ?? []);
|
|
769
|
-
this.finalFields = analyzeFinalFields(mod);
|
|
1130
|
+
this.finalFields = analyzeFinalFields(mod, false, dynamicStores, this.nodeIndex);
|
|
770
1131
|
this.sizeType = options.pointerBits === 32 ? "i32" : "i64";
|
|
771
1132
|
this.ffiExtendNarrowIntegers =
|
|
772
1133
|
options.wasi === true || ffiExtendsNarrowIntegers(options.targetTriple);
|
|
@@ -815,7 +1176,7 @@ export class LlEmitter {
|
|
|
815
1176
|
this.ffiHasForeignCallback = hasForeignFfiCallback(mod.ffiImports ?? []);
|
|
816
1177
|
for (const fn of mod.functions)
|
|
817
1178
|
this.fnByName.set(fn.name, fn);
|
|
818
|
-
this.appendedArrayLiterals = findAppendedArrayLiterals(mod);
|
|
1179
|
+
this.appendedArrayLiterals = findAppendedArrayLiterals(mod, this.nodeIndex);
|
|
819
1180
|
for (const entry of mod.ffiImports ?? []) {
|
|
820
1181
|
this.ffiByName.set(entry.name, entry);
|
|
821
1182
|
}
|
|
@@ -823,8 +1184,11 @@ export class LlEmitter {
|
|
|
823
1184
|
// and per async fiber; WASI, Windows and library builds have none.
|
|
824
1185
|
const triple = (options.targetTriple ?? "").toLowerCase();
|
|
825
1186
|
const windows = triple === "" ? process.platform === "win32" : triple.includes("windows");
|
|
1187
|
+
this.publishedTypes = computePublishedTypes(mod, this.nodeIndex);
|
|
826
1188
|
const mt = computeMayThrow(mod, {
|
|
827
1189
|
stackChecks: !this.wasi && mod.lib === undefined && !windows,
|
|
1190
|
+
published: this.publishedTypes,
|
|
1191
|
+
nodes: this.nodeIndex,
|
|
828
1192
|
});
|
|
829
1193
|
this.mayThrow = mt.fns;
|
|
830
1194
|
this.workerEntryPolls = mt.workerEntryPolls ?? null;
|
|
@@ -833,11 +1197,12 @@ export class LlEmitter {
|
|
|
833
1197
|
// runtime moves deep prefix nests to a fresh stack using the guard,
|
|
834
1198
|
// which Windows lacks.
|
|
835
1199
|
this.stacklessAsyncAllowed = this.stacklessGenerators && mod.lib === undefined && !windows;
|
|
836
|
-
this.publishedTypes = computePublishedTypes(mod);
|
|
837
1200
|
this.unframedFunctions = this.stackTraces
|
|
838
1201
|
? captureFreeFunctions(mod, this.stackChecks, this.publishedTypes)
|
|
839
1202
|
: new Set();
|
|
840
|
-
|
|
1203
|
+
// One field-mutability answer serves immutable fields and traced shapes.
|
|
1204
|
+
const cycleMutability = computeCycleMutability(mod, hierarchyUnitOfClass(mod), dynamicStores);
|
|
1205
|
+
this.immutableFields = computeImmutableFields(mod, dynamicStores, cycleMutability);
|
|
841
1206
|
this.constructorFunctions = new Set((mod.classes ?? []).map((c) => `%${c.name}.constructor`));
|
|
842
1207
|
this.indirectMayThrow = mt.indirect || mod.workers === true;
|
|
843
1208
|
for (const cls of mod.classes ?? []) {
|
|
@@ -870,12 +1235,13 @@ export class LlEmitter {
|
|
|
870
1235
|
this.checkedNarrows = new CheckedNarrows(this.fnByName);
|
|
871
1236
|
this.referenceEffects = new ReferenceEffects(this.fnByName, (call) => this.optionalArrayReads.get(call) !== null, mod.classes ?? []);
|
|
872
1237
|
if (this.debug === null)
|
|
873
|
-
this.referenceWrites = new ReferenceWrites(this.fnByName, mod.classes ?? [], (call) => this.optionalArrayReads.get(call) !== null, new Set((mod.globals ?? []).map((g) => g.id)), { unions: mod.unions, records: mod.records }, this.immutableFields);
|
|
1238
|
+
this.referenceWrites = new ReferenceWrites(this.fnByName, mod.classes ?? [], (call) => this.optionalArrayReads.get(call) !== null, new Set((mod.globals ?? []).map((g) => g.id)), { unions: mod.unions, records: mod.records }, this.immutableFields, this.nodeIndex);
|
|
874
1239
|
const walkParameters = new Map();
|
|
875
1240
|
if (this.debug === null) {
|
|
876
1241
|
const host = {
|
|
877
1242
|
pointerLocal: (local) => this.plainReference(local.type),
|
|
878
1243
|
borrowsWithoutOwning: (e) => this.borrowsWithoutOwning(e),
|
|
1244
|
+
nodes: this.nodeIndex,
|
|
879
1245
|
};
|
|
880
1246
|
for (const fn of this.fnByName.values()) {
|
|
881
1247
|
const preserving = this.referenceEffects.functions.has(fn.name);
|
|
@@ -922,7 +1288,7 @@ export class LlEmitter {
|
|
|
922
1288
|
});
|
|
923
1289
|
this.lentStringParameters =
|
|
924
1290
|
this.debug === null ? findLentStringParameters(this.fnByName, this.callLifetimes) : new Map();
|
|
925
|
-
this.constantCallbacks = findConstantCallbacks(mod, this.callLifetimes);
|
|
1291
|
+
this.constantCallbacks = findConstantCallbacks(mod, this.callLifetimes, this.nodeIndex);
|
|
926
1292
|
// Integer clones signal a stack overflow through their result, which
|
|
927
1293
|
// needs the single-threaded guard; worker programs also poll for
|
|
928
1294
|
// termination, and debug builds and stack traces keep every frame.
|
|
@@ -941,7 +1307,7 @@ export class LlEmitter {
|
|
|
941
1307
|
this.receiverReaders = new AmbientReceiverReaders(this.fnByName);
|
|
942
1308
|
this.stackCaptures = new StackCaptures(this.fnByName, this.callLifetimes, this.stackCallbacks);
|
|
943
1309
|
this.lazyCaptures = new LazyCaptures(this.fnByName);
|
|
944
|
-
const traced = computeTraced(mod);
|
|
1310
|
+
const traced = computeTraced(mod, dynamicStores, cycleMutability);
|
|
945
1311
|
this.tracedShapes = traced.shapes;
|
|
946
1312
|
this.tracedUnions = traced.unions;
|
|
947
1313
|
// A shape union's value is whichever record it holds, and the collector
|
|
@@ -965,6 +1331,22 @@ export class LlEmitter {
|
|
|
965
1331
|
}
|
|
966
1332
|
}
|
|
967
1333
|
this.shapeHost = {
|
|
1334
|
+
// Journal hooks only on emitters that can emit ranges (chunk
|
|
1335
|
+
// emitters, and emitters whose workers take a journal after the
|
|
1336
|
+
// fork), so the host's optional calls cost nothing otherwise.
|
|
1337
|
+
journalAllocated: !this.journaled
|
|
1338
|
+
? undefined
|
|
1339
|
+
: (name, op, args) => this.journal?.allocated(name, op, args),
|
|
1340
|
+
journalBuilt: !this.journaled ? undefined : () => this.journal?.built(),
|
|
1341
|
+
journalOpened: !this.journaled ? undefined : (op) => this.journal?.opened(op),
|
|
1342
|
+
journalUsed: !this.journaled
|
|
1343
|
+
? undefined
|
|
1344
|
+
: (name, op, args) => this.journal?.used(name, op, args),
|
|
1345
|
+
journalEntry: !this.journaled
|
|
1346
|
+
? undefined
|
|
1347
|
+
: (table, key, value) => this.journal?.entry(table, key, value),
|
|
1348
|
+
compactArrayElem: (elem) => this.compactArrayElem(elem),
|
|
1349
|
+
compactRegion: () => this.compactRegion,
|
|
968
1350
|
sizeType: this.sizeType,
|
|
969
1351
|
cycleBufOffset: this.cycleBufOffset,
|
|
970
1352
|
tracedShapes: this.tracedShapes,
|
|
@@ -1003,9 +1385,16 @@ export class LlEmitter {
|
|
|
1003
1385
|
liveDynRefAdapter: (type) => this.liveDynRefAdapter(type),
|
|
1004
1386
|
usesDynBuiltinStream: () => this.usesDynBuiltinStream,
|
|
1005
1387
|
liveDynUnionRefAdapter: (type) => this.liveDynUnionRefAdapter(type),
|
|
1388
|
+
declBoundary: () => this.mod.declBoundary === true,
|
|
1006
1389
|
dynPromiseAdapter: (type) => this.dynPromiseAdapter(type),
|
|
1007
1390
|
isErrorClass: (name) => this.classMeta.get(name)?.root.def.name === "%Error",
|
|
1008
1391
|
classRootOf: (name) => this.classMeta.get(name)?.root.def.name,
|
|
1392
|
+
releasesNothing: (t) => {
|
|
1393
|
+
if (t.kind !== "object" || (this.shapeHost.regions ?? null) !== null)
|
|
1394
|
+
return false;
|
|
1395
|
+
const meta = this.classMeta.get(t.className);
|
|
1396
|
+
return meta !== undefined && programLifetimeClass(this.shapeHost, meta);
|
|
1397
|
+
},
|
|
1009
1398
|
classSubtypes: (name) => {
|
|
1010
1399
|
const target = this.classMetaOf(name);
|
|
1011
1400
|
const intervals = classMembershipIntervals(this.classMeta, target.def.name);
|
|
@@ -1038,7 +1427,7 @@ export class LlEmitter {
|
|
|
1038
1427
|
if (g.tdz)
|
|
1039
1428
|
this.tdzGlobals.set(g.id, g.name);
|
|
1040
1429
|
}
|
|
1041
|
-
this.stableGlobals = stableGlobals(mod);
|
|
1430
|
+
this.stableGlobals = stableGlobals(mod, this.nodeIndex);
|
|
1042
1431
|
// Runtime error, EventEmitter, stream, EventTarget and Event classes
|
|
1043
1432
|
// have known layouts. Subclasses embed the runtime prefixes from
|
|
1044
1433
|
// classes.ts.
|
|
@@ -1068,6 +1457,34 @@ export class LlEmitter {
|
|
|
1068
1457
|
classDefinitions: (cls, sizeOf) => regions.classDefs(cls, sizeOf),
|
|
1069
1458
|
};
|
|
1070
1459
|
}
|
|
1460
|
+
// ProgramLifetime hierarchies count nothing: their instances get the
|
|
1461
|
+
// 32-bit header and packed fields (classes.ts LlClassMeta.compact),
|
|
1462
|
+
// except where regions count them or a slot word follows the header.
|
|
1463
|
+
if (this.sizeType === "i64" && mod.lifetimeRegions !== true)
|
|
1464
|
+
assignCompactLayouts(this.classMeta, (root) => programLifetimeClass(this.shapeHost, root) && !root.threadSlot, (cls) => classFieldTypes(this.shapeHost, cls, this.int32Slots),
|
|
1465
|
+
// Executables whose region lies below 32 GiB hold compact class
|
|
1466
|
+
// instances there (scr_plr_alloc), so fields referring to one store
|
|
1467
|
+
// a 32-bit reference: the field's type, the class of a
|
|
1468
|
+
// `C | undefined` or `C | null` pointer, or the reference arm of a
|
|
1469
|
+
// nullable pointer field, is a compact class. `C | null | undefined`
|
|
1470
|
+
// keeps the pointer: its null is a sentinel outside the region.
|
|
1471
|
+
mod.lib === undefined && options.lowRegion === true
|
|
1472
|
+
? (cls, i, isCompact) => {
|
|
1473
|
+
const f = cls.fields[i];
|
|
1474
|
+
if (this.inlineUnions.classField(cls.name, f.name))
|
|
1475
|
+
return false;
|
|
1476
|
+
if (this.compactRefType(f.type, isCompact))
|
|
1477
|
+
return true;
|
|
1478
|
+
const nullable = f.type.kind === "union" && this.nullableUnions.single(f.type.unionId) === null
|
|
1479
|
+
? this.nullableFields.get(cls.name, f.name)
|
|
1480
|
+
: null;
|
|
1481
|
+
return nullable !== null && isCompact(nullable.arm.className);
|
|
1482
|
+
}
|
|
1483
|
+
: undefined);
|
|
1484
|
+
this.compactRegion =
|
|
1485
|
+
mod.lib === undefined &&
|
|
1486
|
+
options.lowRegion === true &&
|
|
1487
|
+
[...this.classMeta.values()].some((m) => m.compact);
|
|
1071
1488
|
for (const [name, rec] of RUNTIME_ERROR_CLASSES) {
|
|
1072
1489
|
const meta = this.classMeta.get(name);
|
|
1073
1490
|
if (!meta)
|
|
@@ -1330,16 +1747,33 @@ export class LlEmitter {
|
|
|
1330
1747
|
this.fnDefText.set(fn.name, coroText);
|
|
1331
1748
|
});
|
|
1332
1749
|
}
|
|
1750
|
+
/** Whether a fiberless body running on its caller's stack needs the
|
|
1751
|
+
* frame scr_async_inline_enter/exit keep: it isolates the Error.stack
|
|
1752
|
+
* frame chain, which only stack-observing programs push, as a fresh fiber
|
|
1753
|
+
* would. Other programs run the body with a plain call. The body runs in
|
|
1754
|
+
* its caller's AsyncLocalStorage context either way, as Node runs an async
|
|
1755
|
+
* body up to its first await. The frame also counts the bodies running on
|
|
1756
|
+
* a fiber's stack for the runtime's trap on a fiberless body that
|
|
1757
|
+
* suspends. */
|
|
1758
|
+
get fiberlessFrames() {
|
|
1759
|
+
return this.stackTraces;
|
|
1760
|
+
}
|
|
1333
1761
|
/** The spawn wrapper of a fiberless async function: runs the body on the
|
|
1334
|
-
* caller's stack between scr_async_inline_enter/leave
|
|
1335
|
-
* fresh promise from its outcome — the
|
|
1336
|
-
* without the fiber. */
|
|
1762
|
+
* caller's stack (between scr_async_inline_enter/leave when
|
|
1763
|
+
* fiberlessFrames) and settles a fresh promise from its outcome — the
|
|
1764
|
+
* fiber trampoline's epilogue, without the fiber. */
|
|
1337
1765
|
emitFiberlessAsyncSpawn(fn, spawnParams) {
|
|
1338
1766
|
const ret = fn.returnType;
|
|
1339
1767
|
const retTy = this.llType(ret);
|
|
1340
1768
|
const lifted = fn.captures !== undefined;
|
|
1341
|
-
this.
|
|
1342
|
-
|
|
1769
|
+
const framed = this.fiberlessFrames;
|
|
1770
|
+
if (framed) {
|
|
1771
|
+
this.declare(`declare void @scr_async_inline_enter(ptr)`);
|
|
1772
|
+
this.declare(`declare ptr @scr_async_inline_leave(ptr)`);
|
|
1773
|
+
}
|
|
1774
|
+
else {
|
|
1775
|
+
this.declare(`declare ptr @scr_promise_new()`);
|
|
1776
|
+
}
|
|
1343
1777
|
this.declare(`declare void @scr_promise_reject_pending(ptr)`);
|
|
1344
1778
|
if (lifted) {
|
|
1345
1779
|
this.declare(`declare ptr @scr_closure_retain_v(ptr)`);
|
|
@@ -1349,15 +1783,17 @@ export class LlEmitter {
|
|
|
1349
1783
|
const out = [
|
|
1350
1784
|
`define internal ptr @${mangleAsyncSpawn(fn.name)}(${spawnParams.join(", ")}) ${FN_ATTRS} { ; fiberless ${fn.name}`,
|
|
1351
1785
|
`entry:`,
|
|
1352
|
-
` %frame = alloca { ptr, ptr }
|
|
1786
|
+
...(framed ? [` %frame = alloca { ptr, ptr }`] : []),
|
|
1353
1787
|
// The fiber path holds +1 on a lifted environment for the body's
|
|
1354
1788
|
// duration (packed, released by the trampoline); keep that lifetime.
|
|
1355
1789
|
...(lifted ? [` %env = call ptr @scr_closure_retain_v(ptr %a0)`] : []),
|
|
1356
|
-
` call void @scr_async_inline_enter(ptr %frame)
|
|
1790
|
+
...(framed ? [` call void @scr_async_inline_enter(ptr %frame)`] : []),
|
|
1357
1791
|
retTy === "void" ? ` ${bodyCall}` : ` %r = ${bodyCall}`,
|
|
1358
1792
|
...(lifted ? [` call void @scr_closure_release(ptr %a0)`] : []),
|
|
1359
1793
|
...this.pendingTestLines("%pend"),
|
|
1360
|
-
|
|
1794
|
+
framed
|
|
1795
|
+
? ` %p = call ptr @scr_async_inline_leave(ptr %frame)`
|
|
1796
|
+
: ` %p = call ptr @scr_promise_new()`,
|
|
1361
1797
|
` br i1 %pend, label %thrown, label %clean`,
|
|
1362
1798
|
`clean:`,
|
|
1363
1799
|
...this.asyncFulfillLines(ret, "%p"),
|
|
@@ -1397,24 +1833,94 @@ export class LlEmitter {
|
|
|
1397
1833
|
return false;
|
|
1398
1834
|
return fn.captures === undefined;
|
|
1399
1835
|
}
|
|
1836
|
+
/** Whether a stackless coroutine body's `await f(...)` may await f's
|
|
1837
|
+
* fiber record instead of its promise (emitCoroDirectAwait): f is a
|
|
1838
|
+
* stackless async function whose direct call an await-call entry could
|
|
1839
|
+
* take. The await consumes the promise, so nothing else can observe it.
|
|
1840
|
+
* Worker programs keep the promise for their stop checkpoint. */
|
|
1841
|
+
directAwaitEligible(fnName) {
|
|
1842
|
+
if (this.wasi || this.mod.workers === true || this.currentCoro?.kind !== "async")
|
|
1843
|
+
return false;
|
|
1844
|
+
const fn = this.fnByName.get(fnName);
|
|
1845
|
+
if (fn === undefined || fn.async !== true || fn.generator !== undefined)
|
|
1846
|
+
return false;
|
|
1847
|
+
if (!this.stacklessAsync.has(fnName) || fn.captures !== undefined)
|
|
1848
|
+
return false;
|
|
1849
|
+
if (fn.returnType.kind === "dyn")
|
|
1850
|
+
return false;
|
|
1851
|
+
return fn.asyncCacheGlobal === undefined && fn.asyncCycleCacheGlobal === undefined;
|
|
1852
|
+
}
|
|
1853
|
+
/** A stackless coroutine body's `await f(...)` of a stackless f, without
|
|
1854
|
+
* f's promise object: f's prefix runs as the spawn of a fiber record that
|
|
1855
|
+
* keeps the promise inside. A body still running wakes this coroutine
|
|
1856
|
+
* when it finishes, where its promise's settlement would wake its one
|
|
1857
|
+
* waiter; a finished one takes the settled await's turn. The result (or
|
|
1858
|
+
* the rejection, re-thrown) comes out of the record, which goes. */
|
|
1859
|
+
emitCoroDirectAwait(call, type) {
|
|
1860
|
+
const coro = this.currentCoro;
|
|
1861
|
+
if (coro === null)
|
|
1862
|
+
throw new InternalCompilerError("llvm emitter bug: direct await outside a coroutine");
|
|
1863
|
+
const B = this.B;
|
|
1864
|
+
const record = emitCallExpr(this, call, "direct").name;
|
|
1865
|
+
this.declare(`declare zeroext i1 @scr_coro_direct_prepare(ptr, ptr)`);
|
|
1866
|
+
const suspend = B.tmp();
|
|
1867
|
+
B.line(`${suspend} = call zeroext i1 @scr_coro_direct_prepare(ptr ${coro.self}, ptr ${record})`);
|
|
1868
|
+
const park = B.newLabel("await.suspend");
|
|
1869
|
+
const ready = B.newLabel("await.ready");
|
|
1870
|
+
B.condBr(suspend, park, ready);
|
|
1871
|
+
B.startBlock(park);
|
|
1872
|
+
this.emitCoroSuspendPrepared();
|
|
1873
|
+
B.br(ready);
|
|
1874
|
+
B.startBlock(ready);
|
|
1875
|
+
if (type.kind === "void") {
|
|
1876
|
+
this.declare(`declare void @scr_coro_direct_void(ptr)`);
|
|
1877
|
+
B.line(`call void @scr_coro_direct_void(ptr ${record})`);
|
|
1878
|
+
this.emitPendingCheck();
|
|
1879
|
+
return { name: "", type };
|
|
1880
|
+
}
|
|
1881
|
+
const t = B.tmp();
|
|
1882
|
+
if (type.kind === "f64" || type.kind === "date") {
|
|
1883
|
+
this.declare(`declare double @scr_coro_direct_f64(ptr)`);
|
|
1884
|
+
B.line(`${t} = call double @scr_coro_direct_f64(ptr ${record})`);
|
|
1885
|
+
}
|
|
1886
|
+
else if (type.kind === "bool") {
|
|
1887
|
+
this.declare(`declare zeroext i1 @scr_coro_direct_bool(ptr)`);
|
|
1888
|
+
B.line(`${t} = call zeroext i1 @scr_coro_direct_bool(ptr ${record})`);
|
|
1889
|
+
}
|
|
1890
|
+
else if (type.kind === "string") {
|
|
1891
|
+
this.declare(`declare ptr @scr_coro_direct_str(ptr)`);
|
|
1892
|
+
B.line(`${t} = call ptr @scr_coro_direct_str(ptr ${record})`);
|
|
1893
|
+
}
|
|
1894
|
+
else {
|
|
1895
|
+
this.declare(`declare ptr @scr_coro_direct_ref(ptr)`);
|
|
1896
|
+
B.line(`${t} = call ptr @scr_coro_direct_ref(ptr ${record})`);
|
|
1897
|
+
}
|
|
1898
|
+
const out = this.own({ name: this.adoptHeap(t, type), type });
|
|
1899
|
+
this.emitPendingCheck();
|
|
1900
|
+
return out;
|
|
1901
|
+
}
|
|
1400
1902
|
/** The inline await entry of a fiberless async function (`sc_ai_*`): its
|
|
1401
|
-
* body on the caller's stack between scr_async_inline_enter/exit
|
|
1402
|
-
* its spawn wrapper, returning the result and
|
|
1403
|
-
* the awaiting coroutine (emitCoroInlineAwait). */
|
|
1903
|
+
* body on the caller's stack (between scr_async_inline_enter/exit when
|
|
1904
|
+
* fiberlessFrames), as in its spawn wrapper, returning the result and
|
|
1905
|
+
* leaving a throw pending for the awaiting coroutine (emitCoroInlineAwait). */
|
|
1404
1906
|
emitAsyncInlineAwaitCall(fn) {
|
|
1405
1907
|
const retTy = this.llType(fn.returnType);
|
|
1406
1908
|
const params = fn.params.map((p, i) => `${this.llType(p.type)} %a${i}`);
|
|
1407
1909
|
const args = params.join(", ");
|
|
1408
|
-
this.
|
|
1409
|
-
|
|
1910
|
+
const framed = this.fiberlessFrames;
|
|
1911
|
+
if (framed) {
|
|
1912
|
+
this.declare(`declare void @scr_async_inline_enter(ptr)`);
|
|
1913
|
+
this.declare(`declare void @scr_async_inline_exit(ptr)`);
|
|
1914
|
+
}
|
|
1410
1915
|
const bodyCall = `call ${retTy} @${mangleFunction(fn.name)}(${args})`;
|
|
1411
1916
|
return [
|
|
1412
1917
|
`define internal ${retTy} @${mangleAsyncInlineAwaitCall(fn.name)}(${args}) ${FN_ATTRS} { ; inline await ${fn.name}`,
|
|
1413
1918
|
`entry:`,
|
|
1414
|
-
|
|
1415
|
-
|
|
1919
|
+
...(framed
|
|
1920
|
+
? [` %frame = alloca { ptr, ptr }`, ` call void @scr_async_inline_enter(ptr %frame)`]
|
|
1921
|
+
: []),
|
|
1416
1922
|
retTy === "void" ? ` ${bodyCall}` : ` %r = ${bodyCall}`,
|
|
1417
|
-
` call void @scr_async_inline_exit(ptr %frame)
|
|
1923
|
+
...(framed ? [` call void @scr_async_inline_exit(ptr %frame)`] : []),
|
|
1418
1924
|
retTy === "void" ? ` ret void` : ` ret ${retTy} %r`,
|
|
1419
1925
|
`}`,
|
|
1420
1926
|
``,
|
|
@@ -1457,6 +1963,193 @@ export class LlEmitter {
|
|
|
1457
1963
|
this.emitPendingCheck();
|
|
1458
1964
|
return value;
|
|
1459
1965
|
}
|
|
1966
|
+
/** The entries of `Promise.all(arg)` that a stackless coroutine body's
|
|
1967
|
+
* await may run in place (emitCoroInlinePromiseAll): `arg` is a non-empty
|
|
1968
|
+
* array literal, or the local whose declaration emitStmts deferred to this
|
|
1969
|
+
* await (deferredPromiseAllEntries), whose every entry is a call to a
|
|
1970
|
+
* never-suspending async function, and the result is an array. Null
|
|
1971
|
+
* otherwise. Consumes a deferred local's entries. */
|
|
1972
|
+
inlinePromiseAllEntries(all) {
|
|
1973
|
+
if (all.name !== "promise.all" || all.type.kind !== "promise")
|
|
1974
|
+
return null;
|
|
1975
|
+
if (all.type.inner.kind !== "array")
|
|
1976
|
+
return null;
|
|
1977
|
+
const arg = all.args[0];
|
|
1978
|
+
if (arg?.kind === "varRef") {
|
|
1979
|
+
const deferred = this.deferredPromiseAllEntries.get(arg.localId);
|
|
1980
|
+
if (deferred === undefined)
|
|
1981
|
+
return null;
|
|
1982
|
+
this.deferredPromiseAllEntries.delete(arg.localId);
|
|
1983
|
+
return deferred;
|
|
1984
|
+
}
|
|
1985
|
+
return arg?.kind === "arrayLit" && this.promiseAllInlineable(arg) ? arg : null;
|
|
1986
|
+
}
|
|
1987
|
+
/** Whether every entry of `entries` is a call an await could run in place
|
|
1988
|
+
* (inlineAwaitEligible) that yields its promise's inner type. */
|
|
1989
|
+
promiseAllInlineable(entries) {
|
|
1990
|
+
if (entries.elems.length === 0 || (entries.spreads?.length ?? 0) > 0)
|
|
1991
|
+
return false;
|
|
1992
|
+
if (entries.type.kind !== "array" || entries.type.elem.kind !== "promise")
|
|
1993
|
+
return false;
|
|
1994
|
+
const inner = entries.type.elem.inner;
|
|
1995
|
+
return entries.elems.every((el) => {
|
|
1996
|
+
if (el.kind !== "call" || !this.inlineAwaitEligible(el.callee))
|
|
1997
|
+
return false;
|
|
1998
|
+
const callee = this.fnByName.get(el.callee);
|
|
1999
|
+
return typeEquals(callee.returnType, inner) && !this.callLifetimes.borrowed.has(el.callee);
|
|
2000
|
+
});
|
|
2001
|
+
}
|
|
2002
|
+
/** Whether `stmts[i]` declares a local holding an array literal that only
|
|
2003
|
+
* `stmts[i + 1]` reads, as the operand of `await Promise.all(local)` that
|
|
2004
|
+
* runs first in that statement and may run its entries in place. Nothing
|
|
2005
|
+
* runs between the literal and the await, so the await evaluates the
|
|
2006
|
+
* literal itself (inlinePromiseAllEntries). Debug builds keep the local. */
|
|
2007
|
+
deferredPromiseAllLocal(stmts, i) {
|
|
2008
|
+
const decl = stmts[i];
|
|
2009
|
+
const next = stmts[i + 1];
|
|
2010
|
+
if (this.debug !== null || decl?.kind !== "varDecl" || decl.init?.kind !== "arrayLit")
|
|
2011
|
+
return null;
|
|
2012
|
+
if (this.currentCoro?.kind !== "async" || next === undefined)
|
|
2013
|
+
return null;
|
|
2014
|
+
const operand = next.kind === "varDecl"
|
|
2015
|
+
? next.init
|
|
2016
|
+
: next.kind === "exprStmt"
|
|
2017
|
+
? next.expr
|
|
2018
|
+
: next.kind === "assign"
|
|
2019
|
+
? next.value
|
|
2020
|
+
: null;
|
|
2021
|
+
if (operand?.kind !== "awaitExpr" || operand.adopt === true)
|
|
2022
|
+
return null;
|
|
2023
|
+
const all = operand.value;
|
|
2024
|
+
if (all.kind !== "intrinsic" || all.name !== "promise.all" || all.type.kind !== "promise")
|
|
2025
|
+
return null;
|
|
2026
|
+
if (all.type.inner.kind !== "array")
|
|
2027
|
+
return null;
|
|
2028
|
+
const arg = all.args[0];
|
|
2029
|
+
if (arg?.kind !== "varRef" || arg.localId !== decl.localId)
|
|
2030
|
+
return null;
|
|
2031
|
+
if (!this.promiseAllInlineable(decl.init))
|
|
2032
|
+
return null;
|
|
2033
|
+
if (this.currentLocals.get(decl.localId)?.boxed)
|
|
2034
|
+
return null;
|
|
2035
|
+
// The declaration and this read are the local's only mentions.
|
|
2036
|
+
return countLocalMentions(this.currentFunctionBody, decl.localId) === 2 ? decl.init : null;
|
|
2037
|
+
}
|
|
2038
|
+
/** A stackless coroutine body's `await Promise.all([f(...), ...])` of
|
|
2039
|
+
* never-suspending calls, with Promise.all's turns and without its
|
|
2040
|
+
* promises: the entries run in place in order and their values fill the
|
|
2041
|
+
* result array. Promise.all queues one reaction job per entry, back to
|
|
2042
|
+
* back, and the last of them settles the result, whose await then takes a
|
|
2043
|
+
* turn: here one turn stands for the entries' jobs and a second for the
|
|
2044
|
+
* await. A throwing entry becomes the rejection the await re-throws from
|
|
2045
|
+
* its turn; the remaining entries still run, and later throws are handled
|
|
2046
|
+
* rejections, as Promise.all's subscriptions make them. */
|
|
2047
|
+
emitCoroInlinePromiseAll(entries, type) {
|
|
2048
|
+
if (type.kind !== "array")
|
|
2049
|
+
throw new InternalCompilerError("llvm emitter bug: inline Promise.all result");
|
|
2050
|
+
const B = this.B;
|
|
2051
|
+
const elem = type.elem;
|
|
2052
|
+
const acc = elemAccess(elem);
|
|
2053
|
+
const values = B.tmp();
|
|
2054
|
+
// Up to three values fit in the array's own block (scr_arr_new_*_small).
|
|
2055
|
+
const small = entries.elems.length <= 3;
|
|
2056
|
+
B.line(`${values} = ${arrNewCall(this.shapeHost, elem, small ? "0" : String(entries.elems.length), small)}`);
|
|
2057
|
+
const out = this.own({ name: values, type });
|
|
2058
|
+
this.declare(`declare ptr @scr_promise_new()`);
|
|
2059
|
+
this.declare(`declare void @scr_promise_reject_pending(ptr)`);
|
|
2060
|
+
this.declare(`declare void @scr_promise_mark_handled(ptr)`);
|
|
2061
|
+
const promiseType = entries.type.kind === "array" ? entries.type.elem : type;
|
|
2062
|
+
// Each entry's rejection, owned by the frame: unobserved until the
|
|
2063
|
+
// entries have all run, as Promise.all subscribes only then, so an
|
|
2064
|
+
// entry argument's synchronous throw leaves them unhandled.
|
|
2065
|
+
const rejections = [];
|
|
2066
|
+
for (const entry of entries.elems) {
|
|
2067
|
+
if (entry.kind !== "call")
|
|
2068
|
+
throw new InternalCompilerError("llvm emitter bug: inline Promise.all entry");
|
|
2069
|
+
const slot = B.tmp();
|
|
2070
|
+
B.entryAllocas.push(`${slot} = alloca ptr`);
|
|
2071
|
+
B.line(`store ptr null, ptr ${slot}`);
|
|
2072
|
+
this.ownSlot(slot, promiseType);
|
|
2073
|
+
rejections.push(slot);
|
|
2074
|
+
const value = emitCallExpr(this, entry, "inline");
|
|
2075
|
+
const thrown = B.tmp();
|
|
2076
|
+
for (const line of this.pendingTestLines(thrown))
|
|
2077
|
+
B.line(line.trim());
|
|
2078
|
+
const clean = B.newLabel("pa.clean");
|
|
2079
|
+
const rejected = B.newLabel("pa.rejected");
|
|
2080
|
+
const next = B.newLabel("pa.next");
|
|
2081
|
+
B.condBr(thrown, rejected, clean);
|
|
2082
|
+
B.startBlock(clean);
|
|
2083
|
+
if (acc === "ref")
|
|
2084
|
+
this.toHeap(value);
|
|
2085
|
+
this.arrPush(values, acc, value.name, elem);
|
|
2086
|
+
B.br(next);
|
|
2087
|
+
B.startBlock(rejected);
|
|
2088
|
+
const promise = B.tmp();
|
|
2089
|
+
B.line(`${promise} = call ptr @scr_promise_new()`);
|
|
2090
|
+
B.line(`call void @scr_promise_reject_pending(ptr ${promise})`);
|
|
2091
|
+
B.line(`store ptr ${promise}, ptr ${slot}`);
|
|
2092
|
+
B.br(next);
|
|
2093
|
+
B.startBlock(next);
|
|
2094
|
+
}
|
|
2095
|
+
// Promise.all's subscriptions handle every rejection, and the first
|
|
2096
|
+
// (in entry order) rejects the result.
|
|
2097
|
+
let first = "null";
|
|
2098
|
+
for (let k = rejections.length - 1; k >= 0; k--) {
|
|
2099
|
+
const slot = rejections[k];
|
|
2100
|
+
const rejection = B.tmp();
|
|
2101
|
+
const present = B.tmp();
|
|
2102
|
+
B.line(`${rejection} = load ptr, ptr ${slot}`);
|
|
2103
|
+
B.line(`${present} = icmp ne ptr ${rejection}, null`);
|
|
2104
|
+
const mark = B.newLabel("pa.handled");
|
|
2105
|
+
const after = B.newLabel("pa.unrejected");
|
|
2106
|
+
B.condBr(present, mark, after);
|
|
2107
|
+
B.startBlock(mark);
|
|
2108
|
+
B.line(`call void @scr_promise_mark_handled(ptr ${rejection})`);
|
|
2109
|
+
B.br(after);
|
|
2110
|
+
B.startBlock(after);
|
|
2111
|
+
const chosen = B.tmp();
|
|
2112
|
+
B.line(`${chosen} = select i1 ${present}, ptr ${rejection}, ptr ${first}`);
|
|
2113
|
+
first = chosen;
|
|
2114
|
+
}
|
|
2115
|
+
// The entries' reaction jobs.
|
|
2116
|
+
this.emitCoroAwait(null);
|
|
2117
|
+
const failed = B.tmp();
|
|
2118
|
+
B.line(`${failed} = icmp ne ptr ${first}, null`);
|
|
2119
|
+
const fulfilled = B.newLabel("pa.fulfilled");
|
|
2120
|
+
const rejected = B.newLabel("pa.reject");
|
|
2121
|
+
const join = B.newLabel("pa.join");
|
|
2122
|
+
B.condBr(failed, rejected, fulfilled);
|
|
2123
|
+
B.startBlock(fulfilled);
|
|
2124
|
+
this.emitCoroAwait(null);
|
|
2125
|
+
B.br(join);
|
|
2126
|
+
B.startBlock(rejected);
|
|
2127
|
+
this.declare(`declare void @scr_coro_await_void(ptr)`);
|
|
2128
|
+
this.emitCoroAwait(first);
|
|
2129
|
+
B.line(`call void @scr_coro_await_void(ptr ${first})`);
|
|
2130
|
+
B.br(join);
|
|
2131
|
+
B.startBlock(join);
|
|
2132
|
+
// The rejections are released here, only where an entry threw, rather
|
|
2133
|
+
// than by the frame, which releases each slot whether or not it holds a
|
|
2134
|
+
// promise.
|
|
2135
|
+
this.declare(`declare void @scr_promise_release(ptr)`);
|
|
2136
|
+
for (const slot of rejections) {
|
|
2137
|
+
const rejection = B.tmp();
|
|
2138
|
+
const present = B.tmp();
|
|
2139
|
+
B.line(`${rejection} = load ptr, ptr ${slot}`);
|
|
2140
|
+
B.line(`${present} = icmp ne ptr ${rejection}, null`);
|
|
2141
|
+
const release = B.newLabel("pa.release");
|
|
2142
|
+
const after = B.newLabel("pa.released");
|
|
2143
|
+
B.condBr(present, release, after);
|
|
2144
|
+
B.startBlock(release);
|
|
2145
|
+
B.line(`call void @scr_promise_release(ptr ${rejection})`);
|
|
2146
|
+
B.br(after);
|
|
2147
|
+
B.startBlock(after);
|
|
2148
|
+
}
|
|
2149
|
+
this.disownSlots(rejections.map((ptr) => ({ ptr })));
|
|
2150
|
+
this.emitPendingCheck();
|
|
2151
|
+
return out;
|
|
2152
|
+
}
|
|
1460
2153
|
emitAsyncAwaitCall(fn, argPackLines, adopt = false) {
|
|
1461
2154
|
return emitAsyncAwaitCall(this, fn, argPackLines, adopt);
|
|
1462
2155
|
}
|
|
@@ -1503,6 +2196,7 @@ export class LlEmitter {
|
|
|
1503
2196
|
};
|
|
1504
2197
|
this.literals.set(text, lit);
|
|
1505
2198
|
}
|
|
2199
|
+
this.journal?.entry("literal", text, lit);
|
|
1506
2200
|
const name = `@${lit.sym}`;
|
|
1507
2201
|
this.immortalValues.add(name);
|
|
1508
2202
|
return name;
|
|
@@ -1512,6 +2206,7 @@ export class LlEmitter {
|
|
|
1512
2206
|
literalEquals(text) {
|
|
1513
2207
|
const literal = this.internLiteral(text);
|
|
1514
2208
|
const name = `@sc_streq_${literal.slice("@sc_lit_".length)}`;
|
|
2209
|
+
this.journal?.entry("literalEquality", text, name);
|
|
1515
2210
|
if (!this.literalEqualities.has(text)) {
|
|
1516
2211
|
this.literalEqualities.set(text, name);
|
|
1517
2212
|
if (Buffer.byteLength(text, "utf8") > INLINE_LITERAL_BYTES) {
|
|
@@ -1538,6 +2233,7 @@ export class LlEmitter {
|
|
|
1538
2233
|
lit = { sym: this.contentSymbol("sc_bigint_", key), value };
|
|
1539
2234
|
this.bigintLiterals.set(key, lit);
|
|
1540
2235
|
}
|
|
2236
|
+
this.journal?.entry("bigint", key, { sym: lit.sym, value: lit.value.toString() });
|
|
1541
2237
|
const name = `@${lit.sym}`;
|
|
1542
2238
|
this.immortalValues.add(name);
|
|
1543
2239
|
return name;
|
|
@@ -1550,8 +2246,19 @@ export class LlEmitter {
|
|
|
1550
2246
|
c = { sym: this.contentSymbol("sc_cs_", text), len: Buffer.byteLength(text, "utf8") };
|
|
1551
2247
|
this.cstrs.set(text, c);
|
|
1552
2248
|
}
|
|
2249
|
+
this.journal?.entry("cstr", text, c);
|
|
1553
2250
|
return `@${c.sym}`;
|
|
1554
2251
|
}
|
|
2252
|
+
/** The method-id slot for a constant method name (methodIdSlots). */
|
|
2253
|
+
methodIdSlot(name) {
|
|
2254
|
+
let sym = this.methodIdSlots.get(name);
|
|
2255
|
+
if (!sym) {
|
|
2256
|
+
sym = this.contentSymbol("sc_mid_", name);
|
|
2257
|
+
this.methodIdSlots.set(name, sym);
|
|
2258
|
+
}
|
|
2259
|
+
this.journal?.entry("methodIdSlot", name, sym);
|
|
2260
|
+
return `@${sym}`;
|
|
2261
|
+
}
|
|
1555
2262
|
needBadTag() {
|
|
1556
2263
|
this.needsBadTag = true;
|
|
1557
2264
|
}
|
|
@@ -1565,6 +2272,7 @@ export class LlEmitter {
|
|
|
1565
2272
|
sym = this.contentSymbol("sc_map_ops_", body);
|
|
1566
2273
|
this.mapOpsConsts.set(body, sym);
|
|
1567
2274
|
}
|
|
2275
|
+
this.journal?.entry("mapOps", body, sym);
|
|
1568
2276
|
return `@${sym}`;
|
|
1569
2277
|
}
|
|
1570
2278
|
/** The interned immortal instance for a UNIT arm of a union — asserts
|
|
@@ -1588,6 +2296,7 @@ export class LlEmitter {
|
|
|
1588
2296
|
sym = `sc_unit_${this.unitInstances.size}`;
|
|
1589
2297
|
this.unitInstances.set(key, sym);
|
|
1590
2298
|
}
|
|
2299
|
+
this.journal?.entry("unit", key, sym);
|
|
1591
2300
|
const name = `@${sym}`;
|
|
1592
2301
|
this.immortalValues.add(name);
|
|
1593
2302
|
return name;
|
|
@@ -1600,6 +2309,7 @@ export class LlEmitter {
|
|
|
1600
2309
|
sym = `sc_retype_guard_${this.retypeGuards.size}`;
|
|
1601
2310
|
this.retypeGuards.set(unionId, sym);
|
|
1602
2311
|
}
|
|
2312
|
+
this.journal?.entry("retype", unionId, sym);
|
|
1603
2313
|
return `@${sym}`;
|
|
1604
2314
|
}
|
|
1605
2315
|
/** The immortal ABSENT state of an undefined-armed record field slot
|
|
@@ -1618,6 +2328,7 @@ export class LlEmitter {
|
|
|
1618
2328
|
sym = `sc_absent_${this.absentInstances.size}`;
|
|
1619
2329
|
this.absentInstances.set(unionId, sym);
|
|
1620
2330
|
}
|
|
2331
|
+
this.journal?.entry("absent", unionId, sym);
|
|
1621
2332
|
const name = `@${sym}`;
|
|
1622
2333
|
this.immortalValues.add(name);
|
|
1623
2334
|
return name;
|
|
@@ -1658,6 +2369,7 @@ export class LlEmitter {
|
|
|
1658
2369
|
return out;
|
|
1659
2370
|
}
|
|
1660
2371
|
declare(decl) {
|
|
2372
|
+
this.journal?.entry("decl", decl, null);
|
|
1661
2373
|
this.decls.add(decl);
|
|
1662
2374
|
}
|
|
1663
2375
|
needOom() {
|
|
@@ -1998,8 +2710,10 @@ export class LlEmitter {
|
|
|
1998
2710
|
* releases the dummy (NULL for refcounted kinds) harmlessly. A scalar
|
|
1999
2711
|
* call result of the function's return type may be passed as the unwind's
|
|
2000
2712
|
* dummy value (see emitUnwind). `poll` marks a worker termination poll
|
|
2001
|
-
* (function entry or loop budget), whose test must stay ordered.
|
|
2002
|
-
|
|
2713
|
+
* (function entry or loop budget), whose test must stay ordered. A
|
|
2714
|
+
* `guard` (an i1) limits the test to the paths where it is true: false
|
|
2715
|
+
* where the joined call could not have left anything pending. */
|
|
2716
|
+
emitPendingCheck(passThrough, poll = false, guard) {
|
|
2003
2717
|
const through = passThrough !== undefined &&
|
|
2004
2718
|
this.llType(passThrough.type) === this.llType(this.currentReturnType) &&
|
|
2005
2719
|
(passThrough.type.kind === "f64" || passThrough.type.kind === "bool")
|
|
@@ -2008,6 +2722,13 @@ export class LlEmitter {
|
|
|
2008
2722
|
const B = this.B;
|
|
2009
2723
|
if (B.isTerminated())
|
|
2010
2724
|
return;
|
|
2725
|
+
let skip;
|
|
2726
|
+
if (guard !== undefined) {
|
|
2727
|
+
const test = B.newLabel("exc.t");
|
|
2728
|
+
skip = B.newLabel("exc.n");
|
|
2729
|
+
B.condBr(guard, test, skip);
|
|
2730
|
+
B.startBlock(test);
|
|
2731
|
+
}
|
|
2011
2732
|
if (this.mod.lib !== undefined) {
|
|
2012
2733
|
this.declare(`declare zeroext i1 @scr_exc_pending()`);
|
|
2013
2734
|
const p = B.tmp();
|
|
@@ -2018,6 +2739,10 @@ export class LlEmitter {
|
|
|
2018
2739
|
B.startBlock(lu);
|
|
2019
2740
|
this.emitUnwind(through);
|
|
2020
2741
|
B.startBlock(lk);
|
|
2742
|
+
if (skip !== undefined) {
|
|
2743
|
+
B.br(skip);
|
|
2744
|
+
B.startBlock(skip);
|
|
2745
|
+
}
|
|
2021
2746
|
return;
|
|
2022
2747
|
}
|
|
2023
2748
|
// Executables test the active exception cell's kind inline (its first
|
|
@@ -2094,6 +2819,10 @@ export class LlEmitter {
|
|
|
2094
2819
|
B.startBlock(lu);
|
|
2095
2820
|
this.emitUnwind(through);
|
|
2096
2821
|
B.startBlock(lk);
|
|
2822
|
+
if (skip !== undefined) {
|
|
2823
|
+
B.br(skip);
|
|
2824
|
+
B.startBlock(skip);
|
|
2825
|
+
}
|
|
2097
2826
|
}
|
|
2098
2827
|
/** After a runtime call that ALWAYS leaves an exception pending (the
|
|
2099
2828
|
* compiler-resolved Node throws): the pending test would always answer
|
|
@@ -2641,13 +3370,63 @@ export class LlEmitter {
|
|
|
2641
3370
|
* 1 on hierarchy members, then the flattened field list. Runtime error
|
|
2642
3371
|
* classes GEP through %ScrError (their structs live in the runtime; the
|
|
2643
3372
|
* def's [name, message, %code, %cause] order matches the layout). */
|
|
2644
|
-
classFieldPtr(objName, className, field) {
|
|
3373
|
+
classFieldPtr(objName, className, field, refs = "pointer") {
|
|
2645
3374
|
const meta = this.classMetaOf(className);
|
|
2646
|
-
const { index, type } = classFieldIndex(meta, field);
|
|
3375
|
+
const { index, type, compressed } = classFieldIndex(meta, field, refs);
|
|
2647
3376
|
const p = this.B.tmp();
|
|
2648
3377
|
this.B.line(`${p} = getelementptr inbounds %${classStructSym(className)}, ptr ${objName}, i64 0, i32 ${index}`);
|
|
2649
3378
|
this.markFieldPointer(p, field);
|
|
2650
|
-
|
|
3379
|
+
if (compressed)
|
|
3380
|
+
this.compressedFieldPtrs.add(p);
|
|
3381
|
+
return { ptr: p, type, inline: this.inlineUnions.classField(className, field), compressed };
|
|
3382
|
+
}
|
|
3383
|
+
/** Whether values of `t` are NULL or a compact class instance: `C`,
|
|
3384
|
+
* `C | undefined` or `C | null` for a compact class `C`. `C | null |
|
|
3385
|
+
* undefined` is not: its null is a sentinel outside the region. */
|
|
3386
|
+
compactRefType(t, isCompact = (name) => this.classMeta.get(name)?.compact === true) {
|
|
3387
|
+
if (t.kind === "object")
|
|
3388
|
+
return isCompact(t.className);
|
|
3389
|
+
if (t.kind !== "union")
|
|
3390
|
+
return false;
|
|
3391
|
+
const single = this.nullableUnions.single(t.unionId);
|
|
3392
|
+
return (single !== null &&
|
|
3393
|
+
single.nullTag < 0 &&
|
|
3394
|
+
single.arm.kind === "object" &&
|
|
3395
|
+
isCompact(single.arm.className));
|
|
3396
|
+
}
|
|
3397
|
+
/** Whether arrays of `elem` hold 32-bit references (SCR_ELEM_CREF). */
|
|
3398
|
+
compactArrayElem(elem) {
|
|
3399
|
+
return this.compactRegion && this.compactRefType(elem);
|
|
3400
|
+
}
|
|
3401
|
+
/** Loads the reference a field pointer addresses: a pointer, or the
|
|
3402
|
+
* decoded 32-bit reference of a compressed field (compressedFieldPtrs).
|
|
3403
|
+
* `tagged`: the load carries the field's alias tags. */
|
|
3404
|
+
loadRef(ptr, tagged = true) {
|
|
3405
|
+
const B = this.B;
|
|
3406
|
+
const v = B.tmp();
|
|
3407
|
+
const tags = tagged ? this.fieldAliasAttachment(ptr) : "";
|
|
3408
|
+
if (!this.compressedFieldPtrs.has(ptr)) {
|
|
3409
|
+
B.line(`${v} = load ptr, ptr ${ptr}${tags}`);
|
|
3410
|
+
return v;
|
|
3411
|
+
}
|
|
3412
|
+
const idx = B.tmp();
|
|
3413
|
+
B.line(`${idx} = load i32, ptr ${ptr}${tags}`);
|
|
3414
|
+
for (const line of compactRefLoadLines(idx, v, `${v}.r`))
|
|
3415
|
+
B.line(line.trimStart());
|
|
3416
|
+
return v;
|
|
3417
|
+
}
|
|
3418
|
+
/** Stores `value` (a pointer) through a field pointer: as is, or encoded
|
|
3419
|
+
* as the 32-bit reference of a compressed field. */
|
|
3420
|
+
storeRef(ptr, value) {
|
|
3421
|
+
const B = this.B;
|
|
3422
|
+
if (!this.compressedFieldPtrs.has(ptr)) {
|
|
3423
|
+
B.line(`store ptr ${value}, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
3424
|
+
return;
|
|
3425
|
+
}
|
|
3426
|
+
const idx = B.tmp();
|
|
3427
|
+
for (const line of compactRefStoreLines(value, idx, `${idx}.r`))
|
|
3428
|
+
B.line(line.trimStart());
|
|
3429
|
+
B.line(`store i32 ${idx}, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
2651
3430
|
}
|
|
2652
3431
|
/** The dynamic class's preorder number (borrowed object; the static class
|
|
2653
3432
|
* names the struct spelling and where the number is, classPreLines). */
|
|
@@ -2667,6 +3446,7 @@ export class LlEmitter {
|
|
|
2667
3446
|
const meta = this.classMetaOf(className);
|
|
2668
3447
|
this.classObjs.set(className, { nameSym: this.internLiteral(classJsName(meta.def)) });
|
|
2669
3448
|
}
|
|
3449
|
+
this.journal?.entry("classObj", className, this.classObjs.get(className));
|
|
2670
3450
|
return mangleClassObj(className);
|
|
2671
3451
|
}
|
|
2672
3452
|
// ── record plumbing ─────────────────────────────────────────────────────
|
|
@@ -2754,6 +3534,8 @@ export class LlEmitter {
|
|
|
2754
3534
|
const { tag, bits } = loadInlineUnion(B, ptr);
|
|
2755
3535
|
return stackUnionBox(B, this.sizeType, tag, bits);
|
|
2756
3536
|
}
|
|
3537
|
+
if (this.compressedFieldPtrs.has(ptr))
|
|
3538
|
+
return this.loadRef(ptr);
|
|
2757
3539
|
const fieldTy = llFieldType(t, false);
|
|
2758
3540
|
const raw = B.tmp();
|
|
2759
3541
|
B.line(`${raw} = load ${fieldTy}, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
@@ -2778,8 +3560,7 @@ export class LlEmitter {
|
|
|
2778
3560
|
replaceField(ptr, type, inline, v) {
|
|
2779
3561
|
if (!inline && isRefCounted(type)) {
|
|
2780
3562
|
this.toHeap(v);
|
|
2781
|
-
const old = this.
|
|
2782
|
-
this.B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
3563
|
+
const old = this.loadRef(ptr, false);
|
|
2783
3564
|
this.storeField(ptr, type, v.name, false);
|
|
2784
3565
|
this.releaseHeap(old, type);
|
|
2785
3566
|
return;
|
|
@@ -2802,6 +3583,10 @@ export class LlEmitter {
|
|
|
2802
3583
|
storeInlineUnion(B, ptr, tag, bits);
|
|
2803
3584
|
return;
|
|
2804
3585
|
}
|
|
3586
|
+
if (this.compressedFieldPtrs.has(ptr)) {
|
|
3587
|
+
this.storeRef(ptr, value);
|
|
3588
|
+
return;
|
|
3589
|
+
}
|
|
2805
3590
|
const fieldTy = llFieldType(t, false);
|
|
2806
3591
|
if (fieldTy !== "i8") {
|
|
2807
3592
|
B.line(`store ${fieldTy} ${value}, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
@@ -2850,12 +3635,12 @@ export class LlEmitter {
|
|
|
2850
3635
|
// ── bindings ────────────────────────────────────────────────────────────
|
|
2851
3636
|
/** A binding's storage: a module global, a plain local slot, or a boxed
|
|
2852
3637
|
* local (the slot holds the capture BOX; access goes through it). */
|
|
2853
|
-
matchBytesLoopVersion(s, counted) {
|
|
2854
|
-
const fn = this.bytesLoopFunction;
|
|
3638
|
+
matchBytesLoopVersion(s, counted, paired = null) {
|
|
3639
|
+
const fn = LOOPS.of(this).bytesLoopFunction;
|
|
2855
3640
|
if (!fn)
|
|
2856
3641
|
return null;
|
|
2857
|
-
this.bytesLoopEntries ??= findInitializedByteLoopBindings(fn);
|
|
2858
|
-
const initialized = this.bytesLoopEntries.get(s);
|
|
3642
|
+
LOOPS.of(this).bytesLoopEntries ??= findInitializedByteLoopBindings(fn);
|
|
3643
|
+
const initialized = LOOPS.of(this).bytesLoopEntries.get(s);
|
|
2859
3644
|
if (!initialized)
|
|
2860
3645
|
return null;
|
|
2861
3646
|
const invariantGlobals = new Set(this.stableGlobals);
|
|
@@ -2868,7 +3653,10 @@ export class LlEmitter {
|
|
|
2868
3653
|
ranges: this.integerRanges,
|
|
2869
3654
|
initialized,
|
|
2870
3655
|
proven: this.bytesBounds,
|
|
2871
|
-
|
|
3656
|
+
workers: this.mod.workers === true,
|
|
3657
|
+
owned: this.bytesOwned,
|
|
3658
|
+
scalarStrings: new Set(this.stringSlices.keys()),
|
|
3659
|
+
}, paired);
|
|
2872
3660
|
}
|
|
2873
3661
|
/** The alias tag of a whole-slot load of a binding (module globals only). */
|
|
2874
3662
|
slotAlias(id) {
|
|
@@ -2907,6 +3695,24 @@ export class LlEmitter {
|
|
|
2907
3695
|
this.B.line(`${b} = load ptr, ptr ${slot}`);
|
|
2908
3696
|
return b;
|
|
2909
3697
|
}
|
|
3698
|
+
/** The function a call through `callee` is known to reach (a literal
|
|
3699
|
+
* closure, or a binding the constant-callback census resolves) and the
|
|
3700
|
+
* entry it calls directly. Async and generator functions stay indirect. */
|
|
3701
|
+
knownCallbackTarget(callee) {
|
|
3702
|
+
const knownName = callee.kind === "closure"
|
|
3703
|
+
? callee.fnName
|
|
3704
|
+
: callee.kind === "varRef"
|
|
3705
|
+
? this.currentConstantCallbacks.get(callee.localId)
|
|
3706
|
+
: undefined;
|
|
3707
|
+
const known = knownName ? this.fnByName.get(knownName) : undefined;
|
|
3708
|
+
if (!known || known.async || known.generator)
|
|
3709
|
+
return undefined;
|
|
3710
|
+
if (known.captures === undefined) {
|
|
3711
|
+
this.fnValues.add(known.name);
|
|
3712
|
+
return { known, direct: `@${mangleWrapper(known.name)}` };
|
|
3713
|
+
}
|
|
3714
|
+
return { known, direct: `@${this.callTarget(known.name)}` };
|
|
3715
|
+
}
|
|
2910
3716
|
/** The payload slot of a capture box (ScrBox.slot, field 5). */
|
|
2911
3717
|
boxSlot(box) {
|
|
2912
3718
|
const slot = this.B.tmp();
|
|
@@ -2919,13 +3725,15 @@ export class LlEmitter {
|
|
|
2919
3725
|
const r = B.tmp();
|
|
2920
3726
|
// Scalar payloads are read in place (scr_box_get_f64/bool are a
|
|
2921
3727
|
// memcpy and a nonzero test of the same slot), so LLVM can keep a
|
|
2922
|
-
// captured number in a register across a loop of calls.
|
|
3728
|
+
// captured number in a register across a loop of calls. They have an
|
|
3729
|
+
// alias category of their own: every other access to a box's payload
|
|
3730
|
+
// is untagged or a runtime call.
|
|
2923
3731
|
if (acc === "f64") {
|
|
2924
|
-
B.line(`${r} = load double, ptr ${this.boxSlot(box)}`);
|
|
3732
|
+
B.line(`${r} = load double, ptr ${this.boxSlot(box)}${this.memoryAliasAttachment("box:scalar")}`);
|
|
2925
3733
|
}
|
|
2926
3734
|
else if (acc === "bool") {
|
|
2927
3735
|
const raw = B.tmp();
|
|
2928
|
-
B.line(`${raw} = load i64, ptr ${this.boxSlot(box)}`);
|
|
3736
|
+
B.line(`${raw} = load i64, ptr ${this.boxSlot(box)}${this.memoryAliasAttachment("box:scalar")}`);
|
|
2929
3737
|
B.line(`${r} = icmp ne i64 ${raw}, 0`);
|
|
2930
3738
|
}
|
|
2931
3739
|
else {
|
|
@@ -2939,12 +3747,12 @@ export class LlEmitter {
|
|
|
2939
3747
|
const B = this.B;
|
|
2940
3748
|
const acc = boxAccess(t);
|
|
2941
3749
|
if (acc === "f64") {
|
|
2942
|
-
B.line(`store double ${value}, ptr ${this.boxSlot(box)}`);
|
|
3750
|
+
B.line(`store double ${value}, ptr ${this.boxSlot(box)}${this.memoryAliasAttachment("box:scalar")}`);
|
|
2943
3751
|
}
|
|
2944
3752
|
else if (acc === "bool") {
|
|
2945
3753
|
const raw = B.tmp();
|
|
2946
3754
|
B.line(`${raw} = zext i1 ${value} to i64`);
|
|
2947
|
-
B.line(`store i64 ${raw}, ptr ${this.boxSlot(box)}`);
|
|
3755
|
+
B.line(`store i64 ${raw}, ptr ${this.boxSlot(box)}${this.memoryAliasAttachment("box:scalar")}`);
|
|
2948
3756
|
}
|
|
2949
3757
|
else {
|
|
2950
3758
|
this.declare(`declare void @scr_box_set_ref(ptr, ptr)`);
|
|
@@ -2992,7 +3800,7 @@ export class LlEmitter {
|
|
|
2992
3800
|
const acc = boxAccess(t);
|
|
2993
3801
|
const cell = B.tmp();
|
|
2994
3802
|
B.line(`${cell} = ${arrNewCall(this.shapeHost, t, "1")} ; TDZ cell`);
|
|
2995
|
-
this.arrPush(cell, acc === "bool" ? "bool" : "f64", value);
|
|
3803
|
+
this.arrPush(cell, acc === "bool" ? "bool" : "f64", value, null);
|
|
2996
3804
|
this.declare(`declare void @scr_box_set_ref(ptr, ptr)`);
|
|
2997
3805
|
B.line(`call void @scr_box_set_ref(ptr ${box}, ptr ${cell})`);
|
|
2998
3806
|
}
|
|
@@ -3282,6 +4090,171 @@ export class LlEmitter {
|
|
|
3282
4090
|
emitFunction(fn) {
|
|
3283
4091
|
return emitFunction(this, fn);
|
|
3284
4092
|
}
|
|
4093
|
+
/** What this range emitter (chunkEmitter) hands the merging emitter, as
|
|
4094
|
+
* plain data a worker process can write: its journal and the sets and
|
|
4095
|
+
* flags its functions set. */
|
|
4096
|
+
chunkResult() {
|
|
4097
|
+
return {
|
|
4098
|
+
entries: this.journal.entries,
|
|
4099
|
+
flags: {
|
|
4100
|
+
usesCoroutines: this.usesCoroutines,
|
|
4101
|
+
usesTimers: this.usesTimers,
|
|
4102
|
+
usesGenSlots: this.usesGenSlots,
|
|
4103
|
+
needsUnionNone: this.needsUnionNone,
|
|
4104
|
+
needsNullableAbsent: this.needsNullableAbsent,
|
|
4105
|
+
needsOom: this.needsOom,
|
|
4106
|
+
needsBadTag: this.needsBadTag,
|
|
4107
|
+
needsBadKey: this.needsBadKey,
|
|
4108
|
+
needsRetainBox: this.needsRetainBox,
|
|
4109
|
+
},
|
|
4110
|
+
publishedNamesSym: this.publishedNamesSym,
|
|
4111
|
+
rcHelpers: this.rcHelpers === null ? [] : [...this.rcHelpers],
|
|
4112
|
+
immortalValues: [...this.immortalValues],
|
|
4113
|
+
fnValues: [...this.fnValues],
|
|
4114
|
+
arraySearchKinds: [...this.arraySearchKinds],
|
|
4115
|
+
recordCloneShapes: [...this.recordCloneShapes],
|
|
4116
|
+
awaitCallees: [...this.awaitCallees],
|
|
4117
|
+
adoptCallees: [...this.adoptCallees],
|
|
4118
|
+
directAwaitCallees: [...this.directAwaitCallees],
|
|
4119
|
+
inlineAwaitCallees: [...this.inlineAwaitCallees],
|
|
4120
|
+
};
|
|
4121
|
+
}
|
|
4122
|
+
/** Merges a range emitter's result (chunkResult) into this emitter, in
|
|
4123
|
+
* the range's order, and answers the rename of the range's text to this
|
|
4124
|
+
* emitter's numbered helpers. Ranges merge in function order. */
|
|
4125
|
+
mergeChunk(chunk) {
|
|
4126
|
+
const names = new Map();
|
|
4127
|
+
const tags = new Map();
|
|
4128
|
+
// The range's helpers and table entries first, in its order; then the
|
|
4129
|
+
// sets and flags, which replayed definitions must find as serial
|
|
4130
|
+
// emission left them (a helper set guards the declarations its first
|
|
4131
|
+
// request adds).
|
|
4132
|
+
replayJournal(this, chunk.entries, names, tags);
|
|
4133
|
+
const flags = chunk.flags;
|
|
4134
|
+
this.usesCoroutines ||= flags.usesCoroutines;
|
|
4135
|
+
this.usesTimers ||= flags.usesTimers;
|
|
4136
|
+
this.usesGenSlots ||= flags.usesGenSlots;
|
|
4137
|
+
this.needsUnionNone ||= flags.needsUnionNone;
|
|
4138
|
+
this.needsNullableAbsent ||= flags.needsNullableAbsent;
|
|
4139
|
+
this.needsOom ||= flags.needsOom;
|
|
4140
|
+
this.needsBadTag ||= flags.needsBadTag;
|
|
4141
|
+
this.needsBadKey ||= flags.needsBadKey;
|
|
4142
|
+
this.needsRetainBox ||= flags.needsRetainBox;
|
|
4143
|
+
this.publishedNamesSym ??= chunk.publishedNamesSym;
|
|
4144
|
+
if (this.rcHelpers !== null)
|
|
4145
|
+
for (const key of chunk.rcHelpers)
|
|
4146
|
+
this.rcHelpers.add(key);
|
|
4147
|
+
for (const name of chunk.immortalValues)
|
|
4148
|
+
this.immortalValues.add(name);
|
|
4149
|
+
for (const name of chunk.fnValues)
|
|
4150
|
+
this.fnValues.add(name);
|
|
4151
|
+
for (const kind of chunk.arraySearchKinds)
|
|
4152
|
+
this.arraySearchKinds.add(kind);
|
|
4153
|
+
for (const shapeId of chunk.recordCloneShapes)
|
|
4154
|
+
this.recordCloneShapes.add(shapeId);
|
|
4155
|
+
for (const name of chunk.awaitCallees)
|
|
4156
|
+
this.awaitCallees.add(name);
|
|
4157
|
+
for (const name of chunk.adoptCallees)
|
|
4158
|
+
this.adoptCallees.add(name);
|
|
4159
|
+
for (const name of chunk.directAwaitCallees)
|
|
4160
|
+
this.directAwaitCallees.add(name);
|
|
4161
|
+
for (const name of chunk.inlineAwaitCallees)
|
|
4162
|
+
this.inlineAwaitCallees.add(name);
|
|
4163
|
+
return renameChunk(names, tags);
|
|
4164
|
+
}
|
|
4165
|
+
/** Adds a content-named constant a chunk interned. Its symbol is this
|
|
4166
|
+
* emitter's own: a digest collision retries in first-use order, which a
|
|
4167
|
+
* chunk alone does not know. */
|
|
4168
|
+
addContentEntry(into, key, entry, prefix, names) {
|
|
4169
|
+
let own = into.get(key);
|
|
4170
|
+
if (own === undefined) {
|
|
4171
|
+
own = { ...entry, sym: this.contentSymbol(prefix, key) };
|
|
4172
|
+
into.set(key, own);
|
|
4173
|
+
}
|
|
4174
|
+
if (own.sym !== entry.sym)
|
|
4175
|
+
names.set(entry.sym, own.sym);
|
|
4176
|
+
}
|
|
4177
|
+
/** Applies a chunk's table entry (EmitJournal.entry) at its place in the
|
|
4178
|
+
* chunk's order: a key this emitter lacks is added, numbered after its
|
|
4179
|
+
* own entries where the table numbers them, and the chunk's name for it
|
|
4180
|
+
* is renamed to this emitter's. */
|
|
4181
|
+
applyJournalEntry(table, key, value, names, tags) {
|
|
4182
|
+
switch (table) {
|
|
4183
|
+
case "decl":
|
|
4184
|
+
this.decls.add(key);
|
|
4185
|
+
return;
|
|
4186
|
+
case "literal":
|
|
4187
|
+
this.addContentEntry(this.literals, key, value, "sc_lit_", names);
|
|
4188
|
+
return;
|
|
4189
|
+
case "literalEquality":
|
|
4190
|
+
addEntry(this.literalEqualities, key, value);
|
|
4191
|
+
return;
|
|
4192
|
+
case "bigint":
|
|
4193
|
+
{
|
|
4194
|
+
const entry = value;
|
|
4195
|
+
this.addContentEntry(this.bigintLiterals, key, { sym: entry.sym, value: BigInt(entry.value) }, "sc_bigint_", names);
|
|
4196
|
+
}
|
|
4197
|
+
return;
|
|
4198
|
+
case "cstr":
|
|
4199
|
+
this.addContentEntry(this.cstrs, key, value, "sc_cs_", names);
|
|
4200
|
+
return;
|
|
4201
|
+
case "mapOps": {
|
|
4202
|
+
let own = this.mapOpsConsts.get(key);
|
|
4203
|
+
if (own === undefined) {
|
|
4204
|
+
own = this.contentSymbol("sc_map_ops_", key);
|
|
4205
|
+
this.mapOpsConsts.set(key, own);
|
|
4206
|
+
}
|
|
4207
|
+
if (own !== value)
|
|
4208
|
+
names.set(value, own);
|
|
4209
|
+
return;
|
|
4210
|
+
}
|
|
4211
|
+
case "methodIdSlot": {
|
|
4212
|
+
let own = this.methodIdSlots.get(key);
|
|
4213
|
+
if (own === undefined) {
|
|
4214
|
+
own = this.contentSymbol("sc_mid_", key);
|
|
4215
|
+
this.methodIdSlots.set(key, own);
|
|
4216
|
+
}
|
|
4217
|
+
if (own !== value)
|
|
4218
|
+
names.set(value, own);
|
|
4219
|
+
return;
|
|
4220
|
+
}
|
|
4221
|
+
case "classObj":
|
|
4222
|
+
addEntry(this.classObjs, key, value);
|
|
4223
|
+
return;
|
|
4224
|
+
case "retainWrapper":
|
|
4225
|
+
addEntry(this.nullableUnions.retainWrappers, key, value);
|
|
4226
|
+
return;
|
|
4227
|
+
case "unit":
|
|
4228
|
+
return addNumbered(this.unitInstances, key, value, "sc_unit_", names);
|
|
4229
|
+
case "absent":
|
|
4230
|
+
return addNumbered(this.absentInstances, key, value, "sc_absent_", names);
|
|
4231
|
+
case "retype":
|
|
4232
|
+
return addNumbered(this.retypeGuards, key, value, "sc_retype_guard_", names);
|
|
4233
|
+
case "slots":
|
|
4234
|
+
return addNumbered(this.threadSlotsBlocks, key, value, "@sc_slots_", names);
|
|
4235
|
+
case "regex":
|
|
4236
|
+
return addNumberedSymbol(this.regexInstances, key, value, "sc_re_", names);
|
|
4237
|
+
case "templateStrings":
|
|
4238
|
+
return addNumberedSymbol(this.templateStringsInstances, key, value, "sc_tsa_", names);
|
|
4239
|
+
case "tag": {
|
|
4240
|
+
let own = this.fieldAliasTags.get(key);
|
|
4241
|
+
if (own === undefined) {
|
|
4242
|
+
own = 2 + this.fieldAliasTags.size * 2;
|
|
4243
|
+
this.fieldAliasTags.set(key, own);
|
|
4244
|
+
}
|
|
4245
|
+
if (own !== value)
|
|
4246
|
+
tags.set(value, own);
|
|
4247
|
+
return;
|
|
4248
|
+
}
|
|
4249
|
+
default:
|
|
4250
|
+
throw new InternalCompilerError(`llvm emitter bug: no journal table ${table}`);
|
|
4251
|
+
}
|
|
4252
|
+
}
|
|
4253
|
+
/** An emitter for a range of this module's functions: the same facts,
|
|
4254
|
+
* empty module-level tables, and a journal of what the range adds. */
|
|
4255
|
+
chunkEmitter() {
|
|
4256
|
+
return new LlEmitter(this.mod, { ...this.targetOptions, functionChunks: 1 }, new EmitJournal());
|
|
4257
|
+
}
|
|
3285
4258
|
/** The double-ABI entry of a function with an i32 entry: every caller
|
|
3286
4259
|
* that is not a direct call (closures, dispatch, adapters, the runtime)
|
|
3287
4260
|
* enters here. A pending exception passes through to its caller. */
|
|
@@ -3833,6 +4806,11 @@ export class LlEmitter {
|
|
|
3833
4806
|
if (cursor)
|
|
3834
4807
|
cursor.index = i;
|
|
3835
4808
|
this.stmtCursor = cursor;
|
|
4809
|
+
const deferred = this.deferredPromiseAllLocal(stmts, i);
|
|
4810
|
+
if (deferred !== null) {
|
|
4811
|
+
this.deferredPromiseAllEntries.set(stmts[i].localId, deferred);
|
|
4812
|
+
continue;
|
|
4813
|
+
}
|
|
3836
4814
|
this.emitStmt(stmts[i]);
|
|
3837
4815
|
}
|
|
3838
4816
|
}
|
|
@@ -3872,11 +4850,15 @@ export class LlEmitter {
|
|
|
3872
4850
|
const loop = s.kind === "while" || s.kind === "doWhile" || s.kind === "for" || s.kind === "forOf";
|
|
3873
4851
|
if (loop)
|
|
3874
4852
|
this.loopDepth++;
|
|
4853
|
+
// An int32 kind loop's fast-copy write leaves for its resume point.
|
|
4854
|
+
const kindResume = this.int32KindResume;
|
|
4855
|
+
this.int32KindResume = this.int32Kinds?.resume.get(s) ?? null;
|
|
3875
4856
|
try {
|
|
3876
4857
|
this.emitStmtBody(s);
|
|
3877
4858
|
}
|
|
3878
4859
|
finally {
|
|
3879
4860
|
this.B.debugLocation = previous;
|
|
4861
|
+
this.int32KindResume = kindResume;
|
|
3880
4862
|
if (loop)
|
|
3881
4863
|
this.loopDepth--;
|
|
3882
4864
|
}
|
|
@@ -4200,6 +5182,7 @@ export class LlEmitter {
|
|
|
4200
5182
|
sym = `@sc_slots_${this.threadSlotsBlocks.size}`;
|
|
4201
5183
|
this.threadSlotsBlocks.set(name, sym);
|
|
4202
5184
|
}
|
|
5185
|
+
this.journal?.entry("slots", name, sym);
|
|
4203
5186
|
return sym;
|
|
4204
5187
|
}
|
|
4205
5188
|
/** InternTable's runtime calls (scr_itable.c). Table and entry handles
|
|
@@ -4353,6 +5336,20 @@ export class LlEmitter {
|
|
|
4353
5336
|
return this.publishWalkersCache;
|
|
4354
5337
|
const byPre = [...this.classMeta.values()].sort((a, b) => a.pre - b.pre);
|
|
4355
5338
|
this.publishWalkersCache = new PublishWalkers({
|
|
5339
|
+
// Journal hooks only on emitters that can emit ranges (chunk
|
|
5340
|
+
// emitters, and emitters whose workers take a journal after the
|
|
5341
|
+
// fork), so the host's optional calls cost nothing otherwise.
|
|
5342
|
+
journalAllocated: !this.journaled
|
|
5343
|
+
? undefined
|
|
5344
|
+
: (name, op, args) => this.journal?.allocated(name, op, args),
|
|
5345
|
+
journalBuilt: !this.journaled ? undefined : () => this.journal?.built(),
|
|
5346
|
+
journalOpened: !this.journaled ? undefined : (op) => this.journal?.opened(op),
|
|
5347
|
+
journalUsed: !this.journaled
|
|
5348
|
+
? undefined
|
|
5349
|
+
: (name, op, args) => this.journal?.used(name, op, args),
|
|
5350
|
+
journalEntry: !this.journaled
|
|
5351
|
+
? undefined
|
|
5352
|
+
: (table, key, value) => this.journal?.entry(table, key, value),
|
|
4356
5353
|
declare: (decl) => this.declare(decl),
|
|
4357
5354
|
cstr: (text) => this.cstr(text),
|
|
4358
5355
|
sizeType: this.sizeType,
|
|
@@ -4376,14 +5373,16 @@ export class LlEmitter {
|
|
|
4376
5373
|
post: meta.post,
|
|
4377
5374
|
runtimeRooted: meta.root.def.runtime === true,
|
|
4378
5375
|
idInRc: meta.idInRc,
|
|
5376
|
+
compact: meta.compact,
|
|
4379
5377
|
// Inline scalar-union fields are plain bits: nothing to push.
|
|
4380
5378
|
fields: meta.def.fields.flatMap((f) => this.inlineUnions.classField(className, f.name)
|
|
4381
5379
|
? []
|
|
4382
5380
|
: [
|
|
4383
5381
|
{
|
|
4384
5382
|
name: f.name,
|
|
4385
|
-
index: classFieldIndex(meta, f.name).index,
|
|
5383
|
+
index: classFieldIndex(meta, f.name, "compressed").index,
|
|
4386
5384
|
type: this.nullableFields.storageType(className, f.name, f.type),
|
|
5385
|
+
compressed: classFieldIndex(meta, f.name, "compressed").compressed,
|
|
4387
5386
|
},
|
|
4388
5387
|
]),
|
|
4389
5388
|
};
|
|
@@ -4414,13 +5413,20 @@ export class LlEmitter {
|
|
|
4414
5413
|
}
|
|
4415
5414
|
/** Branches on "`obj` is published" (rc == SIZE_MAX, or a count of
|
|
4416
5415
|
* UINT32_MAX in the low half for `count` i32: classes.ts
|
|
4417
|
-
* LlClassMeta.idInRc
|
|
4418
|
-
* the
|
|
5416
|
+
* LlClassMeta.idInRc, or the top bit of a compact header word for
|
|
5417
|
+
* "compact": classes.ts COMPACT_PUBLISHED); leaves the builder in the cold
|
|
5418
|
+
* block and answers the continuation label. */
|
|
4419
5419
|
emitPublishedTest(obj, count = this.sizeType) {
|
|
4420
5420
|
const B = this.B;
|
|
4421
5421
|
const rc = B.tmp(), frozen = B.tmp(), expected = B.tmp();
|
|
4422
|
-
|
|
4423
|
-
|
|
5422
|
+
if (count === "compact") {
|
|
5423
|
+
B.line(`${rc} = load i32, ptr ${obj}`);
|
|
5424
|
+
B.line(`${frozen} = icmp slt i32 ${rc}, 0`);
|
|
5425
|
+
}
|
|
5426
|
+
else {
|
|
5427
|
+
B.line(`${rc} = load ${count}, ptr ${obj}`);
|
|
5428
|
+
B.line(`${frozen} = icmp eq ${count} ${rc}, -1`);
|
|
5429
|
+
}
|
|
4424
5430
|
this.declare(`declare i1 @llvm.expect.i1(i1, i1)`);
|
|
4425
5431
|
B.line(`${expected} = call i1 @llvm.expect.i1(i1 ${frozen}, i1 false)`);
|
|
4426
5432
|
const cold = B.newLabel("pub.frozen"), ok = B.newLabel("pub.ok");
|
|
@@ -4428,6 +5434,33 @@ export class LlEmitter {
|
|
|
4428
5434
|
B.startBlock(cold);
|
|
4429
5435
|
return ok;
|
|
4430
5436
|
}
|
|
5437
|
+
/** Branches on "the array `arr` is frozen" (SCR_ARR_FROZEN in its storage
|
|
5438
|
+
* flags, scr_array.h), or published too when `published`; like
|
|
5439
|
+
* emitPublishedTest, leaves the builder in the cold block and answers the
|
|
5440
|
+
* continuation label. */
|
|
5441
|
+
emitFrozenArrayTest(arr, published) {
|
|
5442
|
+
const B = this.B;
|
|
5443
|
+
const sparep = B.tmp(), spare = B.tmp(), bit = B.tmp();
|
|
5444
|
+
let frozen = B.tmp();
|
|
5445
|
+
B.line(`${sparep} = getelementptr inbounds %ScrArr, ptr ${arr}, i32 0, i32 ${SCR_ARR_FIELD.spare}`);
|
|
5446
|
+
B.line(`${spare} = load i16, ptr ${sparep}`);
|
|
5447
|
+
B.line(`${bit} = and i16 ${spare}, ${SCR_ARR_FROZEN}`);
|
|
5448
|
+
B.line(`${frozen} = icmp ne i16 ${bit}, 0`);
|
|
5449
|
+
if (published) {
|
|
5450
|
+
const rc = B.tmp(), immortal = B.tmp(), either = B.tmp();
|
|
5451
|
+
B.line(`${rc} = load ${this.sizeType}, ptr ${arr}`);
|
|
5452
|
+
B.line(`${immortal} = icmp eq ${this.sizeType} ${rc}, -1`);
|
|
5453
|
+
B.line(`${either} = or i1 ${frozen}, ${immortal}`);
|
|
5454
|
+
frozen = either;
|
|
5455
|
+
}
|
|
5456
|
+
this.declare(`declare i1 @llvm.expect.i1(i1, i1)`);
|
|
5457
|
+
const expected = B.tmp();
|
|
5458
|
+
B.line(`${expected} = call i1 @llvm.expect.i1(i1 ${frozen}, i1 false)`);
|
|
5459
|
+
const cold = B.newLabel("arr.frozen"), ok = B.newLabel("arr.ok");
|
|
5460
|
+
B.condBr(expected, cold, ok);
|
|
5461
|
+
B.startBlock(cold);
|
|
5462
|
+
return ok;
|
|
5463
|
+
}
|
|
4431
5464
|
publishedNamesSym = null;
|
|
4432
5465
|
/** The class-name table the hierarchy field guards index by preorder. */
|
|
4433
5466
|
publishedClassNamesDefs() {
|
|
@@ -4461,7 +5494,7 @@ export class LlEmitter {
|
|
|
4461
5494
|
return;
|
|
4462
5495
|
const B = this.B;
|
|
4463
5496
|
const meta = className === null ? undefined : this.classMeta.get(className);
|
|
4464
|
-
const ok = this.emitPublishedTest(obj, meta?.idInRc === true ? "i32" : this.sizeType);
|
|
5497
|
+
const ok = this.emitPublishedTest(obj, meta?.compact === true ? "compact" : meta?.idInRc === true ? "i32" : this.sizeType);
|
|
4465
5498
|
let owner;
|
|
4466
5499
|
if (meta === undefined)
|
|
4467
5500
|
owner = this.cstr("Object");
|
|
@@ -4482,14 +5515,24 @@ export class LlEmitter {
|
|
|
4482
5515
|
}
|
|
4483
5516
|
/** The frozen-array guard (scr_throw_published_array's ops): `index` and
|
|
4484
5517
|
* `count` are doubles (the written index, the argument count). */
|
|
4485
|
-
emitPublishedArrayGuard(arr, arrType, op, index = f64Lit(0), count = f64Lit(0)) {
|
|
4486
|
-
|
|
5518
|
+
emitPublishedArrayGuard(arr, arrType, op, index = f64Lit(0), count = f64Lit(0), third = null) {
|
|
5519
|
+
const published = this.publishedTypes;
|
|
5520
|
+
if (published?.containerGuarded(arrType) !== true)
|
|
4487
5521
|
return;
|
|
4488
5522
|
const B = this.B;
|
|
4489
|
-
const
|
|
4490
|
-
|
|
5523
|
+
const guards = published.arrayGuards(arrType);
|
|
5524
|
+
const ok = guards.frozen
|
|
5525
|
+
? this.emitFrozenArrayTest(arr, guards.published)
|
|
5526
|
+
: this.emitPublishedTest(arr);
|
|
4491
5527
|
const threw = B.tmp();
|
|
4492
|
-
|
|
5528
|
+
if (third === null) {
|
|
5529
|
+
this.declare(`declare zeroext i1 @scr_throw_published_array(i32, ptr, double, double)`);
|
|
5530
|
+
B.line(`${threw} = call zeroext i1 @scr_throw_published_array(i32 ${op}, ptr ${arr}, double ${index}, double ${count})`);
|
|
5531
|
+
}
|
|
5532
|
+
else {
|
|
5533
|
+
this.declare(`declare zeroext i1 @scr_throw_published_array_range(i32, ptr, double, double, double)`);
|
|
5534
|
+
B.line(`${threw} = call zeroext i1 @scr_throw_published_array_range(i32 ${op}, ptr ${arr}, double ${index}, double ${count}, double ${third})`);
|
|
5535
|
+
}
|
|
4493
5536
|
const unwind = B.newLabel("pub.throw");
|
|
4494
5537
|
B.condBr(threw, unwind, ok);
|
|
4495
5538
|
B.startBlock(unwind);
|
|
@@ -4556,11 +5599,9 @@ export class LlEmitter {
|
|
|
4556
5599
|
const nullable = this.nullableFieldGet(e);
|
|
4557
5600
|
if (!nullable || e.kind !== "fieldGet")
|
|
4558
5601
|
return this.emitReadReceiver(e);
|
|
4559
|
-
const B = this.B;
|
|
4560
5602
|
const receiver = this.emitReadReceiver(e.obj);
|
|
4561
|
-
const { ptr } = this.classFieldPtr(receiver.name, e.className, e.field);
|
|
4562
|
-
const p =
|
|
4563
|
-
B.line(`${p} = load ptr, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
5603
|
+
const { ptr } = this.classFieldPtr(receiver.name, e.className, e.field, "compressed");
|
|
5604
|
+
const p = this.loadRef(ptr);
|
|
4564
5605
|
return { name: this.stackNullableBox(p, nullable), type: e.type };
|
|
4565
5606
|
}
|
|
4566
5607
|
/** A private stack box over a nullable-pointer field read whose payload
|
|
@@ -4572,9 +5613,8 @@ export class LlEmitter {
|
|
|
4572
5613
|
if (!nullable || e.kind !== "fieldGet")
|
|
4573
5614
|
throw new InternalCompilerError("llvm emitter bug: owned nullable stack of non-field");
|
|
4574
5615
|
const receiver = this.emitReadReceiver(e.obj);
|
|
4575
|
-
const { ptr } = this.classFieldPtr(receiver.name, e.className, e.field);
|
|
4576
|
-
const p = this.
|
|
4577
|
-
this.B.line(`${p} = load ptr, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
5616
|
+
const { ptr } = this.classFieldPtr(receiver.name, e.className, e.field, "compressed");
|
|
5617
|
+
const p = this.loadRef(ptr);
|
|
4578
5618
|
const owner = this.own({ name: this.retainFrame(p, nullable.arm), type: nullable.arm });
|
|
4579
5619
|
return { box: this.stackNullableBox(owner.name, nullable), owner };
|
|
4580
5620
|
}
|
|
@@ -4635,7 +5675,6 @@ export class LlEmitter {
|
|
|
4635
5675
|
* retained payload of a borrowed box otherwise. Unlink-then-release like
|
|
4636
5676
|
* every field store. */
|
|
4637
5677
|
emitNullableFieldStore(obj, className, field, nullable, value) {
|
|
4638
|
-
const B = this.B;
|
|
4639
5678
|
let next;
|
|
4640
5679
|
if (value.kind === "unionWrap" &&
|
|
4641
5680
|
value.unionId === nullable.unionId &&
|
|
@@ -4660,10 +5699,9 @@ export class LlEmitter {
|
|
|
4660
5699
|
else {
|
|
4661
5700
|
next = this.unionToNullable(this.emitUnionProjection(value).name, nullable);
|
|
4662
5701
|
}
|
|
4663
|
-
const { ptr } = this.classFieldPtr(obj, className, field);
|
|
4664
|
-
const old =
|
|
4665
|
-
|
|
4666
|
-
B.line(`store ptr ${next}, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
5702
|
+
const { ptr } = this.classFieldPtr(obj, className, field, "compressed");
|
|
5703
|
+
const old = this.loadRef(ptr, false);
|
|
5704
|
+
this.storeRef(ptr, next);
|
|
4667
5705
|
this.releaseHeap(old, nullable.arm);
|
|
4668
5706
|
}
|
|
4669
5707
|
/** A union binding whose slot may hold a private stack box: stack locals
|
|
@@ -4780,11 +5818,25 @@ export class LlEmitter {
|
|
|
4780
5818
|
return (this.jsIcSitesMemo ??= new JsIcSites(this.mod));
|
|
4781
5819
|
}
|
|
4782
5820
|
jsIcSite() {
|
|
4783
|
-
|
|
5821
|
+
const name = `@sc_js_ic_${this.jsIcSiteCount++}`;
|
|
5822
|
+
this.journal?.site(name, "jsIcSite");
|
|
5823
|
+
return name;
|
|
4784
5824
|
}
|
|
4785
5825
|
/** A fresh read-site cache for one constant-key dyn read. */
|
|
4786
5826
|
dynReadIcSite() {
|
|
4787
|
-
|
|
5827
|
+
const name = `@sc_dyn_read_ic_${this.dynReadIcSites++}`;
|
|
5828
|
+
this.journal?.site(name, "dynReadIcSite");
|
|
5829
|
+
return name;
|
|
5830
|
+
}
|
|
5831
|
+
/** A fresh speculative loop site: the global that counts its bailing
|
|
5832
|
+
* entries in a row. */
|
|
5833
|
+
speculativeLoopSite() {
|
|
5834
|
+
const name = `@sc_spec_bails_${this.speculativeLoopSites++}`;
|
|
5835
|
+
this.journal?.site(name, "speculativeLoopSite");
|
|
5836
|
+
this.journal?.opened("speculativeLoopSite");
|
|
5837
|
+
this.declare(`${name} = internal global i8 0`);
|
|
5838
|
+
this.journal?.built();
|
|
5839
|
+
return name;
|
|
4788
5840
|
}
|
|
4789
5841
|
dynKind(d) {
|
|
4790
5842
|
return dynKind(this, d);
|
|
@@ -4861,8 +5913,8 @@ export class LlEmitter {
|
|
|
4861
5913
|
tagInSet(uName, unionId, tags) {
|
|
4862
5914
|
return tagInSet(this, uName, unionId, tags);
|
|
4863
5915
|
}
|
|
4864
|
-
arrPush(arr, acc, value) {
|
|
4865
|
-
return arrPush(this, arr, acc, value);
|
|
5916
|
+
arrPush(arr, acc, value, element) {
|
|
5917
|
+
return arrPush(this, arr, acc, value, element);
|
|
4866
5918
|
}
|
|
4867
5919
|
emitArrayCopyLoop(dst, src, acc) {
|
|
4868
5920
|
return emitArrayCopyLoop(this, dst, src, acc);
|
|
@@ -4903,8 +5955,8 @@ export class LlEmitter {
|
|
|
4903
5955
|
emitBytesLength(elem, receiver, bytes) {
|
|
4904
5956
|
return emitBytesLength(this, elem, receiver, bytes);
|
|
4905
5957
|
}
|
|
4906
|
-
emitBytesGet(elem, receiver, index, expr, inBounds = false, invalidNaN = false) {
|
|
4907
|
-
return emitBytesGet(this, elem, receiver, index, expr, inBounds, invalidNaN);
|
|
5958
|
+
emitBytesGet(elem, receiver, index, expr, inBounds = false, invalidNaN = false, owned = false) {
|
|
5959
|
+
return emitBytesGet(this, elem, receiver, index, expr, inBounds, invalidNaN, owned);
|
|
4908
5960
|
}
|
|
4909
5961
|
emitToUint32(value, expr, uint32) {
|
|
4910
5962
|
return emitToUint32(this, value, expr, uint32);
|
|
@@ -4959,8 +6011,8 @@ export class LlEmitter {
|
|
|
4959
6011
|
const integer = this.emitToUint32(value.name, expr, value.uint32);
|
|
4960
6012
|
this.B.line(`store i32 ${integer}, ptr ${slot}`);
|
|
4961
6013
|
}
|
|
4962
|
-
emitBytesSet(elem, receiver, index, value, indexExpr, expr, inBounds = false) {
|
|
4963
|
-
return emitBytesSet(this, elem, receiver, index, value, indexExpr, expr, inBounds);
|
|
6014
|
+
emitBytesSet(elem, receiver, index, value, indexExpr, expr, inBounds = false, owned = false) {
|
|
6015
|
+
return emitBytesSet(this, elem, receiver, index, value, indexExpr, expr, inBounds, owned);
|
|
4964
6016
|
}
|
|
4965
6017
|
emitBytesIntrinsic(e) {
|
|
4966
6018
|
return emitBytesIntrinsic(this, e);
|
|
@@ -5061,4 +6113,64 @@ export function adoptingAwaitOf(value) {
|
|
|
5061
6113
|
});
|
|
5062
6114
|
return found;
|
|
5063
6115
|
}
|
|
6116
|
+
/** Adds `key` to `into` when it lacks it. */
|
|
6117
|
+
function addEntry(into, key, value) {
|
|
6118
|
+
if (!into.has(key))
|
|
6119
|
+
into.set(key, value);
|
|
6120
|
+
}
|
|
6121
|
+
/** Adds `key` to a numbered table when it lacks it, numbering it after the
|
|
6122
|
+
* table's own entries (`prefix` and its index), and records the rename of
|
|
6123
|
+
* the chunk's `name` for it. */
|
|
6124
|
+
function addNumbered(into, key, name, prefix, names) {
|
|
6125
|
+
let own = into.get(key);
|
|
6126
|
+
if (own === undefined) {
|
|
6127
|
+
own = `${prefix}${into.size}`;
|
|
6128
|
+
into.set(key, own);
|
|
6129
|
+
}
|
|
6130
|
+
if (own !== name)
|
|
6131
|
+
names.set(name.replace(/^@/, ""), own.replace(/^@/, ""));
|
|
6132
|
+
}
|
|
6133
|
+
/** addNumbered for entries that keep their numbered name in `sym`. */
|
|
6134
|
+
function addNumberedSymbol(into, key, entry, prefix, names) {
|
|
6135
|
+
let own = into.get(key);
|
|
6136
|
+
if (own === undefined) {
|
|
6137
|
+
own = { ...entry, sym: `${prefix}${into.size}` };
|
|
6138
|
+
into.set(key, own);
|
|
6139
|
+
}
|
|
6140
|
+
if (own.sym !== entry.sym)
|
|
6141
|
+
names.set(entry.sym, own.sym);
|
|
6142
|
+
}
|
|
6143
|
+
registerReplay("jsIcSite", (emitter) => emitter.jsIcSite());
|
|
6144
|
+
registerReplay("dynReadIcSite", (emitter) => emitter.dynReadIcSite());
|
|
6145
|
+
registerReplay("speculativeLoopSite", (emitter) => emitter.speculativeLoopSite());
|
|
6146
|
+
for (const op of [
|
|
6147
|
+
"dyn.collectionDynOps",
|
|
6148
|
+
"dyn.dynMatchHelper",
|
|
6149
|
+
"dyn.jsonSchema",
|
|
6150
|
+
"dyn.recordNameTable",
|
|
6151
|
+
"dyn.jsonParseHelper",
|
|
6152
|
+
"dyn.dynCheckHelper",
|
|
6153
|
+
"dyn.toDynHelper",
|
|
6154
|
+
"dyn.promiseDynAdapterHelper",
|
|
6155
|
+
"dyn.dynFuncThunkHelper",
|
|
6156
|
+
"dyn.dynFuncBoxHelper",
|
|
6157
|
+
"dyn.dynFuncAdapterHelper",
|
|
6158
|
+
"dyn.dynToStrHelper",
|
|
6159
|
+
"dyn.dynIterNHelper",
|
|
6160
|
+
"dyn.dynDestrCheckHelper",
|
|
6161
|
+
"dyn.dynKeyGetHelper",
|
|
6162
|
+
"dyn.dynComputedKeyGetHelper",
|
|
6163
|
+
"dyn.caughtToDynHelper",
|
|
6164
|
+
"dyn.messageListenerHelper",
|
|
6165
|
+
"dyn.messageReaderHelper",
|
|
6166
|
+
])
|
|
6167
|
+
registerReplay(op, (emitter, args) => emitter.dyn.replayHelper(op, args));
|
|
6168
|
+
for (const op of [
|
|
6169
|
+
"walkers.jsonWriteHelper",
|
|
6170
|
+
"walkers.recordFieldWriter",
|
|
6171
|
+
"walkers.unionJoinHelper",
|
|
6172
|
+
])
|
|
6173
|
+
registerReplay(op, (emitter, args) => emitter.walkers.replayHelper(op, args));
|
|
6174
|
+
for (const op of ["publish.walker", "publish.refusal"])
|
|
6175
|
+
registerReplay(op, (emitter, args) => emitter.publishWalkers.replayHelper(op, args));
|
|
5064
6176
|
//# sourceMappingURL=emitter.js.map
|