Fix: workset=8192 SEGV - Align slab_index_for to Box3 geometry (iteration 2)

Problem:
After Box3 geometry unification (commit 2fe970252), workset=8192 still SEGVs:
- 200K iterations:  OK
- 300K iterations:  SEGV

Root Cause (identified by ChatGPT):
Header/metadata class mismatches around 300K iterations:
- [HDR_META_MISMATCH] hdr_cls=6 meta_cls=5
- [FREE_FAST_HDR_META_MISMATCH] hdr_cls=5 meta_cls=4
- [TLS_SLL_PUSH_META_MISMATCH] cls=5 meta_cls=4

Cause: slab_index_for() geometry mismatch with Box3
- tiny_slab_base_for_geometry() (Box3):
    - Slab 0: ss + SUPERSLAB_SLAB0_DATA_OFFSET
    - Slab 1: ss + 1*SLAB_SIZE
    - Slab k: ss + k*SLAB_SIZE

- Old slab_index_for():
    rel = p - (base + SUPERSLAB_SLAB0_DATA_OFFSET);
    idx = rel / SLAB_SIZE;

- Result: Off-by-one for slab_idx > 0
    Example: tiny_slab_base_for_geometry(ss, 4) returns 0x...40000
             slab_index_for(ss, 0x...40000) returns 3 (wrong!)

Impact:
- Block allocated in "C6 slab 4" appears to be in "C5 slab 3"
- Header class_idx (C6) != meta->class_idx (C5)
- TLS SLL corruption → SEGV after extended runs

Fix: core/superslab/superslab_inline.h
======================================
Rewrite slab_index_for() as inverse of Box3 geometry:

  static inline int slab_index_for(SuperSlab* ss, void* ptr) {
      // ... bounds checks ...

      // Slab 0: special case (has metadata offset)
      if (p < base + SLAB_SIZE) {
          return 0;
      }

      // Slab 1+: simple SLAB_SIZE spacing from base
      size_t rel = p - base;  // ← Changed from (p - base - OFFSET)
      int idx = (int)(rel / SLAB_SIZE);
      return idx;
  }

Verification:
- slab_index_for(ss, tiny_slab_base_for_geometry(ss, idx)) == idx 
- Consistent for any address within slab

Test Results:
=============
workset=8192 SEGV threshold improved further:

Before this fix (after 2fe970252):
   200K iterations: OK
   300K iterations: SEGV

After this fix:
   220K iterations: OK (15.5M ops/s)
   240K iterations: SEGV (different bug)

Progress:
- Iteration 1 (2fe970252): 0 → 200K stable
- Iteration 2 (this fix):  200K → 220K stable
- Total improvement: ∞ → 220K iterations (+10% stability)

Known Issues:
- 240K+ still SEGVs (suspected: TLS SLL double-free, per ChatGPT)
- Debug builds may show TLS_SLL_PUSH FATAL double-free detection
- Requires further investigation of free path

Impact:
- No performance regression in stable range
- Header/metadata mismatch errors eliminated
- workset=256 unaffected: 60M+ ops/s maintained

Credit: Root cause analysis and fix by ChatGPT

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm (CI)
2025-11-22 07:56:06 +09:00
parent 2fe970252a
commit 6ae0db9fd2

View File

@ -30,19 +30,33 @@ static inline uint8_t* tiny_slab_base_for(SuperSlab* ss, int slab_idx)
}
// Compute slab index for a pointer inside ss.
// Box 5 wrapper: inverse of Box 3 geometry (tiny_slab_base_for_geometry).
// Layout (data regions):
// - Slab 0: [ss + SUPERSLAB_SLAB0_DATA_OFFSET, ss + SLAB_SIZE)
// - Slab 1: [ss + 1*SLAB_SIZE, ss + 2*SLAB_SIZE)
// - Slab k: [ss + k*SLAB_SIZE, ss + (k+1)*SLAB_SIZE)
static inline int slab_index_for(SuperSlab* ss, void* ptr)
{
if (!ss || !ptr) return -1;
if (!ss || !ptr) {
return -1;
}
uintptr_t base = (uintptr_t)ss;
uintptr_t p = (uintptr_t)ptr;
size_t ss_size = (size_t)1 << ss->lg_size;
// Outside overall SuperSlab range
if (p < base + SUPERSLAB_SLAB0_DATA_OFFSET || p >= base + ss_size) {
return -1;
}
size_t rel = p - (base + SUPERSLAB_SLAB0_DATA_OFFSET);
// Slab 0: from first data byte up to the end of first slab
if (p < base + SLAB_SIZE) {
return 0;
}
// Slabs 1+ use simple SLAB_SIZE spacing from SuperSlab base
size_t rel = p - base;
int idx = (int)(rel / SLAB_SIZE);
if (idx < 0 || idx >= SLABS_PER_SUPERSLAB_MAX) {
return -1;