Skip to content

Make components small: custom-section GC + component-level reachability GC + canon seam dissolution #239

Description

@avrabe

Problem

WebAssembly Components are large. The fixtures in this repo are ~2.3 MB each (calculator.wasm, datetime.wasm, hello_rust_host.wasm). component_optimizer.rs today optimizes the core module code inside a component (and does type-dedup + adapter/async specialization), but two large size sources are untouched:

  1. Custom sections are never stripped. There is no production custom-section GC for components (the custom_sections: vec![] references are test fixtures only). Components ship with embedded WIT component-type metadata, producers, name, and DWARF .debug_* sections — none of which affect execution semantics, all of which inflate the binary.
  2. No component-level reachability GC. Canonical optimization is stubbed: component_optimizer.rs:624 reads // Future: Inline trivial lift/lower pairs. Unused type defs, aliases, canon lift/lower functions, and core funcs unreachable from the component's exports are not pruned across the instantiation/alias graph.

Proposal — "make components small", in loom's provably-correct idiom

Phases, ordered by safety so they sequence cleanly after the behavioral gate (#238):

Phase A — custom-section GC (cheapest, biggest, safe without #238).
Strip producers, name, and .debug_* (DWARF) sections; opt-in strip of the component-type metadata section (does not affect execution, but tooling/wit-component introspection depends on it — hence opt-in, default-preserve). Custom sections are semantically inert ⇒ removal is trivially sound and behavioral-gate-checkable.

Phase B — component reachability GC (structural, sound).
The component analog of eliminate_dead_functions: mark-and-sweep over the component's export → instance → alias → canon → core-func graph; drop everything unreachable. Must be #196-safe — keep exports, start, and indirect/element-table targets live; conservative on parse failure.

Phase C — canonical ABI seam dissolution (needs #238).
Fold trivial lift/lower pairs and pass-through fused adapters at the component boundary (the line-624 TODO). This is the #219 seam at the component ABI; canon glue is hard to Z3-verify, so it rides the behavioral differential (#238) as its gate.

Dependencies / sequencing

Acceptance

  • Phase A: measurable byte reduction on the component fixtures with byte-for-byte identical execution (differential-clean)
  • Phase B: unreachable types/aliases/canon/core-funcs pruned; exports + indirect targets preserved; dogfood + components still validate and run identically
  • Phase C: trivial lift/lower folds gated by Behavioral differential as an optimization gate (self-certify non-Z3-backstoppable transforms) #238
  • CLI reports component section-level size breakdown (code vs types vs custom) so wins are attributable

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions