Skip to content

Add H1 dealloc hook and record_dealloc machinery (Phase 3.1) - #6

Merged
jayakasadev merged 1 commit into
mainfrom
feature/phase-3-1-h1-dealloc-hook
Jun 11, 2026
Merged

jayakasadev merged 1 commit into
mainfrom
feature/phase-3-1-h1-dealloc-hook

Conversation

@jayakasadev

Copy link
Copy Markdown
Owner

Summary

Phase 3.1 — H1 dealloc hook at the waist (Allocator::dealloc, 100% of public free entry points). Gated by SNMALLOC_PROFILE. Default (OFF) build is byte-identical.

  • snmalloc::profile::record_dealloc<Config>(void*) in src/snmalloc/profile/record.h. Compiles to no-op when Config::ClientMeta is not LazyArrayClientMetaDataProvider<SampledAlloc*> slot type.
  • Split into find_profile_slot (Config-specific pagemap walk) + clear_profile_slot (Config-agnostic atomic-CAS + SampledList::remove + NodePool::release). Second function unit-testable without a real Backend.
  • Hook installed at corealloc.h:1025, fires BEFORE existing dealloc logic so profile cleanup sees live pagemap entry. Re-entrancy-safe via ReentrancyGuard.
  • record.h is intentionally lightweight (forward-declared in corealloc.h, full definition pulled in by backend_helpers.h once LazyArrayClientMetaDataProvider visible) — avoids cycle commonconfig.h → mem/mem.h → corealloc.h → record.h.
  • record_alloc stays a stub; full alloc-side wiring is Phase 3.3.

Test plan

  • 88/88 ctest with SNMALLOC_PROFILE=OFF (default)
  • 88/88 ctest with SNMALLOC_PROFILE=ON
  • func-malloc-fast test binary byte-identical OFF vs ON (216240 bytes)
  • test_clear_null_slot — clear on null is no-op
  • test_clear_populated_slot — published sample → cleared → live count drops, second clear no-op
  • test_double_free_race — 2048 iters × 2 threads, exactly one CAS winner each
  • test_default_config_compiletime_noopstatic_assert(!config_has_profile_slot_v<snmalloc::Config>)
  • test_reentrancy_short_circuit — slot untouched while profile_in_progress=1
  • test_e2e_dealloc_does_not_crash — 1024 mixed-size libc malloc/free pairs through H1

Ticket: 86ahrfww6

- New snmalloc::profile::record_dealloc<Config>(void*) free function in
  src/snmalloc/profile/record.h. Compiles to a no-op for configs whose
  ClientMeta is not LazyArrayClientMetaDataProvider<SampledAlloc-slot>,
  so the default snmalloc::Config sees zero cost.
- record_dealloc body splits into find_profile_slot (Config-specific
  pagemap walk) and clear_profile_slot (Config-agnostic atomic-CAS +
  SampledList::remove + NodePool::release), with the latter callable
  directly from tests.
- H1 hook installed at the dealloc waist in Allocator::dealloc(void*)
  (mem/corealloc.h:1025), gated by SNMALLOC_PROFILE. Fires before any
  existing dealloc logic so profile-side cleanup observes the live
  pagemap, and is itself safe under recursive entry via the per-thread
  ReentrancyGuard.
- record.h is intentionally lightweight; including commonconfig.h there
  would create a cycle (commonconfig -> mem/mem -> corealloc -> record).
  Instead corealloc.h forward-declares the template, and
  backend_helpers/backend_helpers.h pulls the full definition in once
  LazyArrayClientMetaDataProvider is visible.
- record_alloc stays a stub: full alloc-side wiring lands in Phase 3.3.
- New test src/test/func/profile_record/profile_record.cc covers the
  null-slot no-op, populated-slot drain, multi-threaded double-free
  CAS race, default-config compile-time no-op, ReentrancyGuard
  short-circuit and end-to-end libc::malloc/libc::free crash-freedom.
- Default (OFF) build remains byte-identical to pre-Phase-3.1: the H1
  call site is behind #ifdef SNMALLOC_PROFILE, and SNMALLOC_PROFILE=ON
  with the default NoClientMetaDataProvider Config inlines the
  if-constexpr branch into nothing (verified: same binary size for the
  default-config test executable in OFF vs ON builds).
- All existing tests pass under both -DSNMALLOC_PROFILE=OFF (88/88) and
  -DSNMALLOC_PROFILE=ON (88/88), -fast and -check variants.
@jayakasadev
jayakasadev merged commit fd8c3b2 into main Jun 11, 2026
166 of 202 checks passed
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.

1 participant