Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/honest-external-buffer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
External buffer wrappers carry their native byte pointer and Node-API finalizer in the GC buffer cell. Remove the legacy external-buffer registration API and address tables, retain byte-address identity, release native resources after collection or environment shutdown, and reject native-backed wrappers and views by name at worker transfer.
1 change: 0 additions & 1 deletion crates/perry-codegen/src/gc_effects/linux-x86_64.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,6 @@ js_buffer_read_uint32_le Reenters
js_buffer_read_uint8 Reenters
js_buffer_read_uint_be Reenters
js_buffer_read_uint_le Reenters
js_buffer_register_external Leaf
js_buffer_resolve_object_url Leaf
js_buffer_set Leaf
js_buffer_set_from Reenters
Expand Down
1 change: 0 additions & 1 deletion crates/perry-codegen/src/gc_effects/macos-aarch64.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,6 @@ js_buffer_read_uint32_le Reenters
js_buffer_read_uint8 Reenters
js_buffer_read_uint_be Reenters
js_buffer_read_uint_le Reenters
js_buffer_register_external Leaf
js_buffer_resolve_object_url Leaf
js_buffer_set Leaf
js_buffer_set_from Reenters
Expand Down
1 change: 0 additions & 1 deletion crates/perry-codegen/src/gc_effects/windows-x86_64.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,6 @@ js_buffer_read_uint32_le Reenters
js_buffer_read_uint8 Reenters
js_buffer_read_uint_be Reenters
js_buffer_read_uint_le Reenters
js_buffer_register_external Leaf
js_buffer_resolve_object_url Leaf
js_buffer_set Leaf
js_buffer_set_from Reenters
Expand Down
1 change: 0 additions & 1 deletion crates/perry-codegen/src/wasm32/runtime_abi.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,6 @@ js_buffer_read_uint32_le f64 f64,i32s
js_buffer_read_uint8 f64 f64,i32s
js_buffer_read_uint_be f64 f64,i32s,i32s
js_buffer_read_uint_le f64 f64,i32s,i32s
js_buffer_register_external void usize
js_buffer_resolve_object_url f64 f64
js_buffer_set void ptr,i32s,i32s
js_buffer_set_from void ptr,ptr,i32s
Expand Down
4 changes: 4 additions & 0 deletions crates/perry-runtime/src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ pub fn retire_agent(id: AgentId) {
id, PRIMARY_AGENT,
"the primary agent outlives the process; it is never retired"
);
// Finish native-addon ownership while this agent's heap and loop are
// still live. TLS destruction cannot safely call back into the runtime.
#[cfg(feature = "node-api-host")]
crate::node_api_host::shutdown_current_env();
// turnloop P9: this agent may own a `turnloop::Loop`. Tear it down FIRST,
// while the arena is still mapped and this thread can still run the
// bindings' completion sinks.
Expand Down
15 changes: 3 additions & 12 deletions crates/perry-runtime/src/array/buffer_receiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,9 @@ pub(crate) fn buffer_receiver_dispatch(
// arena-backed `GC_TYPE_ARRAY` cannot be a registered Buffer, so an
// ordinary `[1,2,3].map(…)` reaches NEITHER registry.
//
// `arena_payload_has_gc_type` rather than a bare header-byte read (or an
// open-coded address floor): a Buffer comes in BOTH backings, and an
// EXTERNAL one — `EXTERNAL_BUFFER_REGISTRY`, `shared_sab::alloc_shared_sab`
// — has no `GcHeader` at all. The eight bytes below its payload are
// allocator bookkeeping and can read as any `obj_type`, `GC_TYPE_ARRAY`
// included. A bare tag read would therefore skip the probe for exactly the
// receiver this function exists to catch, silently and only sometimes.
// The predicate range-checks, rejects `HeapSpace::Unknown` for the HEADER
// address, and validates through `gc_type_info` before trusting the byte;
// it answers `false` for an external buffer, which falls through to the
// registry — the authoritative answer. See `array/header.rs`'s
// `array_receiver_gc_tag` doc (#8142).
// Prove ownership before trusting the tag. Process-global SABs have a
// real header but live outside this thread's arena; they still need the
// buffer classification below rather than an arena-only rejection.
if unsafe { crate::typedarray::arena_payload_has_gc_type(addr, crate::gc::GC_TYPE_ARRAY) } {
return None;
}
Expand Down
8 changes: 3 additions & 5 deletions crates/perry-runtime/src/array/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,9 @@ pub(crate) unsafe fn array_object_flags_resolved(arr: *const ArrayHeader) -> u16
/// These carry a genuine `GcHeader` with a correct `obj_type`; they are
/// pinned rather than movable, which is a different property from being
/// untracked. This is the population #8041 started nulling.
/// * **external** — `EXTERNAL_BUFFER_REGISTRY` /
/// `EXTERNAL_UINT8ARRAY_REGISTRY` addresses, plus
/// `shared_sab::alloc_shared_sab`'s `alloc_zeroed`. For these the eight
/// bytes below the payload really are allocator bookkeeping and can read
/// as any value.
/// * **process-global** — `shared_sab::alloc_shared_sab` owns a real header
/// outside the current thread's GC heap. Registration alone does not prove
/// membership in that heap.
///
/// So the tag is authoritative only once the address is known to be
/// arena-backed. `typedarray::arena_payload_has_gc_type` is the predicate
Expand Down
Loading
Loading