Commit Graph
2 Commits
Author SHA1 Message Date
Chris Tate d97e816848 Keep integer clones off records that may be views
A checked conversion can answer a record view: an object of the target
record type whose fields live in the record it views, at that record's
offsets (record-views.ts). An integer clone read the fields of a borrowed
record at its own shape's offsets, so for a view it read the view's unused
slots and returned wrong results.

Record shapes that may be views are no longer references a clone reads, so
functions that read them keep the ordinary body, which reads a view's fields
through the original record. The emitter now plans integer clones after
record views.

integer-recursion-records.ts gains a recursive sum over a view.
2026-10-27 21:15:37 -05:00
Chris Tate 677c74c78a Give integer clones borrowed records and worker programs
Integer clones run a pure number function on int32 values and fall back to
the ordinary body when a value leaves the int32 range. Until now a clone
could only take numbers, booleans and borrowed number arrays, and worker
programs had no clones. Recursive functions that walk a record graph, such
as a tree count, always ran on doubles.

A clone now also takes borrowed record parameters:

- A parameter qualifies when its type is a record or `R | null` for a
  record `R`, and its function borrows it.
- The clone reads number fields (exactly int32, otherwise it falls back),
  boolean fields and reference fields of those records in place, tests
  references against `null`, narrows them to the record arm (`null` falls
  back, so the ordinary body reports it), and passes them to other clones.
- A clone has no effect, so the records it reaches stay alive and unchanged
  while it runs: it reads them without retaining them.
- Fields that a clone cannot read in place (inline unions, optional
  properties, other kinds) keep the function on the ordinary path, as do
  class instances.

ELF worker executables now have clones too:

- The stack guard is the thread's own.
- A clone polls the thread's pending word, which a stop request also sets,
  when it is called and every 64 iterations of a loop over plain tail
  calls. On a set word it falls back, and its dispatcher forwards the
  pending exception or stop. Accumulating loops need no poll: their virtual
  stack bounds them.
- Worker programs on other targets keep no clones.

New corpus programs: integer-recursion-records.ts and
integer-recursion-records-workers.ts.
2026-10-27 21:02:26 -05:00