Skip to content

#67: bulk copies for the remaining flat list element types - #80

Merged
lann merged 1 commit into
mainfrom
bulk-flat-lists-67
Aug 11, 2026
Merged

#67: bulk copies for the remaining flat list element types#80
lann merged 1 commit into
mainfrom
bulk-flat-lists-67

Conversation

@lann

@lann lann commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Closes #67. Companion PR: the #68 bench lanes (separate, bench-only).

Decision (a) from the issue: host shapes are unchanged (number[]/bigint[]/boolean[] — no contract edit); only the copy mechanics change. cabi/bulk_lists.ts adds TypedArray-backed lift/store for bool, s8, u16/s16, u32/s32, u64/s64, f32/f64, with exact per-element semantics parity:

  • integers: same assert texts ("int store", "64-bit store requires bigint"), same assert-before-write order, same wrap-on-overflow (TypedArray coercion ≡ DataView setters);
  • floats: the deterministic profile's NaN canonicalization preserved in both directions (decodeI32AsFloat/encodeFloatAsI32 semantics; canonical bit patterns pinned by test against absolute bytes, including payload-NaN lift→re-store round trips for f32 and f64);
  • bool: truthiness-normalized stores, nonzero-lifts-true.

Endianness is a named assumption (PLATFORM_LITTLE_ENDIAN, one check): on a BE platform the helpers decline and the DataView per-element loops remain as the correct fallback (also exercised by a misaligned-view test). u8 keeps its Uint8Array-shaped path from #63; char stays per-element (USV validation is the cost); compound types fall through.

Checklist deviation, reviewed as sound: "PayloadChunk generalization" is N/A under decision (a) — non-u8 stream chunks stay plain arrays and hit these paths inside GuestBuffer read/write anyway.

Numbers (16 KiB lists, this box): store 15–22 → 1.5–2.9 ns/el (10–14×); lift u32 17 → 1.4, f64 23 → 3.3, u64 23 → 8.7 ns/el (bigint-allocation bound).

Also closes #63 review F3: stream-pass grows take (bounded consumption returning the sum of what it took), driven by a 256 KiB typed offer — the writeAll re-offer rounds against a real guest, data integrity pinned exactly, take count bounded (wit-bindgen buffers reads).

Gates: test-runtime (380), conformance (1254/0 — the values directory exercises every list kind through the new paths), sched-seeds, wasi-shims (50), ct-runner, bundle, translate, examples, ports, webrtc, smoke-tls, websocket-conformance (55/0), smoke-c0 legs 2+4, shells, browsers, build/test-rust. Reviewed against definitions.py (canonicalize_nan32/64, DETERMINISTIC_PROFILE) + float.ts/memory.ts; all advisories addressed in-diff.

list<u8> went bulk in #63; every other flat element type still moved one
interpreted store()/load() per element (~13-45 ns/el of despecialize +
asserts + DataView), and a stream<u32> paid that on every rendezvous.

cabi/bulk_lists.ts: TypedArray-backed lift/store for bool, s8, u16/s16,
u32/s32, u64/s64, f32/f64 — decision (a) from the issue: host shapes are
UNCHANGED (number[]/bigint[]/boolean[]; no contract edit), only the copy
mechanics change. Semantics parity with the per-element path is exact:

* integers keep storeInt's assert texts ("int store", "64-bit store
  requires bigint"), assert-before-write ordering, and wrap-on-overflow
  (TypedArray element coercion == the matching DataView setter);
* floats keep the deterministic profile's NaN canonicalization in BOTH
  directions (float.ts decodeI32AsFloat/encodeFloatAsI32 semantics:
  every lifted NaN is the canonical one, every stored number NaN writes
  the canonical bit pattern; non-NaN values are bit-exact, f32
  narrowing is the same IEEE RTNE);
* bool stores normalize by truthiness and lift nonzero as true, as
  before.

The platform's little-endianness is a NAMED assumption
(PLATFORM_LITTLE_ENDIAN, checked once): wasm memory is LE by spec, JS
TypedArrays are platform-endian; on a BE platform (and for misaligned
test-only views) the helpers decline and the DataView per-element loops
remain as the endianness-correct fallback. u8 keeps its dedicated
Uint8Array-shaped path; char stays per-element (its lift IS per-element
USV validation); compound types fall through unchanged.

Issue-checklist deviation, reviewed: "PayloadChunk generalization" is
N/A under decision (a) — non-u8 stream chunks stay plain arrays and hit
these fast paths inside GuestBuffer read/write anyway.

16 KiB lists, this box: store 15-22 -> 1.5-2.9 ns/el (10-14x); lift
u32 17 -> 1.4 ns/el, f64 23 -> 3.3, u64 23 -> 8.7 (bigint allocation
bound). The conformance values directory (165 cases over every list
kind) passes unchanged through the new paths.

Also closes #63 review F3: stream-pass grows `take` (bounded
consumption, returns the sum of what it took), and a new test drives a
256 KiB typed offer against it — the writeAll re-offer rounds against a
real guest's GuestBuffer, with data integrity pinned exactly and the
take count only bounded (wit-bindgen buffers reads).

Tests: bulk_list_test.ts pins per-type round-trips, wrap parity,
assert-text parity (incl. Infinity/NaN), bigint wrap mod 2^64, f32
narrowing, canonical-NaN bit patterns both directions (f32 + f64
payload NaNs), bool normalization, empty/fixed-length lists, the
misaligned-view fallback, and that the fast path actually engages on LE
platforms. docs/architecture.md §7 records the policy.

Gates: build, test-rust, test-runtime (380), test-wasi-shims (50),
test-ct-runner, test-bundle, test-translate, examples, conformance
(1254/0, no stale xfails), sched-seeds (1, 4242), test-ports,
test-webrtc, shells (sm-pinned; jsc-pinned arch-skipped), browsers
(chromium, firefox), websocket-conformance (55/0), smoke-tls, smoke-c0
legs 2+4. Reviewed against definitions.py (canonicalize_nan32/64,
DETERMINISTIC_PROFILE, store/load discipline) + float.ts/memory.ts;
advisories addressed in-diff (bytesOf defense-in-depth on the bool
paths, extra assert cases, f64 payload-NaN twin, fast-path-engages
smoke).

Closes #67.
@lann
lann enabled auto-merge August 11, 2026 00:57
@lann
lann merged commit c1f879e into main Aug 11, 2026
4 checks passed
@lannbot
lannbot deleted the bulk-flat-lists-67 branch August 23, 2026 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cabi: bulk copies for the remaining flat element types (list<u16|u32|u64|f32|f64|...>, and their streams)

1 participant