Skip to content

repsel: promotion census — make "zero values promoted" a visible, gated state instead of an invisible one #7106

Closed

Description

@proggeramlug

--opt-report (#6952) can tell you, for one build, which values got an unboxed
representation and which did not. What it cannot do is tell you that the answer
changed — or that it has been zero all along.

#7034 established the state of things by hand-instrumenting the compiler:

  • Ptr<Shape> promotes nothing at all on benchmarks/app-patterns/kernels/batch.ts,
    the object/property-heavy program that representation exists for.
    PERRY_PTR_SHAPE_LOCALS=0 versus the default produced a byte-identical
    binary (4,294,904 bytes, __text 3,804,424).
  • Across benchmarks/suite, only 3 files promote a shape local, and each
    promotes exactly one.

Nobody knew any of that until somebody went looking. That is the failure to
make impossible to repeat.

Ask

A per-workload, per-representation census recorded as a ratcheted baseline,
so a drop turns a build red.

Per representation, not aggregated: the interesting signal is Ptr<Shape> = 0
while canonical Str ≠ 0. One total hides exactly that.

The hard part

CLAUDE.md, "★ Four ways a gate can be unable to fail", case 4 — the gate runs
but its subject never did
. A census that faithfully reports Ptr<Shape>: 0
and exits green is worth nothing: that is the state the project is in
today.
So the census needs, beyond floors:

  • floors that can actually be violated (the honest floor for Ptr<Shape> on
    real code is zero, and a zero floor can never fail);
  • a liveness assertion on the instrument itself — a fixture that definitely
    promotes, which fails the census if its count reads zero, so that "zero
    because nothing promoted" is distinguishable from "zero because nobody
    increments the counter";
  • verification by sabotage in both directions.

Related

Activity

  1. proggeramlug commented on Jul 31, 2026

    @proggeramlug
    ContributorAuthor

    The census's first verdict is measured and written up in #7128.

    Headline for this issue specifically: the census works, and its
    selected/consumed split (#7117/#7119) is what made the result honest.

    Corpus-wide canonical-i32 went 13 → 64 and from promoting in 2 of 18 real
    workloads to 17 of 18 — and it changes the emitted object on 2 of them.
    Without the consumed column the answer would have read "64 promotions, looks
    great".

    Also from that run, four instrumentation defects worth tracking here:

    • PERRY_CANONICAL_I32_LOCALS=0 is not representation-isolating — it also
      disables all Ptr<Shape> consumption (repsel_context_allows_ptr_shape: repsel_allows). Under that knob the census reads ptr-shape 7 selected /
      0 consumed with all six sites NEVER FIRES.
    • PERRY_CANONICAL_STR_LOCALS=0 is not scoped to Str locals either (it gates
      nanbox_string_ref_boxed), so 24 of 26 workloads emit differently under it.
    • every __pshape clone has zero call sites and is dead-stripped before the
      object, so the 8 consumed_receiver entries count consumption inside
      functions that never ship.
    • Ptr<NumArray>: 6 selected, and turning it off leaves every real workload
      byte-identical.

    And one that affects the census's own method: object emission is
    nondeterministic on Linux (the module name embeds pid + nanotime), so
    object-hash A/B is macOS-only today.

  2. proggeramlug commented on Aug 5, 2026

    @proggeramlug
    ContributorAuthor

    Delivered: benchmarks/repsel_census/baseline.json, scripts/compiler_output_harness/repsel_census.py, tests/test_repsel_census.py, and a repsel-census job in test.yml with floors and sabotage checks.

    One follow-up remains and is tracked separately: the job is not yet in branch protection's required contexts, so it cannot turn a merge red.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions