Files
hakmem/core/region_id_v6.c
Moe Charm (CI) 39a3c53dbc Phase v7-2: SmallObject v7 C6-only implementation with RegionIdBox integration
- SmallSegment_v7: 2MiB segment with TLS slot and free page stack
- ColdIface_v7: Page refill/retire between HotBox and SegmentBox
- HotBox_v7: Full C6-only alloc/free with header writing (HEADER_MAGIC|class_idx)
- Free path early-exit: Check v7 route BEFORE ss_fast_lookup (separate mmap segment)
- RegionIdBox: Register v7 segment for ptr->region lookup
- Benchmark: v7 ON ~54.5M ops/s (-7% overhead vs 58.6M legacy baseline)

v7 correctly balances alloc/free counts and page lifecycle.
RegionIdBox overhead identified as primary cost driver.

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

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-12 03:12:28 +09:00

430 lines
15 KiB
C

// region_id_v6.c - RegionIdBox implementation for V6-HDR-1
//
// Purpose: Centralized ptr -> region lookup for headerless design
// Phase V6-HDR-1: OBSERVE only (no behavior change)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "box/region_id_v6_box.h"
#include "box/smallsegment_v6_box.h"
#ifndef likely
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#endif
// ============================================================================
// ENV Control
// ============================================================================
#define REGION_OBSERVE_UNINIT (-1)
#define REGION_OBSERVE_OFF 0
#define REGION_OBSERVE_ON 1
static int g_region_observe = REGION_OBSERVE_UNINIT;
bool region_id_observe_enabled(void) {
if (unlikely(g_region_observe == REGION_OBSERVE_UNINIT)) {
const char* env = getenv("HAKMEM_REGION_ID_V6_OBSERVE");
g_region_observe = (env && env[0] == '1') ? REGION_OBSERVE_ON : REGION_OBSERVE_OFF;
}
return g_region_observe == REGION_OBSERVE_ON;
}
// ============================================================================
// TLS Cache + Segment Registration (Phase V6-HDR-3)
// ============================================================================
static __thread RegionIdTlsCache g_region_tls_cache;
static __thread int g_region_tls_cache_init = 0;
// TLS segment info (registered on first access)
static __thread uintptr_t g_v6_segment_base = 0;
static __thread uintptr_t g_v6_segment_end = 0;
static __thread SmallSegmentV6* g_v6_segment = NULL;
static __thread int g_v6_segment_registered = 0;
RegionIdTlsCache* region_id_tls_cache_get(void) {
if (unlikely(!g_region_tls_cache_init)) {
memset(&g_region_tls_cache, 0, sizeof(g_region_tls_cache));
g_region_tls_cache_init = 1;
}
return &g_region_tls_cache;
}
/// Register this thread's v6 segment (Phase V6-HDR-3)
/// Called from small_heap_ctx_v6() when segment is first acquired
void region_id_register_v6_segment(SmallSegmentV6* seg) {
if (!seg || g_v6_segment_registered) {
return; // Already registered or invalid
}
g_v6_segment_base = seg->base;
g_v6_segment_end = seg->base + SMALL_SEGMENT_V6_SIZE;
g_v6_segment = seg;
g_v6_segment_registered = 1;
}
// ============================================================================
// Global RegionIdBox (V6-HDR-2: Full implementation)
// ============================================================================
// Maximum number of registered regions
#define REGION_MAX_ENTRIES 256
// RegionEntry: Single registered region
typedef struct RegionEntry {
uintptr_t base; // Region base address
uintptr_t end; // Region end address (exclusive)
region_kind_t kind; // Region type
void* metadata; // Kind-specific metadata (e.g., page_meta)
uint32_t id; // Unique region ID
uint8_t active; // 1 = active, 0 = free slot
uint8_t reserved[3]; // Padding
} RegionEntry;
// RegionIdBox: Region registry
struct RegionIdBox {
uint32_t next_id; // Next available ID
uint32_t count; // Number of active entries
RegionEntry entries[REGION_MAX_ENTRIES]; // Sorted by base address
// Note: entries are kept sorted by base for binary search lookup
};
static struct RegionIdBox g_region_id_box = {
.next_id = 2, // Start from 2 (1 is reserved for TLS segment)
.count = 0
};
RegionIdBox* region_id_box_get(void) {
return &g_region_id_box;
}
// Binary search helper: find entry containing address
static RegionEntry* region_entry_find(uintptr_t addr) {
RegionIdBox* box = &g_region_id_box;
if (box->count == 0) return NULL;
// Binary search for entry where base <= addr < end
uint32_t lo = 0, hi = box->count;
while (lo < hi) {
uint32_t mid = lo + (hi - lo) / 2;
RegionEntry* e = &box->entries[mid];
if (!e->active) {
// Skip inactive entries (shouldn't happen in sorted array)
lo = mid + 1;
continue;
}
if (addr < e->base) {
hi = mid;
} else if (addr >= e->end) {
lo = mid + 1;
} else {
// addr is in range [base, end)
return e;
}
}
return NULL;
}
// Insert entry maintaining sorted order
static int region_entry_insert(RegionEntry* entry) {
RegionIdBox* box = &g_region_id_box;
if (box->count >= REGION_MAX_ENTRIES) {
return -1; // Registry full
}
// Find insertion point (binary search)
uint32_t pos = 0;
for (uint32_t i = 0; i < box->count; i++) {
if (box->entries[i].base > entry->base) {
pos = i;
break;
}
pos = i + 1;
}
// Shift entries to make room
for (uint32_t i = box->count; i > pos; i--) {
box->entries[i] = box->entries[i - 1];
}
// Insert new entry
box->entries[pos] = *entry;
box->count++;
return 0;
}
// Remove entry by ID
static int region_entry_remove(uint32_t id) {
RegionIdBox* box = &g_region_id_box;
for (uint32_t i = 0; i < box->count; i++) {
if (box->entries[i].id == id && box->entries[i].active) {
// Shift entries to fill gap
for (uint32_t j = i; j < box->count - 1; j++) {
box->entries[j] = box->entries[j + 1];
}
box->count--;
return 0;
}
}
return -1; // Not found
}
// ============================================================================
// Lookup Implementation (V6-HDR-2: TLS + Registry)
// ============================================================================
// Forward declaration from smallsegment_v6.c
extern SmallPageMetaV6* small_page_meta_v6_of(void* ptr);
RegionLookupV6 region_id_lookup_v6(void* ptr) {
RegionLookupV6 result = {
.kind = REGION_KIND_UNKNOWN,
.region_id = 0,
.page_meta = NULL
};
if (unlikely(!ptr)) {
return result;
}
uintptr_t addr = (uintptr_t)ptr;
// Phase V6-HDR-4 P0: Direct page_meta calculation (Double validation 排除)
// TLS segment が登録済みかつ範囲内なら、small_page_meta_v6_of() を呼ばずに
// 直接 page_meta を計算する。これにより:
// - slot->in_use チェックの重複を排除
// - small_ptr_in_segment_v6() の重複を排除
// - 関数呼び出しオーバーヘッドを削減
if (g_v6_segment_registered && addr >= g_v6_segment_base && addr < g_v6_segment_end) {
// Calculate page_idx directly using TLS cached base
size_t page_idx = (addr - g_v6_segment_base) >> SMALL_PAGE_V6_SHIFT;
// Bounds check (should always pass if segment is valid)
if (likely(page_idx < SMALL_PAGES_PER_SEGMENT)) {
SmallPageMetaV6* page = &g_v6_segment->page_meta[page_idx];
// Minimal validation: only check capacity (page is in use)
if (likely(page->capacity > 0)) {
result.kind = REGION_KIND_SMALL_V6;
result.region_id = 1;
result.page_meta = page;
// Phase V6-HDR-4 P1: Update TLS cache with page-level info
RegionIdTlsCache* cache = region_id_tls_cache_get();
cache->last_base = g_v6_segment_base;
cache->last_end = g_v6_segment_end;
// Page-level cache: same-page ptr は page_meta lookup をスキップ可能
uintptr_t page_base = g_v6_segment_base + (page_idx << SMALL_PAGE_V6_SHIFT);
cache->last_page_base = page_base;
cache->last_page_end = page_base + SMALL_PAGE_V6_SIZE;
cache->last_page = page;
cache->last_result = result;
}
}
return result;
}
// V6-HDR-2: Check registered regions (binary search)
RegionEntry* entry = region_entry_find(addr);
if (entry) {
result.kind = entry->kind;
result.region_id = entry->id;
result.page_meta = entry->metadata;
// Update TLS cache for segment-level caching
RegionIdTlsCache* cache = region_id_tls_cache_get();
cache->last_base = entry->base;
cache->last_end = entry->end;
cache->last_result = result;
// Note: page-level cache not applicable for arbitrary registered regions
return result;
}
// Legacy fallback (if TLS not registered yet)
SmallPageMetaV6* page = small_page_meta_v6_of(ptr);
if (page != NULL) {
result.kind = REGION_KIND_SMALL_V6;
result.region_id = 1;
result.page_meta = page;
RegionIdTlsCache* cache = region_id_tls_cache_get();
SmallSegmentV6* seg = (SmallSegmentV6*)page->segment;
if (seg) {
cache->last_base = seg->base;
cache->last_end = seg->base + SMALL_SEGMENT_V6_SIZE;
cache->last_result = result;
}
}
return result;
}
RegionLookupV6 region_id_lookup_cached_v6(void* ptr) {
RegionIdTlsCache* cache = region_id_tls_cache_get();
uintptr_t addr = (uintptr_t)ptr;
// Phase V6-HDR-4 P1: Same-page hit optimization
// 同一ページ内なら page_meta lookup を完全にスキップ
if (addr >= cache->last_page_base && addr < cache->last_page_end &&
cache->last_page != NULL && cache->last_page->capacity > 0) {
// Same page hit - return cached page_meta directly
RegionLookupV6 result = cache->last_result;
result.page_meta = cache->last_page;
return result;
}
// Segment hit but different page - need to recalculate page_meta
if (addr >= cache->last_base && addr < cache->last_end &&
cache->last_result.kind != REGION_KIND_UNKNOWN) {
// Calculate new page_idx
size_t page_idx = (addr - cache->last_base) >> SMALL_PAGE_V6_SHIFT;
if (likely(page_idx < SMALL_PAGES_PER_SEGMENT && g_v6_segment != NULL)) {
SmallPageMetaV6* page = &g_v6_segment->page_meta[page_idx];
if (likely(page->capacity > 0)) {
RegionLookupV6 result = cache->last_result;
result.page_meta = page;
// Update page-level cache
uintptr_t page_base = cache->last_base + (page_idx << SMALL_PAGE_V6_SHIFT);
cache->last_page_base = page_base;
cache->last_page_end = page_base + SMALL_PAGE_V6_SIZE;
cache->last_page = page;
return result;
}
}
}
// Cache miss -> slow path
return region_id_lookup_v6(ptr);
}
// ============================================================================
// Registration API (V6-HDR-2: Full implementation)
// ============================================================================
uint32_t region_id_register_v6(void* base, size_t size, region_kind_t kind, void* metadata) {
if (!base || size == 0) {
return 0; // Invalid arguments
}
RegionIdBox* box = &g_region_id_box;
// Create new entry
RegionEntry entry = {
.base = (uintptr_t)base,
.end = (uintptr_t)base + size,
.kind = kind,
.metadata = metadata,
.id = box->next_id,
.active = 1
};
// Insert into registry
if (region_entry_insert(&entry) != 0) {
return 0; // Registry full
}
uint32_t id = box->next_id++;
// OBSERVE mode logging
region_id_observe_register(base, size, kind, id);
return id;
}
void region_id_unregister_v6(uint32_t region_id) {
if (region_id == 0 || region_id == 1) {
return; // Invalid or reserved ID
}
// OBSERVE mode logging
region_id_observe_unregister(region_id);
region_entry_remove(region_id);
}
bool region_id_is_valid_v6(uint32_t region_id) {
if (region_id == 0) return false;
if (region_id == 1) return true; // Reserved for TLS segment
RegionIdBox* box = &g_region_id_box;
for (uint32_t i = 0; i < box->count; i++) {
if (box->entries[i].id == region_id && box->entries[i].active) {
return true;
}
}
return false;
}
// ============================================================================
// Utility API
// ============================================================================
const char* region_kind_to_string(region_kind_t kind) {
switch (kind) {
case REGION_KIND_UNKNOWN: return "UNKNOWN";
case REGION_KIND_SMALL_V6: return "SMALL_V6";
case REGION_KIND_C7_ULTRA: return "C7_ULTRA";
case REGION_KIND_POOL_V1: return "POOL_V1";
case REGION_KIND_LARGE: return "LARGE";
case REGION_KIND_TINY_LEGACY: return "TINY_LEGACY";
case REGION_KIND_MID_V3: return "MID_V3";
case REGION_KIND_SMALL_V7: return "SMALL_V7";
default: return "INVALID";
}
}
void region_id_box_dump(void) {
fprintf(stderr, "[REGION_ID_BOX] V6-HDR-2: TLS segment + Registry\n");
fprintf(stderr, "[REGION_ID_BOX] observe=%d\n", region_id_observe_enabled());
RegionIdBox* box = &g_region_id_box;
fprintf(stderr, "[REGION_ID_BOX] next_id=%u count=%u\n", box->next_id, box->count);
// Dump TLS segment info
if (g_v6_segment_registered) {
fprintf(stderr, "[REGION_ID_BOX] TLS segment: base=%p end=%p (reserved id=1)\n",
(void*)g_v6_segment_base, (void*)g_v6_segment_end);
}
// Dump registered regions
for (uint32_t i = 0; i < box->count; i++) {
RegionEntry* e = &box->entries[i];
if (e->active) {
fprintf(stderr, "[REGION_ID_BOX] [%u] id=%u kind=%s base=%p end=%p meta=%p\n",
i, e->id, region_kind_to_string(e->kind),
(void*)e->base, (void*)e->end, e->metadata);
}
}
}
// ============================================================================
// OBSERVE Mode Logging
// ============================================================================
void region_id_observe_lookup(void* ptr, const RegionLookupV6* result) {
if (region_id_observe_enabled()) {
fprintf(stderr, "[REGION_ID] lookup ptr=%p kind=%s region_id=%u page_meta=%p\n",
ptr, region_kind_to_string(result->kind),
result->region_id, result->page_meta);
}
}
void region_id_observe_register(void* base, size_t size, region_kind_t kind, uint32_t id) {
if (region_id_observe_enabled()) {
fprintf(stderr, "[REGION_ID] register base=%p size=%zu kind=%s id=%u\n",
base, size, region_kind_to_string(kind), id);
}
}
void region_id_observe_unregister(uint32_t id) {
if (region_id_observe_enabled()) {
fprintf(stderr, "[REGION_ID] unregister id=%u\n", id);
}
}