@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.
Files changed (368) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +5 -18
  2. package/dist/backend/cycle-analysis.d.ts +21 -9
  3. package/dist/backend/cycle-analysis.js +139 -67
  4. package/dist/backend/cycle-analysis.js.map +1 -1
  5. package/dist/backend/cycle-analysis.test.js +283 -3
  6. package/dist/backend/cycle-analysis.test.js.map +1 -1
  7. package/dist/backend/cycle-mutability.d.ts +39 -0
  8. package/dist/backend/cycle-mutability.js +205 -0
  9. package/dist/backend/cycle-mutability.js.map +1 -0
  10. package/dist/backend/link-plan-core.d.ts +2 -1
  11. package/dist/backend/link-plan-core.js +15 -3
  12. package/dist/backend/link-plan-core.js.map +1 -1
  13. package/dist/backend/link-plan.d.ts +2 -1
  14. package/dist/backend/link-plan.js.map +1 -1
  15. package/dist/backend/llvm/alloc.d.ts +40 -0
  16. package/dist/backend/llvm/alloc.js +205 -0
  17. package/dist/backend/llvm/alloc.js.map +1 -0
  18. package/dist/backend/llvm/alloc.test.d.ts +1 -0
  19. package/dist/backend/llvm/alloc.test.js +102 -0
  20. package/dist/backend/llvm/alloc.test.js.map +1 -0
  21. package/dist/backend/llvm/call-lifetimes.d.ts +15 -3
  22. package/dist/backend/llvm/call-lifetimes.js +42 -18
  23. package/dist/backend/llvm/call-lifetimes.js.map +1 -1
  24. package/dist/backend/llvm/call-lifetimes.test.js +170 -0
  25. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
  26. package/dist/backend/llvm/classes.d.ts +4 -1
  27. package/dist/backend/llvm/classes.js +35 -32
  28. package/dist/backend/llvm/classes.js.map +1 -1
  29. package/dist/backend/llvm/classes.test.js +36 -3
  30. package/dist/backend/llvm/classes.test.js.map +1 -1
  31. package/dist/backend/llvm/common.d.ts +13 -0
  32. package/dist/backend/llvm/common.js +30 -0
  33. package/dist/backend/llvm/common.js.map +1 -1
  34. package/dist/backend/llvm/constant-callbacks.d.ts +19 -3
  35. package/dist/backend/llvm/constant-callbacks.js +289 -52
  36. package/dist/backend/llvm/constant-callbacks.js.map +1 -1
  37. package/dist/backend/llvm/constant-callbacks.test.js +140 -3
  38. package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
  39. package/dist/backend/llvm/dense-array-access.d.ts +29 -0
  40. package/dist/backend/llvm/dense-array-access.js +335 -0
  41. package/dist/backend/llvm/dense-array-access.js.map +1 -0
  42. package/dist/backend/llvm/dense-array-access.test.d.ts +1 -0
  43. package/dist/backend/llvm/dense-array-access.test.js +149 -0
  44. package/dist/backend/llvm/dense-array-access.test.js.map +1 -0
  45. package/dist/backend/llvm/dyn.d.ts +34 -0
  46. package/dist/backend/llvm/dyn.js +189 -1
  47. package/dist/backend/llvm/dyn.js.map +1 -1
  48. package/dist/backend/llvm/emitter.d.ts +124 -4
  49. package/dist/backend/llvm/emitter.js +623 -105
  50. package/dist/backend/llvm/emitter.js.map +1 -1
  51. package/dist/backend/llvm/emitter.test.js +68 -6
  52. package/dist/backend/llvm/emitter.test.js.map +1 -1
  53. package/dist/backend/llvm/expr-async.js +58 -4
  54. package/dist/backend/llvm/expr-async.js.map +1 -1
  55. package/dist/backend/llvm/expr-async.test.d.ts +1 -0
  56. package/dist/backend/llvm/expr-async.test.js +62 -0
  57. package/dist/backend/llvm/expr-async.test.js.map +1 -0
  58. package/dist/backend/llvm/expr-calls.js +64 -6
  59. package/dist/backend/llvm/expr-calls.js.map +1 -1
  60. package/dist/backend/llvm/expr-containers.js +16 -5
  61. package/dist/backend/llvm/expr-containers.js.map +1 -1
  62. package/dist/backend/llvm/expr-control.js +92 -2
  63. package/dist/backend/llvm/expr-control.js.map +1 -1
  64. package/dist/backend/llvm/expr-dispatch.js +2 -0
  65. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  66. package/dist/backend/llvm/expr-dynamic.js +174 -25
  67. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  68. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  69. package/dist/backend/llvm/expr-primitives.js +52 -24
  70. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  71. package/dist/backend/llvm/expr-primitives.test.js +1 -1
  72. package/dist/backend/llvm/expr-records.js +3 -3
  73. package/dist/backend/llvm/expr-records.js.map +1 -1
  74. package/dist/backend/llvm/expr-stream-bridges.js +59 -2
  75. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  76. package/dist/backend/llvm/expr-stream-bridges.test.js +1 -1
  77. package/dist/backend/llvm/integer-remainder.d.ts +11 -0
  78. package/dist/backend/llvm/integer-remainder.js +91 -0
  79. package/dist/backend/llvm/integer-remainder.js.map +1 -1
  80. package/dist/backend/llvm/layouts.d.ts +2 -1
  81. package/dist/backend/llvm/layouts.js +3 -2
  82. package/dist/backend/llvm/layouts.js.map +1 -1
  83. package/dist/backend/llvm/lazy-captures.d.ts +16 -0
  84. package/dist/backend/llvm/lazy-captures.js +96 -0
  85. package/dist/backend/llvm/lazy-captures.js.map +1 -0
  86. package/dist/backend/llvm/lazy-captures.test.d.ts +1 -0
  87. package/dist/backend/llvm/lazy-captures.test.js +78 -0
  88. package/dist/backend/llvm/lazy-captures.test.js.map +1 -0
  89. package/dist/backend/llvm/lib-filesystem.js +3 -4
  90. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  91. package/dist/backend/llvm/local-array-reads.d.ts +5 -1
  92. package/dist/backend/llvm/local-array-reads.js +78 -17
  93. package/dist/backend/llvm/local-array-reads.js.map +1 -1
  94. package/dist/backend/llvm/local-array-reads.test.js +78 -1
  95. package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
  96. package/dist/backend/llvm/local-union-storage.d.ts +5 -1
  97. package/dist/backend/llvm/local-union-storage.js +48 -6
  98. package/dist/backend/llvm/local-union-storage.js.map +1 -1
  99. package/dist/backend/llvm/local-union-storage.test.js +91 -4
  100. package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
  101. package/dist/backend/llvm/map-read-lifetimes.test.js +1 -1
  102. package/dist/backend/llvm/nullable-fields.d.ts +28 -0
  103. package/dist/backend/llvm/nullable-fields.js +45 -0
  104. package/dist/backend/llvm/nullable-fields.js.map +1 -0
  105. package/dist/backend/llvm/nullable-fields.test.d.ts +1 -0
  106. package/dist/backend/llvm/nullable-fields.test.js +48 -0
  107. package/dist/backend/llvm/nullable-fields.test.js.map +1 -0
  108. package/dist/backend/llvm/serialized-ir-emission.test.d.ts +1 -0
  109. package/dist/backend/llvm/serialized-ir-emission.test.js +52 -0
  110. package/dist/backend/llvm/serialized-ir-emission.test.js.map +1 -0
  111. package/dist/backend/llvm/shapes.d.ts +69 -2
  112. package/dist/backend/llvm/shapes.js +259 -27
  113. package/dist/backend/llvm/shapes.js.map +1 -1
  114. package/dist/backend/llvm/shapes.test.js +114 -5
  115. package/dist/backend/llvm/shapes.test.js.map +1 -1
  116. package/dist/backend/llvm/stack-callbacks.js +2 -3
  117. package/dist/backend/llvm/stack-callbacks.js.map +1 -1
  118. package/dist/backend/llvm/stack-captures.d.ts +3 -1
  119. package/dist/backend/llvm/stack-captures.js +5 -3
  120. package/dist/backend/llvm/stack-captures.js.map +1 -1
  121. package/dist/backend/llvm/stack-unions.test.js +38 -1
  122. package/dist/backend/llvm/stack-unions.test.js.map +1 -1
  123. package/dist/backend/llvm/string-construction.test.js +1 -1
  124. package/dist/backend/llvm/string-key-hash.d.ts +8 -0
  125. package/dist/backend/llvm/string-key-hash.js +59 -0
  126. package/dist/backend/llvm/string-key-hash.js.map +1 -0
  127. package/dist/backend/llvm/string-key-hash.test.d.ts +1 -0
  128. package/dist/backend/llvm/string-key-hash.test.js +34 -0
  129. package/dist/backend/llvm/string-key-hash.test.js.map +1 -0
  130. package/dist/backend/llvm/string-lifetimes.test.js +41 -4
  131. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
  132. package/dist/backend/llvm/switch-dispatch.js +1 -1
  133. package/dist/backend/llvm/switch-dispatch.js.map +1 -1
  134. package/dist/backend/llvm/switch-dispatch.test.js +2 -2
  135. package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
  136. package/dist/backend/may-throw.js +3 -0
  137. package/dist/backend/may-throw.js.map +1 -1
  138. package/dist/backend/may-throw.test.js +1 -1
  139. package/dist/backend/native/cache-warm.d.ts +2 -1
  140. package/dist/backend/native/cache-warm.js.map +1 -1
  141. package/dist/backend/native/contracts.d.ts +3 -2
  142. package/dist/backend/native/contracts.js.map +1 -1
  143. package/dist/backend/native/runtime-inputs.d.ts +1 -1
  144. package/dist/backend/native/runtime-inputs.js +1 -0
  145. package/dist/backend/native/runtime-inputs.js.map +1 -1
  146. package/dist/backend/native-codegen-core.d.ts +2 -1
  147. package/dist/backend/native-codegen-core.js.map +1 -1
  148. package/dist/backend/native-codegen.d.ts +5 -0
  149. package/dist/backend/native-codegen.js +4 -0
  150. package/dist/backend/native-codegen.js.map +1 -1
  151. package/dist/backend/native-codegen.test.js +23 -0
  152. package/dist/backend/native-codegen.test.js.map +1 -1
  153. package/dist/backend/native-link-info-core.d.ts +3 -2
  154. package/dist/backend/native-link-info-core.js.map +1 -1
  155. package/dist/backend/native-link-info.d.ts +2 -1
  156. package/dist/backend/native-link-info.js.map +1 -1
  157. package/dist/backend/native-link-info.test.js +2 -2
  158. package/dist/backend/native-link-info.test.js.map +1 -1
  159. package/dist/backend/native-tools.d.ts +3 -1
  160. package/dist/backend/native-tools.js +0 -1
  161. package/dist/backend/native-tools.js.map +1 -1
  162. package/dist/backend/optimization.d.ts +25 -0
  163. package/dist/backend/optimization.js +21 -0
  164. package/dist/backend/optimization.js.map +1 -0
  165. package/dist/backend/optimization.test.d.ts +1 -0
  166. package/dist/backend/optimization.test.js +24 -0
  167. package/dist/backend/optimization.test.js.map +1 -0
  168. package/dist/backend/runtime-abi.d.ts +2 -2
  169. package/dist/backend/runtime-abi.js +2 -2
  170. package/dist/backend/runtime-pack-core.d.ts +15 -4
  171. package/dist/backend/runtime-pack-core.js +23 -12
  172. package/dist/backend/runtime-pack-core.js.map +1 -1
  173. package/dist/backend/runtime-pack-native.d.ts +7 -3
  174. package/dist/backend/runtime-pack-native.js +0 -3
  175. package/dist/backend/runtime-pack-native.js.map +1 -1
  176. package/dist/backend/runtime-pack-targets.test.js +1 -1
  177. package/dist/backend/runtime-pack.d.ts +20 -2
  178. package/dist/backend/runtime-pack.js +23 -0
  179. package/dist/backend/runtime-pack.js.map +1 -1
  180. package/dist/backend/runtime-pack.test.js +115 -2
  181. package/dist/backend/runtime-pack.test.js.map +1 -1
  182. package/dist/backend/target-diagnostics.test.js +1 -1
  183. package/dist/backend/targets.d.ts +2 -1
  184. package/dist/backend/targets.js +1 -1
  185. package/dist/backend/targets.js.map +1 -1
  186. package/dist/cli/command.js +5 -4
  187. package/dist/cli/command.js.map +1 -1
  188. package/dist/cli/host.d.ts +2 -1
  189. package/dist/cli/usage.d.ts +1 -1
  190. package/dist/cli/usage.js +5 -2
  191. package/dist/cli/usage.js.map +1 -1
  192. package/dist/compile-types.d.ts +5 -2
  193. package/dist/diagnostics/diagnostic.js +10 -8
  194. package/dist/diagnostics/diagnostic.js.map +1 -1
  195. package/dist/executable/executable-cache.d.ts +2 -2
  196. package/dist/executable/executable-cache.js +7 -4
  197. package/dist/executable/executable-cache.js.map +1 -1
  198. package/dist/executable/executable-cache.test.js +20 -0
  199. package/dist/executable/executable-cache.test.js.map +1 -1
  200. package/dist/frontend/lowering/abstract-equality.js +5 -49
  201. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  202. package/dist/frontend/lowering/array-values.d.ts +23 -0
  203. package/dist/frontend/lowering/array-values.js +129 -0
  204. package/dist/frontend/lowering/array-values.js.map +1 -1
  205. package/dist/frontend/lowering/builtins/errors.js +17 -2
  206. package/dist/frontend/lowering/builtins/errors.js.map +1 -1
  207. package/dist/frontend/lowering/builtins/process.d.ts +6 -17
  208. package/dist/frontend/lowering/builtins/process.js +56 -29
  209. package/dist/frontend/lowering/builtins/process.js.map +1 -1
  210. package/dist/frontend/lowering/caught-value-dispatch.d.ts +11 -0
  211. package/dist/frontend/lowering/caught-value-dispatch.js +87 -0
  212. package/dist/frontend/lowering/caught-value-dispatch.js.map +1 -0
  213. package/dist/frontend/lowering/class-assertions.d.ts +4 -0
  214. package/dist/frontend/lowering/class-assertions.js +12 -4
  215. package/dist/frontend/lowering/class-assertions.js.map +1 -1
  216. package/dist/frontend/lowering/class-callbacks.d.ts +3 -3
  217. package/dist/frontend/lowering/class-callbacks.js +18 -5
  218. package/dist/frontend/lowering/class-callbacks.js.map +1 -1
  219. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +1 -0
  220. package/dist/frontend/lowering/class-dynamic-dispatch.js +4 -1
  221. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  222. package/dist/frontend/lowering/class-method-mutations.d.ts +5 -0
  223. package/dist/frontend/lowering/class-method-mutations.js +472 -0
  224. package/dist/frontend/lowering/class-method-mutations.js.map +1 -0
  225. package/dist/frontend/lowering/class-method-values.js +25 -5
  226. package/dist/frontend/lowering/class-method-values.js.map +1 -1
  227. package/dist/frontend/lowering/class-prototypes.js +8 -2
  228. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  229. package/dist/frontend/lowering/class-unions.d.ts +16 -0
  230. package/dist/frontend/lowering/class-unions.js +127 -0
  231. package/dist/frontend/lowering/class-unions.js.map +1 -0
  232. package/dist/frontend/lowering/coercions/builders.js +8 -1
  233. package/dist/frontend/lowering/coercions/builders.js.map +1 -1
  234. package/dist/frontend/lowering/coercions/function-adapters.js +2 -0
  235. package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
  236. package/dist/frontend/lowering/coercions/identity.d.ts +7 -0
  237. package/dist/frontend/lowering/coercions/identity.js +26 -0
  238. package/dist/frontend/lowering/coercions/identity.js.map +1 -0
  239. package/dist/frontend/lowering/coercions/structural.js +9 -6
  240. package/dist/frontend/lowering/coercions/structural.js.map +1 -1
  241. package/dist/frontend/lowering/collection-narrowing.d.ts +6 -0
  242. package/dist/frontend/lowering/collection-narrowing.js +31 -0
  243. package/dist/frontend/lowering/collection-narrowing.js.map +1 -0
  244. package/dist/frontend/lowering/containers/array-callback-call.d.ts +7 -0
  245. package/dist/frontend/lowering/containers/array-callback-call.js +52 -0
  246. package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -0
  247. package/dist/frontend/lowering/containers/array-callbacks.d.ts +1 -1
  248. package/dist/frontend/lowering/containers/array-callbacks.js +363 -49
  249. package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
  250. package/dist/frontend/lowering/containers/array-concat.d.ts +7 -0
  251. package/dist/frontend/lowering/containers/array-concat.js +130 -0
  252. package/dist/frontend/lowering/containers/array-concat.js.map +1 -0
  253. package/dist/frontend/lowering/containers/array-construction.d.ts +2 -0
  254. package/dist/frontend/lowering/containers/array-construction.js +95 -3
  255. package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
  256. package/dist/frontend/lowering/containers/array-methods.d.ts +1 -11
  257. package/dist/frontend/lowering/containers/array-methods.js +43 -132
  258. package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
  259. package/dist/frontend/lowering/containers/collection-methods.js +10 -1
  260. package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
  261. package/dist/frontend/lowering/containers/indexed-objects.js +56 -70
  262. package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
  263. package/dist/frontend/lowering/cycle-initialization.d.ts +41 -0
  264. package/dist/frontend/lowering/cycle-initialization.js +277 -0
  265. package/dist/frontend/lowering/cycle-initialization.js.map +1 -0
  266. package/dist/frontend/lowering/expressions/evaluation-safety.js +4 -0
  267. package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
  268. package/dist/frontend/lowering/expressions/object-literals.js +138 -32
  269. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  270. package/dist/frontend/lowering/expressions/union-field-write.d.ts +4 -4
  271. package/dist/frontend/lowering/expressions/union-field-write.js +54 -44
  272. package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -1
  273. package/dist/frontend/lowering/iterator-adapters.d.ts +20 -0
  274. package/dist/frontend/lowering/iterator-adapters.js +605 -0
  275. package/dist/frontend/lowering/iterator-adapters.js.map +1 -0
  276. package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
  277. package/dist/frontend/lowering/lower-array-sort.js +44 -5
  278. package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
  279. package/dist/frontend/lowering/lower-array-sort.test.d.ts +1 -0
  280. package/dist/frontend/lowering/lower-array-sort.test.js +31 -0
  281. package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -0
  282. package/dist/frontend/lowering/lower-assert.js +7 -0
  283. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  284. package/dist/frontend/lowering/lower-builtin-values.js +1 -0
  285. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  286. package/dist/frontend/lowering/lower-calls.d.ts +3 -3
  287. package/dist/frontend/lowering/lower-calls.js +162 -121
  288. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  289. package/dist/frontend/lowering/lower-classes.d.ts +2 -0
  290. package/dist/frontend/lowering/lower-classes.js +45 -43
  291. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  292. package/dist/frontend/lowering/lower-exprs.d.ts +9 -2
  293. package/dist/frontend/lowering/lower-exprs.js +390 -157
  294. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  295. package/dist/frontend/lowering/lower-functions.js +32 -19
  296. package/dist/frontend/lowering/lower-functions.js.map +1 -1
  297. package/dist/frontend/lowering/lower-inspect.js +26 -2
  298. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  299. package/dist/frontend/lowering/lower-modules.js +10 -2
  300. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  301. package/dist/frontend/lowering/lower-stmts.js +46 -58
  302. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  303. package/dist/frontend/lowering/lowerer.d.ts +37 -0
  304. package/dist/frontend/lowering/lowerer.js +283 -18
  305. package/dist/frontend/lowering/lowerer.js.map +1 -1
  306. package/dist/frontend/lowering/native-ffi.js +3 -1
  307. package/dist/frontend/lowering/native-ffi.js.map +1 -1
  308. package/dist/frontend/lowering/runtime-optional-provenance.d.ts +15 -0
  309. package/dist/frontend/lowering/runtime-optional-provenance.js +40 -0
  310. package/dist/frontend/lowering/runtime-optional-provenance.js.map +1 -0
  311. package/dist/frontend/lowering/sanitize-class-types.test.js +2 -2
  312. package/dist/frontend/lowering/strict-equality.d.ts +9 -0
  313. package/dist/frontend/lowering/strict-equality.js +116 -0
  314. package/dist/frontend/lowering/strict-equality.js.map +1 -0
  315. package/dist/frontend/lowering/surfaces.js +3 -0
  316. package/dist/frontend/lowering/surfaces.js.map +1 -1
  317. package/dist/frontend/lowering/union-comparison.d.ts +5 -0
  318. package/dist/frontend/lowering/union-comparison.js +47 -0
  319. package/dist/frontend/lowering/union-comparison.js.map +1 -0
  320. package/dist/frontend/program.d.ts +38 -2
  321. package/dist/frontend/program.js +440 -59
  322. package/dist/frontend/program.js.map +1 -1
  323. package/dist/frontend/program.test.js +59 -6
  324. package/dist/frontend/program.test.js.map +1 -1
  325. package/dist/frontend/type-mapper.d.ts +1 -1
  326. package/dist/frontend/type-mapper.js +89 -14
  327. package/dist/frontend/type-mapper.js.map +1 -1
  328. package/dist/frontend/type-mapper.test.js +15 -3
  329. package/dist/frontend/type-mapper.test.js.map +1 -1
  330. package/dist/index.js +25 -9
  331. package/dist/index.js.map +1 -1
  332. package/dist/ir/analysis.d.ts +3 -1
  333. package/dist/ir/analysis.js +4 -0
  334. package/dist/ir/analysis.js.map +1 -1
  335. package/dist/ir/builtin-signatures.js +2 -3
  336. package/dist/ir/builtin-signatures.js.map +1 -1
  337. package/dist/ir/constant-tables.test.js +1 -1
  338. package/dist/ir/initializer-bindings.test.js +1 -1
  339. package/dist/ir/ir.d.ts +78 -15
  340. package/dist/ir/ir.js +20 -6
  341. package/dist/ir/ir.js.map +1 -1
  342. package/dist/ir/scalar-records.test.js +1 -1
  343. package/dist/ir/serialize.d.ts +1 -1
  344. package/dist/ir/serialize.js +3 -3
  345. package/dist/ir/serialize.js.map +1 -1
  346. package/dist/ir/traverse.js +8 -0
  347. package/dist/ir/traverse.js.map +1 -1
  348. package/dist/ir/validate.js +118 -20
  349. package/dist/ir/validate.js.map +1 -1
  350. package/dist/ir/validate.test.js +269 -8
  351. package/dist/ir/validate.test.js.map +1 -1
  352. package/dist/library/fence-eval.test.js +1 -1
  353. package/dist/library/int-infer.test.js +4 -4
  354. package/dist/library/library-cache.test.js +5 -5
  355. package/dist/library/library-profile.d.ts +2 -1
  356. package/dist/library/library-profile.js +4 -3
  357. package/dist/library/library-profile.js.map +1 -1
  358. package/dist/native/compiler.js.map +1 -1
  359. package/dist/native/compiler.test.js +2 -2
  360. package/dist/native/library.d.ts +2 -1
  361. package/dist/native/library.js.map +1 -1
  362. package/dist/native/prepare.js +27 -3
  363. package/dist/native/prepare.js.map +1 -1
  364. package/dist/native/sanitizer.d.ts +3 -2
  365. package/dist/native/sanitizer.js +3 -13
  366. package/dist/native/sanitizer.js.map +1 -1
  367. package/package.json +20 -20
  368. 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: "release" | "dev";
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.runtimeObjects,
12
- ...options.runtimeArchives,
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":"AAAA,oFAAoF;AACpF,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,MAAM,EAAE;YACN,OAAO,CAAC,aAAa;YACrB,GAAG,CAAC,OAAO,CAAC,iBAAiB,IAAI,EAAE,CAAC;YACpC,GAAG,OAAO,CAAC,YAAY;YACvB,GAAG,OAAO,CAAC,cAAc;YACzB,GAAG,OAAO,CAAC,eAAe;SAC3B;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"}
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: "release" | "dev";
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":"AAWA,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"}
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. Synchronous bodies
29
- * without environments are the only supported calling convention. */
30
- export declare function analyzeCallLifetimes(functions: ReadonlyMap<string, IrFunction>): CallLifetimes;
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
- /** Read each function once. A whole-value use is unsafe unless it is an
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. Synchronous bodies
147
- * without environments are the only supported calling convention. */
148
- export function analyzeCallLifetimes(functions) {
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 || fn.captures !== undefined || fn.classCaptures !== undefined)
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 &&