@scriptc/compiler 0.2.6 → 0.2.7
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 +5 -18
- package/dist/backend/cycle-analysis.d.ts +21 -9
- package/dist/backend/cycle-analysis.js +139 -67
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +283 -3
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/cycle-mutability.d.ts +39 -0
- package/dist/backend/cycle-mutability.js +205 -0
- package/dist/backend/cycle-mutability.js.map +1 -0
- package/dist/backend/link-plan-core.d.ts +2 -1
- package/dist/backend/link-plan-core.js +15 -3
- package/dist/backend/link-plan-core.js.map +1 -1
- package/dist/backend/link-plan.d.ts +2 -1
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/llvm/alloc.d.ts +40 -0
- package/dist/backend/llvm/alloc.js +205 -0
- package/dist/backend/llvm/alloc.js.map +1 -0
- package/dist/backend/llvm/alloc.test.d.ts +1 -0
- package/dist/backend/llvm/alloc.test.js +102 -0
- package/dist/backend/llvm/alloc.test.js.map +1 -0
- package/dist/backend/llvm/call-lifetimes.d.ts +15 -3
- package/dist/backend/llvm/call-lifetimes.js +42 -18
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +170 -0
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/classes.d.ts +4 -1
- package/dist/backend/llvm/classes.js +35 -32
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +36 -3
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +13 -0
- package/dist/backend/llvm/common.js +30 -0
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.d.ts +19 -3
- package/dist/backend/llvm/constant-callbacks.js +289 -52
- package/dist/backend/llvm/constant-callbacks.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.test.js +140 -3
- package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.d.ts +29 -0
- package/dist/backend/llvm/dense-array-access.js +335 -0
- package/dist/backend/llvm/dense-array-access.js.map +1 -0
- package/dist/backend/llvm/dense-array-access.test.d.ts +1 -0
- package/dist/backend/llvm/dense-array-access.test.js +149 -0
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +34 -0
- package/dist/backend/llvm/dyn.js +189 -1
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +124 -4
- package/dist/backend/llvm/emitter.js +623 -105
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +68 -6
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +58 -4
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-async.test.d.ts +1 -0
- package/dist/backend/llvm/expr-async.test.js +62 -0
- package/dist/backend/llvm/expr-async.test.js.map +1 -0
- package/dist/backend/llvm/expr-calls.js +64 -6
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +16 -5
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-control.js +92 -2
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.js +2 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +174 -25
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +52 -24
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +1 -1
- package/dist/backend/llvm/expr-records.js +3 -3
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +59 -2
- 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/integer-remainder.d.ts +11 -0
- package/dist/backend/llvm/integer-remainder.js +91 -0
- package/dist/backend/llvm/integer-remainder.js.map +1 -1
- package/dist/backend/llvm/layouts.d.ts +2 -1
- package/dist/backend/llvm/layouts.js +3 -2
- package/dist/backend/llvm/layouts.js.map +1 -1
- package/dist/backend/llvm/lazy-captures.d.ts +16 -0
- package/dist/backend/llvm/lazy-captures.js +96 -0
- package/dist/backend/llvm/lazy-captures.js.map +1 -0
- package/dist/backend/llvm/lazy-captures.test.d.ts +1 -0
- package/dist/backend/llvm/lazy-captures.test.js +78 -0
- package/dist/backend/llvm/lazy-captures.test.js.map +1 -0
- package/dist/backend/llvm/lib-filesystem.js +3 -4
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.d.ts +5 -1
- package/dist/backend/llvm/local-array-reads.js +78 -17
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +78 -1
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.d.ts +5 -1
- package/dist/backend/llvm/local-union-storage.js +48 -6
- package/dist/backend/llvm/local-union-storage.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.test.js +91 -4
- package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js +1 -1
- package/dist/backend/llvm/nullable-fields.d.ts +28 -0
- package/dist/backend/llvm/nullable-fields.js +45 -0
- package/dist/backend/llvm/nullable-fields.js.map +1 -0
- package/dist/backend/llvm/nullable-fields.test.d.ts +1 -0
- package/dist/backend/llvm/nullable-fields.test.js +48 -0
- package/dist/backend/llvm/nullable-fields.test.js.map +1 -0
- package/dist/backend/llvm/serialized-ir-emission.test.d.ts +1 -0
- package/dist/backend/llvm/serialized-ir-emission.test.js +52 -0
- package/dist/backend/llvm/serialized-ir-emission.test.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +69 -2
- package/dist/backend/llvm/shapes.js +259 -27
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +114 -5
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/stack-callbacks.js +2 -3
- package/dist/backend/llvm/stack-callbacks.js.map +1 -1
- package/dist/backend/llvm/stack-captures.d.ts +3 -1
- package/dist/backend/llvm/stack-captures.js +5 -3
- package/dist/backend/llvm/stack-captures.js.map +1 -1
- package/dist/backend/llvm/stack-unions.test.js +38 -1
- package/dist/backend/llvm/stack-unions.test.js.map +1 -1
- package/dist/backend/llvm/string-construction.test.js +1 -1
- package/dist/backend/llvm/string-key-hash.d.ts +8 -0
- package/dist/backend/llvm/string-key-hash.js +59 -0
- package/dist/backend/llvm/string-key-hash.js.map +1 -0
- package/dist/backend/llvm/string-key-hash.test.d.ts +1 -0
- package/dist/backend/llvm/string-key-hash.test.js +34 -0
- package/dist/backend/llvm/string-key-hash.test.js.map +1 -0
- package/dist/backend/llvm/string-lifetimes.test.js +41 -4
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/switch-dispatch.js +1 -1
- package/dist/backend/llvm/switch-dispatch.js.map +1 -1
- package/dist/backend/llvm/switch-dispatch.test.js +2 -2
- package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
- package/dist/backend/may-throw.js +3 -0
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +1 -1
- package/dist/backend/native/cache-warm.d.ts +2 -1
- package/dist/backend/native/cache-warm.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +3 -2
- package/dist/backend/native/contracts.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-core.d.ts +2 -1
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +5 -0
- package/dist/backend/native-codegen.js +4 -0
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +23 -0
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +3 -2
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/native-link-info.d.ts +2 -1
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +2 -2
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +3 -1
- package/dist/backend/native-tools.js +0 -1
- package/dist/backend/native-tools.js.map +1 -1
- package/dist/backend/optimization.d.ts +25 -0
- package/dist/backend/optimization.js +21 -0
- package/dist/backend/optimization.js.map +1 -0
- package/dist/backend/optimization.test.d.ts +1 -0
- package/dist/backend/optimization.test.js +24 -0
- package/dist/backend/optimization.test.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 +15 -4
- package/dist/backend/runtime-pack-core.js +23 -12
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-native.d.ts +7 -3
- package/dist/backend/runtime-pack-native.js +0 -3
- package/dist/backend/runtime-pack-native.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.d.ts +20 -2
- package/dist/backend/runtime-pack.js +23 -0
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +115 -2
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-diagnostics.test.js +1 -1
- package/dist/backend/targets.d.ts +2 -1
- package/dist/backend/targets.js +1 -1
- package/dist/backend/targets.js.map +1 -1
- package/dist/cli/command.js +5 -4
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/host.d.ts +2 -1
- package/dist/cli/usage.d.ts +1 -1
- package/dist/cli/usage.js +5 -2
- package/dist/cli/usage.js.map +1 -1
- package/dist/compile-types.d.ts +5 -2
- package/dist/diagnostics/diagnostic.js +10 -8
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +2 -2
- package/dist/executable/executable-cache.js +7 -4
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +20 -0
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/frontend/lowering/abstract-equality.js +5 -49
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +23 -0
- package/dist/frontend/lowering/array-values.js +129 -0
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.js +17 -2
- package/dist/frontend/lowering/builtins/errors.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.d.ts +6 -17
- package/dist/frontend/lowering/builtins/process.js +56 -29
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/caught-value-dispatch.d.ts +11 -0
- package/dist/frontend/lowering/caught-value-dispatch.js +87 -0
- package/dist/frontend/lowering/caught-value-dispatch.js.map +1 -0
- package/dist/frontend/lowering/class-assertions.d.ts +4 -0
- package/dist/frontend/lowering/class-assertions.js +12 -4
- package/dist/frontend/lowering/class-assertions.js.map +1 -1
- package/dist/frontend/lowering/class-callbacks.d.ts +3 -3
- package/dist/frontend/lowering/class-callbacks.js +18 -5
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +4 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-method-mutations.d.ts +5 -0
- package/dist/frontend/lowering/class-method-mutations.js +472 -0
- package/dist/frontend/lowering/class-method-mutations.js.map +1 -0
- package/dist/frontend/lowering/class-method-values.js +25 -5
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.js +8 -2
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-unions.d.ts +16 -0
- package/dist/frontend/lowering/class-unions.js +127 -0
- package/dist/frontend/lowering/class-unions.js.map +1 -0
- package/dist/frontend/lowering/coercions/builders.js +8 -1
- package/dist/frontend/lowering/coercions/builders.js.map +1 -1
- package/dist/frontend/lowering/coercions/function-adapters.js +2 -0
- package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
- package/dist/frontend/lowering/coercions/identity.d.ts +7 -0
- package/dist/frontend/lowering/coercions/identity.js +26 -0
- package/dist/frontend/lowering/coercions/identity.js.map +1 -0
- package/dist/frontend/lowering/coercions/structural.js +9 -6
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/collection-narrowing.d.ts +6 -0
- package/dist/frontend/lowering/collection-narrowing.js +31 -0
- package/dist/frontend/lowering/collection-narrowing.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callback-call.d.ts +7 -0
- package/dist/frontend/lowering/containers/array-callback-call.js +52 -0
- package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callbacks.d.ts +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.js +363 -49
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-concat.d.ts +7 -0
- package/dist/frontend/lowering/containers/array-concat.js +130 -0
- package/dist/frontend/lowering/containers/array-concat.js.map +1 -0
- package/dist/frontend/lowering/containers/array-construction.d.ts +2 -0
- package/dist/frontend/lowering/containers/array-construction.js +95 -3
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.d.ts +1 -11
- package/dist/frontend/lowering/containers/array-methods.js +43 -132
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +10 -1
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/indexed-objects.js +56 -70
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/cycle-initialization.d.ts +41 -0
- package/dist/frontend/lowering/cycle-initialization.js +277 -0
- package/dist/frontend/lowering/cycle-initialization.js.map +1 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js +4 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.js +138 -32
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-field-write.d.ts +4 -4
- package/dist/frontend/lowering/expressions/union-field-write.js +54 -44
- package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -1
- package/dist/frontend/lowering/iterator-adapters.d.ts +20 -0
- package/dist/frontend/lowering/iterator-adapters.js +605 -0
- package/dist/frontend/lowering/iterator-adapters.js.map +1 -0
- package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
- package/dist/frontend/lowering/lower-array-sort.js +44 -5
- package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
- package/dist/frontend/lowering/lower-array-sort.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-array-sort.test.js +31 -0
- package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -0
- package/dist/frontend/lowering/lower-assert.js +7 -0
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.js +1 -0
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +3 -3
- package/dist/frontend/lowering/lower-calls.js +162 -121
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +2 -0
- package/dist/frontend/lowering/lower-classes.js +45 -43
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +9 -2
- package/dist/frontend/lowering/lower-exprs.js +390 -157
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.js +32 -19
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +26 -2
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +10 -2
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +46 -58
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +37 -0
- package/dist/frontend/lowering/lowerer.js +283 -18
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/native-ffi.js +3 -1
- package/dist/frontend/lowering/native-ffi.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-provenance.d.ts +15 -0
- package/dist/frontend/lowering/runtime-optional-provenance.js +40 -0
- package/dist/frontend/lowering/runtime-optional-provenance.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js +2 -2
- package/dist/frontend/lowering/strict-equality.d.ts +9 -0
- package/dist/frontend/lowering/strict-equality.js +116 -0
- package/dist/frontend/lowering/strict-equality.js.map +1 -0
- package/dist/frontend/lowering/surfaces.js +3 -0
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/union-comparison.d.ts +5 -0
- package/dist/frontend/lowering/union-comparison.js +47 -0
- package/dist/frontend/lowering/union-comparison.js.map +1 -0
- package/dist/frontend/program.d.ts +38 -2
- package/dist/frontend/program.js +440 -59
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +59 -6
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +1 -1
- package/dist/frontend/type-mapper.js +89 -14
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +15 -3
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/index.js +25 -9
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +3 -1
- package/dist/ir/analysis.js +4 -0
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/builtin-signatures.js +2 -3
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/constant-tables.test.js +1 -1
- package/dist/ir/initializer-bindings.test.js +1 -1
- package/dist/ir/ir.d.ts +78 -15
- package/dist/ir/ir.js +20 -6
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +3 -3
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/traverse.js +8 -0
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +118 -20
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +269 -8
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/fence-eval.test.js +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/library-cache.test.js +5 -5
- package/dist/library/library-profile.d.ts +2 -1
- package/dist/library/library-profile.js +4 -3
- package/dist/library/library-profile.js.map +1 -1
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/compiler.test.js +2 -2
- package/dist/native/library.d.ts +2 -1
- package/dist/native/library.js.map +1 -1
- package/dist/native/prepare.js +27 -3
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/sanitizer.d.ts +3 -2
- package/dist/native/sanitizer.js +3 -13
- package/dist/native/sanitizer.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +8 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** Ordered link inputs shared by synchronous native and asynchronous Node hosts. */
|
|
2
|
+
import type { NativeOptimization } from "./optimization.js";
|
|
2
3
|
import { type NativeTargetSpec, type WindowsSubsystem } from "./targets.js";
|
|
3
4
|
export interface ExecutableLinkInputs {
|
|
4
5
|
inputs: string[];
|
|
@@ -16,7 +17,7 @@ export declare function executableLinkInputs(options: {
|
|
|
16
17
|
runtimeObjects: readonly string[];
|
|
17
18
|
runtimeArchives: readonly string[];
|
|
18
19
|
runtimeSystemLibraries: readonly string[];
|
|
19
|
-
optimization:
|
|
20
|
+
optimization: NativeOptimization;
|
|
20
21
|
strip?: boolean;
|
|
21
22
|
windowsSubsystem?: WindowsSubsystem;
|
|
22
23
|
}): ExecutableLinkInputs;
|
|
@@ -1,15 +1,27 @@
|
|
|
1
|
-
/** Ordered link inputs shared by synchronous native and asynchronous Node hosts. */
|
|
2
1
|
import { executableOptimizationLinkerArgs, executableStripLinkerArgs, windowsSubsystemLinkerArgs, } from "./targets.js";
|
|
3
2
|
export function executableLinkInputs(options) {
|
|
4
3
|
if (options.ffiFrameworks.length !== 0 && options.target.platform !== "darwin")
|
|
5
4
|
throw new Error("FFI frameworks require a Darwin target");
|
|
6
5
|
return {
|
|
6
|
+
// Linkers lay out code in input order. The precompiled runtime and its
|
|
7
|
+
// archives go first so their addresses do not depend on the size of the
|
|
8
|
+
// program object: otherwise any program edit shifts every runtime
|
|
9
|
+
// function, and hot interpreter loops (the regex engine's especially)
|
|
10
|
+
// swing by double-digit percentages with incidental cache-line
|
|
11
|
+
// placement. Program code never references archive members directly,
|
|
12
|
+
// so single-pass archive resolution (GNU ld) still sees every runtime
|
|
13
|
+
// reference first. FFI libraries stay after the program that uses them;
|
|
14
|
+
// single-pass linkers get the archives once more after them in case a
|
|
15
|
+
// foreign library depends on a vendored one.
|
|
7
16
|
inputs: [
|
|
17
|
+
...options.runtimeObjects,
|
|
18
|
+
...options.runtimeArchives,
|
|
8
19
|
options.programObject,
|
|
9
20
|
...(options.programPartitions ?? []),
|
|
10
21
|
...options.ffiLibraries,
|
|
11
|
-
...options.
|
|
12
|
-
|
|
22
|
+
...(options.ffiLibraries.length !== 0 && options.target.platform !== "darwin"
|
|
23
|
+
? options.runtimeArchives
|
|
24
|
+
: []),
|
|
13
25
|
],
|
|
14
26
|
systemLibraries: [
|
|
15
27
|
...new Set([...options.ffiSystemLibraries, ...options.runtimeSystemLibraries]),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-plan-core.js","sourceRoot":"","sources":["../../src/backend/link-plan-core.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"link-plan-core.js","sourceRoot":"","sources":["../../src/backend/link-plan-core.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,0BAA0B,GAG3B,MAAM,cAAc,CAAC;AAQtB,MAAM,UAAU,oBAAoB,CAAC,OAcpC;IACC,IAAI,OAAO,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ;QAC5E,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,OAAO;QACL,uEAAuE;QACvE,wEAAwE;QACxE,kEAAkE;QAClE,sEAAsE;QACtE,+DAA+D;QAC/D,qEAAqE;QACrE,sEAAsE;QACtE,wEAAwE;QACxE,sEAAsE;QACtE,6CAA6C;QAC7C,MAAM,EAAE;YACN,GAAG,OAAO,CAAC,cAAc;YACzB,GAAG,OAAO,CAAC,eAAe;YAC1B,OAAO,CAAC,aAAa;YACrB,GAAG,CAAC,OAAO,CAAC,iBAAiB,IAAI,EAAE,CAAC;YACpC,GAAG,OAAO,CAAC,YAAY;YACvB,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ;gBAC3E,CAAC,CAAC,OAAO,CAAC,eAAe;gBACzB,CAAC,CAAC,EAAE,CAAC;SACR;QACD,eAAe,EAAE;YACf,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,kBAAkB,EAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;SAC/E;QACD,WAAW,EAAE;YACX,GAAG,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YAChE,GAAG,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAC9D,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,CACrF;YACD,GAAG,gCAAgC,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC;YAClF,GAAG,yBAAyB,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC;YAC7E,GAAG,0BAA0B,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,gBAAgB,CAAC;SACjF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* program, FFI inputs, runtime objects/archives, and system libraries meet
|
|
7
7
|
* the platform linker.
|
|
8
8
|
*/
|
|
9
|
+
import type { NativeOptimization } from "./optimization.js";
|
|
9
10
|
import type { FfiProfile } from "../ffi/ffi-manifest.js";
|
|
10
11
|
import type { NativeLinkFeatures } from "./native-link-info.js";
|
|
11
12
|
import type { NativeArtifactDependency } from "./native/contracts.js";
|
|
@@ -32,7 +33,7 @@ export declare function createNativeLinkPlan(options: {
|
|
|
32
33
|
outPath: string;
|
|
33
34
|
features: NativeLinkFeatures;
|
|
34
35
|
ffi: FfiProfile | null;
|
|
35
|
-
optimization:
|
|
36
|
+
optimization: NativeOptimization;
|
|
36
37
|
strip?: boolean;
|
|
37
38
|
windowsSubsystem?: WindowsSubsystem;
|
|
38
39
|
programObjectDependencies?: readonly NativeArtifactDependency[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-plan.js","sourceRoot":"","sources":["../../src/backend/link-plan.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"link-plan.js","sourceRoot":"","sources":["../../src/backend/link-plan.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAA6B,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAkB3D,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAa1C;IACC,IAAI,OAAO,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ;QACzE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;IACnD,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,kBAAkB,EAAE,uBAAuB,CACzC,OAAO,CAAC,MAAM,CAAC,QAAQ,EACvB,OAAO,CAAC,YAAY,EACpB,OAAO,CAAC,KAAK,CACd;QACD,UAAU,EAAE,OAAO,CAAC,OAAO;QAC3B,GAAG,oBAAoB,CAAC;YACtB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,GAAG,CAAC,OAAO,CAAC,iBAAiB,KAAK,SAAS;gBACzC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC;YACrD,YAAY,EAAE,OAAO,CAAC,GAAG,EAAE,SAAS,IAAI,EAAE;YAC1C,kBAAkB,EAAE,OAAO,CAAC,GAAG,EAAE,eAAe,IAAI,EAAE;YACtD,aAAa,EAAE,OAAO,CAAC,GAAG,EAAE,UAAU,IAAI,EAAE;YAC5C,cAAc,EAAE,WAAW,CAAC,cAAc;YAC1C,eAAe,EAAE,WAAW,CAAC,QAAQ;YACrC,sBAAsB,EAAE,WAAW,CAAC,eAAe;YACnD,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;YAChE,GAAG,CAAC,OAAO,CAAC,gBAAgB,KAAK,SAAS;gBACxC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC;SACpD,CAAC;QACF,eAAe,EAAE,CAAC,GAAG,WAAW,CAAC,eAAe,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC;QACpF,yBAAyB,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;QACzE,WAAW;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** The emitter surface this module needs (a subset of ShapeHost). */
|
|
2
|
+
export interface AllocHost {
|
|
3
|
+
declare(decl: string): void;
|
|
4
|
+
needOom(): void;
|
|
5
|
+
readonly sizeType: "i32" | "i64";
|
|
6
|
+
/** Inline the allocator fast paths (see the target rule above). */
|
|
7
|
+
readonly inlineAlloc?: boolean;
|
|
8
|
+
/** Emit the RC-audit object notes on the out-of-line paths (ShapeHost
|
|
9
|
+
* objectAudit: only --sanitize builds count them). Absent means emit. */
|
|
10
|
+
readonly objectAudit?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** Whether a target can use the inline allocation paths. */
|
|
13
|
+
export declare function inlineAllocSupported(options: {
|
|
14
|
+
pointerBits?: 32 | 64 | undefined;
|
|
15
|
+
wasi?: boolean | undefined;
|
|
16
|
+
targetTriple?: string | undefined;
|
|
17
|
+
threadInstances?: boolean | undefined;
|
|
18
|
+
}): boolean;
|
|
19
|
+
/** A collector header to install: the object's trace and teardown. */
|
|
20
|
+
export interface CycHeader {
|
|
21
|
+
trace: string;
|
|
22
|
+
free: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Lines that leave a zeroed object of `size` bytes (an integer constant
|
|
26
|
+
* expression) in `%o`, aborting on OOM, with the RC-audit allocation note
|
|
27
|
+
* on the out-of-line path. With `cyc`, the object carries a collector
|
|
28
|
+
* header (scr_cyc_alloc's contract). `stored` is the number of leading
|
|
29
|
+
* object bytes the caller stores unconditionally right after (at least the
|
|
30
|
+
* refcount word), which a recycled block need not clear. Labels use the
|
|
31
|
+
* `sa.` prefix; the lines end in an open block.
|
|
32
|
+
*/
|
|
33
|
+
export declare function emitObjectAlloc(host: AllocHost, size: string, cyc: CycHeader | null, stored?: number): string[];
|
|
34
|
+
/**
|
|
35
|
+
* Lines that free the object `%o` after its members were released: the
|
|
36
|
+
* RC-audit free note, the weak-collection dispose hook, and the block —
|
|
37
|
+
* `scr_cyc_free` for collector-headered objects, `scr_rt_free` otherwise.
|
|
38
|
+
* Labels use the `sf.` prefix; the lines end in an open block.
|
|
39
|
+
*/
|
|
40
|
+
export declare function emitObjectFree(host: AllocHost, cyc: boolean): string[];
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/* Emitted object allocation and deallocation for records and class
|
|
2
|
+
* instances.
|
|
3
|
+
*
|
|
4
|
+
* Every constructor allocates a constant-size block. The runtime's
|
|
5
|
+
* small-object allocator (scr_alloc.c, contract in scr_runtime.h) serves it
|
|
6
|
+
* from a per-size-class free list or bump pointer, but through an
|
|
7
|
+
* out-of-line call the size class, the zeroing length, and the
|
|
8
|
+
* collector-header setup are recomputed for every object. Here the fast
|
|
9
|
+
* paths are inlined into the emitted `new`/release helpers instead, so they
|
|
10
|
+
* fold to a constant class, a constant-length clear of only the bytes the
|
|
11
|
+
* helper does not store itself, and a handful of loads and stores.
|
|
12
|
+
*
|
|
13
|
+
* Soundness does not depend on which runtime the program links against.
|
|
14
|
+
* The runtime defines `scr_sa` in every build; where its allocator is
|
|
15
|
+
* compiled out (AddressSanitizer, the RC audit) the state stays all-zero,
|
|
16
|
+
* so the inline paths find no free block, no bump room and an empty span,
|
|
17
|
+
* and always take the slow path: the same out-of-line calls as before
|
|
18
|
+
* (scr_rt_calloc / scr_cyc_alloc, scr_rt_free) plus the RC-audit object
|
|
19
|
+
* notes. The fast paths skip those notes, which are no-ops whenever the
|
|
20
|
+
* allocator is live (SCR_RC_AUDIT forces it off; scr_runtime.h #errors
|
|
21
|
+
* otherwise). Blocks outside the reservation (system fallbacks) go back
|
|
22
|
+
* through scr_rt_free.
|
|
23
|
+
*
|
|
24
|
+
* Inlining is limited to the targets where the allocator can be live and
|
|
25
|
+
* its state is a process global: 64-bit, not WASI, not Windows, and not
|
|
26
|
+
* thread-instanced libraries or worker programs (whose runtime state,
|
|
27
|
+
* including scr_cyc_live and scr_weak_dispose_hook, is thread-local and
|
|
28
|
+
* whose allocator is compiled out). Elsewhere the out-of-line calls
|
|
29
|
+
* remain. */
|
|
30
|
+
const ALLOC_NOTE = ` call void @scr_obj_alloc_note()`;
|
|
31
|
+
const FREE_NOTE = ` call void @scr_obj_free_note()`;
|
|
32
|
+
/** Whether a target can use the inline allocation paths. */
|
|
33
|
+
export function inlineAllocSupported(options) {
|
|
34
|
+
if (options.pointerBits === 32 || options.wasi === true || options.threadInstances === true) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
// An omitted triple means the host ABI. That stays sound even on a host
|
|
38
|
+
// whose runtime compiles the allocator out: scr_sa is defined there too
|
|
39
|
+
// and stays zero, so only the slow paths run.
|
|
40
|
+
const triple = (options.targetTriple ?? "").toLowerCase();
|
|
41
|
+
return !/windows|mingw|msvc|cygwin|wasm/.test(triple);
|
|
42
|
+
}
|
|
43
|
+
/* ScrSaState layout on 64-bit targets (asserted in scr_runtime.h). */
|
|
44
|
+
const SA_TYPE = "{ i64, i64, i32, [32 x ptr], [32 x ptr], [32 x ptr] }";
|
|
45
|
+
const SA_SPAN = 8;
|
|
46
|
+
const SA_SHIFT = 16;
|
|
47
|
+
const SA_FREE = 24;
|
|
48
|
+
const SA_BUMP = 280;
|
|
49
|
+
const SA_LIM = 536;
|
|
50
|
+
const SA_STEP_SHIFT = 4; // 16-byte classes
|
|
51
|
+
const SA_MAX = 512;
|
|
52
|
+
/** sizeof(ScrCycHdr) on 64-bit targets; trace and free_fn are its first
|
|
53
|
+
* two words, and every other header word starts zero. */
|
|
54
|
+
const CYC_HDR = 32;
|
|
55
|
+
function declareState(host) {
|
|
56
|
+
host.declare(`@scr_sa = external global ${SA_TYPE}`);
|
|
57
|
+
host.declare(`declare i1 @llvm.expect.i1(i1, i1)`);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Lines that leave a zeroed object of `size` bytes (an integer constant
|
|
61
|
+
* expression) in `%o`, aborting on OOM, with the RC-audit allocation note
|
|
62
|
+
* on the out-of-line path. With `cyc`, the object carries a collector
|
|
63
|
+
* header (scr_cyc_alloc's contract). `stored` is the number of leading
|
|
64
|
+
* object bytes the caller stores unconditionally right after (at least the
|
|
65
|
+
* refcount word), which a recycled block need not clear. Labels use the
|
|
66
|
+
* `sa.` prefix; the lines end in an open block.
|
|
67
|
+
*/
|
|
68
|
+
export function emitObjectAlloc(host, size, cyc, stored = 8) {
|
|
69
|
+
const lines = allocLines(host, size, cyc, stored);
|
|
70
|
+
if (host.objectAudit === false)
|
|
71
|
+
return lines.filter((line) => line !== ALLOC_NOTE);
|
|
72
|
+
host.declare(`declare void @scr_obj_alloc_note()`);
|
|
73
|
+
return lines;
|
|
74
|
+
}
|
|
75
|
+
function allocLines(host, size, cyc, stored) {
|
|
76
|
+
const S = host.sizeType;
|
|
77
|
+
if (host.inlineAlloc !== true) {
|
|
78
|
+
if (cyc) {
|
|
79
|
+
host.declare(`declare ptr @scr_cyc_alloc(${S}, ptr, ptr)`);
|
|
80
|
+
return [
|
|
81
|
+
` %o = call ptr @scr_cyc_alloc(${S} ${size}, ptr ${cyc.trace}, ptr ${cyc.free})`,
|
|
82
|
+
` call void @scr_obj_alloc_note()`,
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
host.declare(`declare ptr @scr_rt_calloc(${S})`);
|
|
86
|
+
host.needOom();
|
|
87
|
+
return [
|
|
88
|
+
` %o = call ptr @scr_rt_calloc(${S} ${size})`,
|
|
89
|
+
` %isnull = icmp eq ptr %o, null`,
|
|
90
|
+
` br i1 %isnull, label %oom, label %ok`,
|
|
91
|
+
`oom:`,
|
|
92
|
+
` call void @sc_oom()`,
|
|
93
|
+
` unreachable`,
|
|
94
|
+
`ok:`,
|
|
95
|
+
` call void @scr_obj_alloc_note()`,
|
|
96
|
+
];
|
|
97
|
+
}
|
|
98
|
+
declareState(host);
|
|
99
|
+
// Bytes of the block that the fast path itself stores after the clear:
|
|
100
|
+
// the header's trace/free_fn words, or the object's leading words.
|
|
101
|
+
const keep = cyc ? 16 : stored;
|
|
102
|
+
const lines = [
|
|
103
|
+
` %sa.n = add i64 ${size}, ${cyc ? CYC_HDR : 0}`,
|
|
104
|
+
` %sa.small = icmp ule i64 %sa.n, ${SA_MAX}`,
|
|
105
|
+
` br i1 %sa.small, label %sa.class, label %sa.slow`,
|
|
106
|
+
`sa.class:`,
|
|
107
|
+
` %sa.nm1 = sub i64 %sa.n, 1`,
|
|
108
|
+
` %sa.c = lshr i64 %sa.nm1, ${SA_STEP_SHIFT}`,
|
|
109
|
+
` %sa.c8 = shl i64 %sa.c, 3`,
|
|
110
|
+
` %sa.fo = add i64 %sa.c8, ${SA_FREE}`,
|
|
111
|
+
` %sa.fp = getelementptr inbounds i8, ptr @scr_sa, i64 %sa.fo`,
|
|
112
|
+
` %sa.b = load ptr, ptr %sa.fp`,
|
|
113
|
+
` %sa.hit = icmp ne ptr %sa.b, null`,
|
|
114
|
+
` %sa.hitx = call i1 @llvm.expect.i1(i1 %sa.hit, i1 true)`,
|
|
115
|
+
` br i1 %sa.hitx, label %sa.pop, label %sa.bump`,
|
|
116
|
+
`sa.pop: ; recycled blocks are dirty`,
|
|
117
|
+
` %sa.next = load ptr, ptr %sa.b`,
|
|
118
|
+
` store ptr %sa.next, ptr %sa.fp`,
|
|
119
|
+
` %sa.z = getelementptr inbounds i8, ptr %sa.b, i64 ${keep}`,
|
|
120
|
+
` %sa.zn = sub i64 %sa.n, ${keep}`,
|
|
121
|
+
` call void @llvm.memset.p0.i64(ptr align 8 %sa.z, i8 0, i64 %sa.zn, i1 false)`,
|
|
122
|
+
` br label %sa.fast`,
|
|
123
|
+
`sa.bump: ; fresh reservation memory is already zero`,
|
|
124
|
+
` %sa.c1 = add i64 %sa.c, 1`,
|
|
125
|
+
` %sa.sz = shl i64 %sa.c1, ${SA_STEP_SHIFT}`,
|
|
126
|
+
` %sa.bo = add i64 %sa.c8, ${SA_BUMP}`,
|
|
127
|
+
` %sa.bp = getelementptr inbounds i8, ptr @scr_sa, i64 %sa.bo`,
|
|
128
|
+
` %sa.lo = add i64 %sa.c8, ${SA_LIM}`,
|
|
129
|
+
` %sa.lp = getelementptr inbounds i8, ptr @scr_sa, i64 %sa.lo`,
|
|
130
|
+
` %sa.p = load ptr, ptr %sa.bp`,
|
|
131
|
+
` %sa.l = load ptr, ptr %sa.lp`,
|
|
132
|
+
` %sa.pi = ptrtoint ptr %sa.p to i64`,
|
|
133
|
+
` %sa.li = ptrtoint ptr %sa.l to i64`,
|
|
134
|
+
` %sa.room = sub i64 %sa.li, %sa.pi`,
|
|
135
|
+
` %sa.fits = icmp uge i64 %sa.room, %sa.sz`,
|
|
136
|
+
` %sa.fitsx = call i1 @llvm.expect.i1(i1 %sa.fits, i1 true)`,
|
|
137
|
+
` br i1 %sa.fitsx, label %sa.carve, label %sa.slow`,
|
|
138
|
+
`sa.carve:`,
|
|
139
|
+
` %sa.np = getelementptr inbounds i8, ptr %sa.p, i64 %sa.sz`,
|
|
140
|
+
` store ptr %sa.np, ptr %sa.bp`,
|
|
141
|
+
` br label %sa.fast`,
|
|
142
|
+
];
|
|
143
|
+
host.declare(`declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)`);
|
|
144
|
+
if (cyc) {
|
|
145
|
+
host.declare(`declare ptr @scr_cyc_alloc(${S}, ptr, ptr)`);
|
|
146
|
+
host.declare(`@scr_cyc_live = external global i64`);
|
|
147
|
+
lines.push(`sa.fast:`, ` %sa.blk = phi ptr [ %sa.b, %sa.pop ], [ %sa.p, %sa.carve ]`, ` store ptr ${cyc.trace}, ptr %sa.blk ; ScrCycHdr.trace`, ` %sa.ffp = getelementptr inbounds i8, ptr %sa.blk, i64 8`, ` store ptr ${cyc.free}, ptr %sa.ffp ; ScrCycHdr.free_fn`, ` %sa.live = load i64, ptr @scr_cyc_live`, ` %sa.live1 = add i64 %sa.live, 1`, ` store i64 %sa.live1, ptr @scr_cyc_live`, ` %sa.obj = getelementptr inbounds i8, ptr %sa.blk, i64 ${CYC_HDR}`, ` br label %sa.done`, `sa.slow:`, ` %sa.s = call ptr @scr_cyc_alloc(i64 ${size}, ptr ${cyc.trace}, ptr ${cyc.free})`, ` call void @scr_obj_alloc_note()`, ` br label %sa.done`, `sa.done:`, ` %o = phi ptr [ %sa.obj, %sa.fast ], [ %sa.s, %sa.slow ]`);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
host.declare(`declare ptr @scr_rt_calloc(${S})`);
|
|
151
|
+
host.needOom();
|
|
152
|
+
lines.push(`sa.fast:`, ` %sa.blk = phi ptr [ %sa.b, %sa.pop ], [ %sa.p, %sa.carve ]`, ` br label %sa.done`, `sa.slow:`, ` %sa.s = call ptr @scr_rt_calloc(i64 ${size})`, ` %sa.null = icmp eq ptr %sa.s, null`, ` br i1 %sa.null, label %oom, label %sa.noted`, `oom:`, ` call void @sc_oom()`, ` unreachable`, `sa.noted:`, ` call void @scr_obj_alloc_note()`, ` br label %sa.done`, `sa.done:`, ` %o = phi ptr [ %sa.blk, %sa.fast ], [ %sa.s, %sa.noted ]`);
|
|
153
|
+
}
|
|
154
|
+
return lines;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Lines that free the object `%o` after its members were released: the
|
|
158
|
+
* RC-audit free note, the weak-collection dispose hook, and the block —
|
|
159
|
+
* `scr_cyc_free` for collector-headered objects, `scr_rt_free` otherwise.
|
|
160
|
+
* Labels use the `sf.` prefix; the lines end in an open block.
|
|
161
|
+
*/
|
|
162
|
+
export function emitObjectFree(host, cyc) {
|
|
163
|
+
const lines = freeLines(host, cyc);
|
|
164
|
+
if (host.objectAudit === false)
|
|
165
|
+
return lines.filter((line) => line !== FREE_NOTE);
|
|
166
|
+
host.declare(`declare void @scr_obj_free_note()`);
|
|
167
|
+
return lines;
|
|
168
|
+
}
|
|
169
|
+
function freeLines(host, cyc) {
|
|
170
|
+
if (host.inlineAlloc !== true) {
|
|
171
|
+
if (cyc) {
|
|
172
|
+
host.declare(`declare void @scr_cyc_free(ptr)`);
|
|
173
|
+
return [` call void @scr_obj_free_note()`, ` call void @scr_cyc_free(ptr %o)`];
|
|
174
|
+
}
|
|
175
|
+
host.declare(`declare void @scr_rt_free(ptr)`);
|
|
176
|
+
host.declare(`declare void @scr_weak_dispose(ptr)`);
|
|
177
|
+
return [
|
|
178
|
+
` call void @scr_obj_free_note()`,
|
|
179
|
+
` call void @scr_weak_dispose(ptr %o)`,
|
|
180
|
+
` call void @scr_rt_free(ptr %o)`,
|
|
181
|
+
];
|
|
182
|
+
}
|
|
183
|
+
declareState(host);
|
|
184
|
+
host.declare(`declare void @scr_rt_free(ptr)`);
|
|
185
|
+
host.declare(`@scr_weak_dispose_hook = external global ptr`);
|
|
186
|
+
const lines = [
|
|
187
|
+
` %sf.hook = load ptr, ptr @scr_weak_dispose_hook`,
|
|
188
|
+
` %sf.has = icmp ne ptr %sf.hook, null`,
|
|
189
|
+
` %sf.hasx = call i1 @llvm.expect.i1(i1 %sf.has, i1 false)`,
|
|
190
|
+
` br i1 %sf.hasx, label %sf.observe, label %sf.block`,
|
|
191
|
+
`sf.observe: ; weak collections observe the disposal`,
|
|
192
|
+
` call void %sf.hook(ptr %o)`,
|
|
193
|
+
` br label %sf.block`,
|
|
194
|
+
`sf.block:`,
|
|
195
|
+
];
|
|
196
|
+
if (cyc) {
|
|
197
|
+
host.declare(`@scr_cyc_live = external global i64`);
|
|
198
|
+
host.declare(`@scr_cyc_old_freed = external global i64`);
|
|
199
|
+
lines.push(` %sf.live = load i64, ptr @scr_cyc_live`, ` %sf.live1 = sub i64 %sf.live, 1`, ` store i64 %sf.live1, ptr @scr_cyc_live`, ` %sf.blk = getelementptr inbounds i8, ptr %o, i64 -${CYC_HDR}`, ` %sf.genp = getelementptr inbounds i8, ptr %sf.blk, i64 22`, ` %sf.gen = load i16, ptr %sf.genp`, ` %sf.old = icmp eq i16 %sf.gen, 2`, ` br i1 %sf.old, label %sf.oldcount, label %sf.accounted`, `sf.oldcount:`, ` %sf.freed = load i64, ptr @scr_cyc_old_freed`, ` %sf.freed1 = add i64 %sf.freed, 1`, ` store i64 %sf.freed1, ptr @scr_cyc_old_freed`, ` br label %sf.accounted`, `sf.accounted:`);
|
|
200
|
+
}
|
|
201
|
+
const blk = cyc ? "%sf.blk" : "%o";
|
|
202
|
+
lines.push(` %sf.base = load i64, ptr @scr_sa`, ` %sf.spanp = getelementptr inbounds i8, ptr @scr_sa, i64 ${SA_SPAN}`, ` %sf.span = load i64, ptr %sf.spanp`, ` %sf.bi = ptrtoint ptr ${blk} to i64`, ` %sf.off = sub i64 %sf.bi, %sf.base`, ` %sf.in = icmp ult i64 %sf.off, %sf.span`, ` %sf.inx = call i1 @llvm.expect.i1(i1 %sf.in, i1 true)`, ` br i1 %sf.inx, label %sf.push, label %sf.sys`, `sf.push:`, ` %sf.shp = getelementptr inbounds i8, ptr @scr_sa, i64 ${SA_SHIFT}`, ` %sf.sh32 = load i32, ptr %sf.shp`, ` %sf.sh = zext i32 %sf.sh32 to i64`, ` %sf.c = lshr i64 %sf.off, %sf.sh`, ` %sf.c8 = shl i64 %sf.c, 3`, ` %sf.fo = add i64 %sf.c8, ${SA_FREE}`, ` %sf.fp = getelementptr inbounds i8, ptr @scr_sa, i64 %sf.fo`, ` %sf.head = load ptr, ptr %sf.fp`, ` store ptr %sf.head, ptr ${blk}`, ` store ptr ${blk}, ptr %sf.fp`, ` br label %sf.done`, `sf.sys: ; outside the reservation, or the allocator is compiled out`, ` call void @scr_obj_free_note()`, ` call void @scr_rt_free(ptr ${blk})`, ` br label %sf.done`, `sf.done:`);
|
|
203
|
+
return lines;
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=alloc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alloc.js","sourceRoot":"","sources":["../../../src/backend/llvm/alloc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { emitObjectAlloc, emitObjectFree, inlineAllocSupported } from "./alloc.js";
|
|
3
|
+
function host(inlineAlloc) {
|
|
4
|
+
const h = {
|
|
5
|
+
decls: new Set(),
|
|
6
|
+
oom: false,
|
|
7
|
+
sizeType: "i64",
|
|
8
|
+
inlineAlloc,
|
|
9
|
+
declare(decl) {
|
|
10
|
+
h.decls.add(decl);
|
|
11
|
+
},
|
|
12
|
+
needOom() {
|
|
13
|
+
h.oom = true;
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
return h;
|
|
17
|
+
}
|
|
18
|
+
/** Every SSA value and label is defined once (the lines are spliced into
|
|
19
|
+
* one function body). */
|
|
20
|
+
function expectSingleDefinitions(lines) {
|
|
21
|
+
const defs = lines.flatMap((l) => {
|
|
22
|
+
const value = /^\s*(%[\w.]+) = /.exec(l);
|
|
23
|
+
const label = /^([\w.]+):/.exec(l);
|
|
24
|
+
return value ? [value[1]] : label ? [`%${label[1]}`] : [];
|
|
25
|
+
});
|
|
26
|
+
expect(new Set(defs).size).toBe(defs.length);
|
|
27
|
+
}
|
|
28
|
+
describe("emitted object allocation", () => {
|
|
29
|
+
test("inlines only where the runtime allocator state is a 64-bit process global", () => {
|
|
30
|
+
expect(inlineAllocSupported({ pointerBits: 64, targetTriple: "" })).toBe(true);
|
|
31
|
+
expect(inlineAllocSupported({ targetTriple: "x86_64-unknown-linux-gnu" })).toBe(true);
|
|
32
|
+
expect(inlineAllocSupported({ targetTriple: "arm64-apple-macosx14.0.0" })).toBe(true);
|
|
33
|
+
expect(inlineAllocSupported({ pointerBits: 32 })).toBe(false);
|
|
34
|
+
expect(inlineAllocSupported({ wasi: true })).toBe(false);
|
|
35
|
+
expect(inlineAllocSupported({ targetTriple: "wasm32-unknown-wasip1" })).toBe(false);
|
|
36
|
+
expect(inlineAllocSupported({ targetTriple: "x86_64-pc-windows-msvc" })).toBe(false);
|
|
37
|
+
expect(inlineAllocSupported({ targetTriple: "x86_64-w64-windows-gnu" })).toBe(false);
|
|
38
|
+
expect(inlineAllocSupported({ threadInstances: true })).toBe(false);
|
|
39
|
+
});
|
|
40
|
+
test("keeps the out-of-line calls when inlining is off", () => {
|
|
41
|
+
const h = host(false);
|
|
42
|
+
expect(emitObjectAlloc(h, "24", null)).toEqual([
|
|
43
|
+
" %o = call ptr @scr_rt_calloc(i64 24)",
|
|
44
|
+
" %isnull = icmp eq ptr %o, null",
|
|
45
|
+
" br i1 %isnull, label %oom, label %ok",
|
|
46
|
+
"oom:",
|
|
47
|
+
" call void @sc_oom()",
|
|
48
|
+
" unreachable",
|
|
49
|
+
"ok:",
|
|
50
|
+
" call void @scr_obj_alloc_note()",
|
|
51
|
+
]);
|
|
52
|
+
expect(emitObjectAlloc(h, "24", { trace: "@t", free: "@f" })).toEqual([
|
|
53
|
+
" %o = call ptr @scr_cyc_alloc(i64 24, ptr @t, ptr @f)",
|
|
54
|
+
" call void @scr_obj_alloc_note()",
|
|
55
|
+
]);
|
|
56
|
+
expect(emitObjectFree(h, true)).toEqual([
|
|
57
|
+
" call void @scr_obj_free_note()",
|
|
58
|
+
" call void @scr_cyc_free(ptr %o)",
|
|
59
|
+
]);
|
|
60
|
+
expect(emitObjectFree(h, false)).toEqual([
|
|
61
|
+
" call void @scr_obj_free_note()",
|
|
62
|
+
" call void @scr_weak_dispose(ptr %o)",
|
|
63
|
+
" call void @scr_rt_free(ptr %o)",
|
|
64
|
+
]);
|
|
65
|
+
expect([...h.decls].some((d) => d.includes("@scr_sa"))).toBe(false);
|
|
66
|
+
});
|
|
67
|
+
test("inline allocation falls back to the audited out-of-line entry points", () => {
|
|
68
|
+
const h = host(true);
|
|
69
|
+
const plain = emitObjectAlloc(h, "40", null, 16);
|
|
70
|
+
expectSingleDefinitions(plain);
|
|
71
|
+
expect(h.oom).toBe(true);
|
|
72
|
+
// Recycled blocks clear everything past the bytes the caller stores.
|
|
73
|
+
expect(plain).toContain(" %sa.z = getelementptr inbounds i8, ptr %sa.b, i64 16");
|
|
74
|
+
// The slow path is the old sequence: allocate, OOM check, audit note.
|
|
75
|
+
const slow = plain.slice(plain.indexOf("sa.slow:"));
|
|
76
|
+
expect(slow).toContain(" %sa.s = call ptr @scr_rt_calloc(i64 40)");
|
|
77
|
+
expect(slow).toContain(" call void @scr_obj_alloc_note()");
|
|
78
|
+
expect(plain.filter((l) => l.includes("@scr_obj_alloc_note")).length).toBe(1);
|
|
79
|
+
expect(plain.at(-1)).toBe(" %o = phi ptr [ %sa.blk, %sa.fast ], [ %sa.s, %sa.noted ]");
|
|
80
|
+
const cyc = emitObjectAlloc(h, "40", { trace: "@t", free: "@f" });
|
|
81
|
+
expectSingleDefinitions(cyc);
|
|
82
|
+
expect(cyc).toContain(" %sa.n = add i64 40, 32");
|
|
83
|
+
expect(cyc).toContain(" %sa.s = call ptr @scr_cyc_alloc(i64 40, ptr @t, ptr @f)");
|
|
84
|
+
expect(cyc).toContain(" store i64 %sa.live1, ptr @scr_cyc_live");
|
|
85
|
+
expect(h.decls).toContain("@scr_sa = external global { i64, i64, i32, [32 x ptr], [32 x ptr], [32 x ptr] }");
|
|
86
|
+
});
|
|
87
|
+
test("inline frees route foreign blocks and the bypassed allocator to scr_rt_free", () => {
|
|
88
|
+
for (const cyc of [false, true]) {
|
|
89
|
+
const h = host(true);
|
|
90
|
+
const lines = emitObjectFree(h, cyc);
|
|
91
|
+
expectSingleDefinitions(lines);
|
|
92
|
+
const blk = cyc ? "%sf.blk" : "%o";
|
|
93
|
+
const sys = lines.slice(lines.indexOf(lines.find((l) => l.startsWith("sf.sys:"))));
|
|
94
|
+
expect(sys).toContain(" call void @scr_obj_free_note()");
|
|
95
|
+
expect(sys).toContain(` call void @scr_rt_free(ptr ${blk})`);
|
|
96
|
+
expect(lines).toContain(" call void %sf.hook(ptr %o)");
|
|
97
|
+
expect(lines.some((l) => l.includes("@scr_cyc_live"))).toBe(cyc);
|
|
98
|
+
expect(lines.at(-1)).toBe("sf.done:");
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
//# sourceMappingURL=alloc.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alloc.test.js","sourceRoot":"","sources":["../../../src/backend/llvm/alloc.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,17 @@ export interface CallLifetimes {
|
|
|
18
18
|
* initializer and assignment still needs a separate storage proof. */
|
|
19
19
|
projectedLocals: Map<string, Set<string>>;
|
|
20
20
|
}
|
|
21
|
+
/** Read each function once. A whole-value use is unsafe unless it is an
|
|
22
|
+
* explicitly supported projection, invocation, borrowing string operation, or direct-call
|
|
23
|
+
* argument whose target parameter can be proved separately. Traversal of every other consumer
|
|
24
|
+
* reaches the ordinary varRef rejection, including future IR nodes.
|
|
25
|
+
*
|
|
26
|
+
* Projection results may escape: the existing emitter retains extracted
|
|
27
|
+
* payloads. The enclosing union box itself must never be retained, released,
|
|
28
|
+
* stored, returned, captured, or passed to arbitrary runtime code. */
|
|
29
|
+
/** True for class fields stored as nullable instance pointers: a store
|
|
30
|
+
* extracts and retains the payload, so the stored union is only projected. */
|
|
31
|
+
export type NullableFieldTest = (className: string, field: string) => boolean;
|
|
21
32
|
/** Solve dependencies between individual parameters, rather than marking
|
|
22
33
|
* every argument unsafe when one parameter escapes. Begin optimistically
|
|
23
34
|
* inside recursive groups, then propagate each rejection through reverse
|
|
@@ -25,6 +36,7 @@ export interface CallLifetimes {
|
|
|
25
36
|
* do not recurse on the compiler stack or repeatedly rescan function bodies.
|
|
26
37
|
*
|
|
27
38
|
* The result is private to one emission of the finalized IR. No fact is
|
|
28
|
-
* serialized or reused after a compiler transformation.
|
|
29
|
-
* without environments
|
|
30
|
-
|
|
39
|
+
* serialized or reused after a compiler transformation. Parameter facts
|
|
40
|
+
* cover synchronous bodies without environments only; closure bodies get
|
|
41
|
+
* local facts alone. */
|
|
42
|
+
export declare function analyzeCallLifetimes(functions: ReadonlyMap<string, IrFunction>, nullableField?: NullableFieldTest): CallLifetimes;
|
|
@@ -13,15 +13,7 @@ function eligible(local) {
|
|
|
13
13
|
local.type.kind === "string" ||
|
|
14
14
|
local.type.kind === "func"));
|
|
15
15
|
}
|
|
16
|
-
|
|
17
|
-
* explicitly supported projection, invocation, borrowing string operation, or direct-call
|
|
18
|
-
* argument whose target parameter can be proved separately. Traversal of every other consumer
|
|
19
|
-
* reaches the ordinary varRef rejection, including future IR nodes.
|
|
20
|
-
*
|
|
21
|
-
* Projection results may escape: the existing emitter retains extracted
|
|
22
|
-
* payloads. The enclosing union box itself must never be retained, released,
|
|
23
|
-
* stored, returned, captured, or passed to arbitrary runtime code. */
|
|
24
|
-
function collectUses(fn) {
|
|
16
|
+
function collectUses(fn, nullableField) {
|
|
25
17
|
const uses = {
|
|
26
18
|
invalid: new Set(),
|
|
27
19
|
written: new Set(),
|
|
@@ -58,6 +50,19 @@ function collectUses(fn) {
|
|
|
58
50
|
if (node.value.kind === "varRef")
|
|
59
51
|
return true;
|
|
60
52
|
break;
|
|
53
|
+
case "unionEq": {
|
|
54
|
+
// Tag compare plus a borrowed arm compare; neither box escapes.
|
|
55
|
+
const operand = (value) => (value.kind === "varRef" && value.type.kind === "union") || expr(value);
|
|
56
|
+
return operand(node.left) && operand(node.right);
|
|
57
|
+
}
|
|
58
|
+
case "nullish":
|
|
59
|
+
// The narrowed shape only tests the tag and extracts the payload.
|
|
60
|
+
// The pass-through shape returns the box itself.
|
|
61
|
+
if (node.left.kind === "varRef" &&
|
|
62
|
+
node.left.type.kind === "union" &&
|
|
63
|
+
node.type.kind !== "union")
|
|
64
|
+
return expr(node.right);
|
|
65
|
+
break;
|
|
61
66
|
case "fieldGet":
|
|
62
67
|
case "recordGet":
|
|
63
68
|
if (node.obj.kind === "varRef")
|
|
@@ -104,6 +109,12 @@ function collectUses(fn) {
|
|
|
104
109
|
case "varDecl":
|
|
105
110
|
uses.declarations.set(node.localId, (uses.declarations.get(node.localId) ?? 0) + 1);
|
|
106
111
|
break;
|
|
112
|
+
case "fieldSet":
|
|
113
|
+
if (node.value.kind === "varRef" &&
|
|
114
|
+
node.value.type.kind === "union" &&
|
|
115
|
+
nullableField(node.className, node.field))
|
|
116
|
+
return expr(node.obj);
|
|
117
|
+
break;
|
|
107
118
|
case "assign":
|
|
108
119
|
uses.written.add(node.localId);
|
|
109
120
|
// Sequence expressions can rebind a previous call argument before
|
|
@@ -143,9 +154,10 @@ function collectUses(fn) {
|
|
|
143
154
|
* do not recurse on the compiler stack or repeatedly rescan function bodies.
|
|
144
155
|
*
|
|
145
156
|
* The result is private to one emission of the finalized IR. No fact is
|
|
146
|
-
* serialized or reused after a compiler transformation.
|
|
147
|
-
* without environments
|
|
148
|
-
|
|
157
|
+
* serialized or reused after a compiler transformation. Parameter facts
|
|
158
|
+
* cover synchronous bodies without environments only; closure bodies get
|
|
159
|
+
* local facts alone. */
|
|
160
|
+
export function analyzeCallLifetimes(functions, nullableField = () => false) {
|
|
149
161
|
const usesByFunction = new Map();
|
|
150
162
|
const nodes = new Map();
|
|
151
163
|
const unsafe = [];
|
|
@@ -157,13 +169,28 @@ export function analyzeCallLifetimes(functions) {
|
|
|
157
169
|
projectedLocals: new Map(),
|
|
158
170
|
};
|
|
159
171
|
for (const fn of functions.values()) {
|
|
160
|
-
if (fn.async || fn.generator
|
|
172
|
+
if (fn.async || fn.generator)
|
|
161
173
|
continue;
|
|
162
|
-
const uses = collectUses(fn);
|
|
174
|
+
const uses = collectUses(fn, nullableField);
|
|
163
175
|
usesByFunction.set(fn.name, uses);
|
|
176
|
+
// Class-capturing bodies get only local facts (computed below from
|
|
177
|
+
// their uses; class captures are already invalid). Binding and
|
|
178
|
+
// parameter facts stay limited to plain functions and closures.
|
|
179
|
+
if (fn.classCaptures !== undefined)
|
|
180
|
+
continue;
|
|
164
181
|
const locals = new Map(fn.locals.map((local) => [local.id, local]));
|
|
165
|
-
const borrowed = new Set();
|
|
166
182
|
const stable = (local) => !local.boxed && !local.tdz && !uses.written.has(local.id);
|
|
183
|
+
result.bindings.set(fn.name, new Set(fn.locals
|
|
184
|
+
.filter((local) => stable(local) && uses.declarations.get(local.id) === 1)
|
|
185
|
+
.map((local) => local.id)));
|
|
186
|
+
if (fn.captures !== undefined) {
|
|
187
|
+
// A closure body is invoked through its environment trampoline, so
|
|
188
|
+
// its parameters keep the owned convention and no direct call can
|
|
189
|
+
// forward to them. Its own unboxed locals follow the same rules as
|
|
190
|
+
// any synchronous body; captured cells are boxed and marked invalid.
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const borrowed = new Set();
|
|
167
194
|
fn.params.forEach((param, index) => {
|
|
168
195
|
const local = locals.get(param.localId);
|
|
169
196
|
if (local && isRefCounted(param.type) && stable(local) && !uses.declarations.has(local.id))
|
|
@@ -171,9 +198,6 @@ export function analyzeCallLifetimes(functions) {
|
|
|
171
198
|
});
|
|
172
199
|
if (borrowed.size > 0)
|
|
173
200
|
result.borrowed.set(fn.name, borrowed);
|
|
174
|
-
result.bindings.set(fn.name, new Set(fn.locals
|
|
175
|
-
.filter((local) => stable(local) && uses.declarations.get(local.id) === 1)
|
|
176
|
-
.map((local) => local.id)));
|
|
177
201
|
nodes.set(fn.name, fn.params.map((param) => {
|
|
178
202
|
const local = locals.get(param.localId);
|
|
179
203
|
const safe = local !== undefined &&
|