Files
hakmem/core/box/tiny_route_env_box.h
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

177 lines
7.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// tiny_route_env_box.h - Route snapshot for Tiny front (Heap vs Legacy)
// 役割:
// - 起動時に「各クラスが TinyHeap を使うか」をスナップショットし、ホットパスでは LUT 1 回に縮約する。
// - HAKMEM_TINY_HEAP_PROFILE / HAKMEM_TINY_HEAP_BOX / HAKMEM_TINY_HEAP_CLASSES の組合せをここで解決する。
#pragma once
#include <stdint.h>
#include <stdlib.h>
#include "../hakmem_tiny_config.h"
#include "tiny_heap_env_box.h"
#include "free_dispatch_stats_box.h" // Phase FREE-DISPATCHER-OPT-1
#include "smallobject_hotbox_v3_env_box.h"
#include "smallobject_hotbox_v4_env_box.h"
#include "smallobject_v5_env_box.h"
// ENV sentinel values
#ifndef ENV_UNINIT
#define ENV_UNINIT (-1)
#define ENV_ENABLED (1)
#define ENV_DISABLED (0)
#endif
typedef enum {
TINY_ROUTE_LEGACY = 0,
TINY_ROUTE_HEAP = 1, // TinyHeap v1
TINY_ROUTE_HOTHEAP_V2 = 2, // TinyHotHeap v2
TINY_ROUTE_SMALL_HEAP_V3 = 3, // SmallObject HotHeap v3 (C7-first,研究箱)
TINY_ROUTE_SMALL_HEAP_V4 = 4, // SmallObject HotHeap v4 (stub, route未使用)
TINY_ROUTE_SMALL_HEAP_V5 = 5, // SmallObject HotHeap v5 (C6-only route stub, Phase v5-1)
TINY_ROUTE_SMALL_HEAP_V6 = 6, // SmallObject Core v6 (C6-only route stub, Phase v6-1)
TINY_ROUTE_SMALL_HEAP_V7 = 7, // SmallObject HotHeap v7 (C6-only route stub, Phase v7-1)
} tiny_route_kind_t;
extern tiny_route_kind_t g_tiny_route_class[TINY_NUM_CLASSES];
extern int g_tiny_route_snapshot_done;
// ============================================================================
// Phase v6-1: SmallObject Core v6 ENV gate (must be before tiny_route_snapshot_init)
// ============================================================================
// small_heap_v6_enabled() - グローバル v6 enable check
static inline int small_heap_v6_enabled(void) {
static int g_enabled = ENV_UNINIT;
if (__builtin_expect(g_enabled == ENV_UNINIT, 0)) {
const char* e = getenv("HAKMEM_SMALL_HEAP_V6_ENABLED");
g_enabled = (e && *e && *e != '0') ? ENV_ENABLED : ENV_DISABLED;
}
return (g_enabled == ENV_ENABLED);
}
// small_heap_v6_class_mask() - v6 対象クラスのビットマスク
static inline uint32_t small_heap_v6_class_mask(void) {
static int g_mask = ENV_UNINIT;
if (__builtin_expect(g_mask == ENV_UNINIT, 0)) {
const char* e = getenv("HAKMEM_SMALL_HEAP_V6_CLASSES");
if (e && *e) {
g_mask = (int)strtoul(e, NULL, 0);
} else {
g_mask = 0x0; // default: OFF
}
}
return (uint32_t)g_mask;
}
// small_heap_v6_class_enabled() - 指定クラスが v6 有効か
static inline int small_heap_v6_class_enabled(uint32_t class_idx) {
if (class_idx >= 8) return 0;
if (!small_heap_v6_enabled()) return 0;
uint32_t mask = small_heap_v6_class_mask();
return (mask & (1u << class_idx)) ? 1 : 0;
}
// ============================================================================
// Phase v7-1: SmallObject HotHeap v7 ENV gate (must be before tiny_route_snapshot_init)
// ============================================================================
// small_heap_v7_enabled() - グローバル v7 enable check
static inline int small_heap_v7_enabled(void) {
static int g_enabled = ENV_UNINIT;
if (__builtin_expect(g_enabled == ENV_UNINIT, 0)) {
const char* e = getenv("HAKMEM_SMALL_HEAP_V7_ENABLED");
g_enabled = (e && *e && *e != '0') ? ENV_ENABLED : ENV_DISABLED;
}
return (g_enabled == ENV_ENABLED);
}
// small_heap_v7_class_mask() - v7 対象クラスのビットマスク
static inline uint32_t small_heap_v7_class_mask(void) {
static int g_mask = ENV_UNINIT;
if (__builtin_expect(g_mask == ENV_UNINIT, 0)) {
const char* e = getenv("HAKMEM_SMALL_HEAP_V7_CLASSES");
if (e && *e) {
g_mask = (int)strtoul(e, NULL, 0);
} else {
g_mask = 0x0; // default: OFF
}
}
return (uint32_t)g_mask;
}
// small_heap_v7_class_enabled() - 指定クラスが v7 有効か
static inline int small_heap_v7_class_enabled(uint32_t class_idx) {
if (class_idx >= 8) return 0;
if (!small_heap_v7_enabled()) return 0;
uint32_t mask = small_heap_v7_class_mask();
return (mask & (1u << class_idx)) ? 1 : 0;
}
static inline void tiny_route_snapshot_init(void) {
for (int i = 0; i < TINY_NUM_CLASSES; i++) {
// Phase v7-1: C6-only v7 route stub (highest priority)
FREE_DISPATCH_STAT_INC(env_checks); // ENV check counter
if (small_heap_v7_class_enabled((uint32_t)i)) {
g_tiny_route_class[i] = TINY_ROUTE_SMALL_HEAP_V7;
FREE_DISPATCH_STAT_INC(route_core_v7);
} else if (small_heap_v6_class_enabled((uint32_t)i)) {
// Phase v6-1: C6-only v6 route stub
FREE_DISPATCH_STAT_INC(env_checks);
g_tiny_route_class[i] = TINY_ROUTE_SMALL_HEAP_V6;
FREE_DISPATCH_STAT_INC(route_core_v6);
} else if (i == 6 && small_heap_v5_class_enabled(6)) {
// Phase v5-1: C6-only v5 route stub (before v4 check)
FREE_DISPATCH_STAT_INC(env_checks);
g_tiny_route_class[i] = TINY_ROUTE_SMALL_HEAP_V5;
} else if (small_heap_v4_class_enabled((uint8_t)i)) {
FREE_DISPATCH_STAT_INC(env_checks);
g_tiny_route_class[i] = TINY_ROUTE_SMALL_HEAP_V4;
} else if (small_heap_v3_class_enabled((uint8_t)i)) {
FREE_DISPATCH_STAT_INC(env_checks);
g_tiny_route_class[i] = TINY_ROUTE_SMALL_HEAP_V3;
} else if (tiny_hotheap_v2_class_enabled((uint8_t)i)) {
FREE_DISPATCH_STAT_INC(env_checks);
g_tiny_route_class[i] = TINY_ROUTE_HOTHEAP_V2;
} else if (tiny_heap_box_enabled() && tiny_heap_class_route_enabled(i)) {
FREE_DISPATCH_STAT_INC(env_checks);
FREE_DISPATCH_STAT_INC(env_checks);
g_tiny_route_class[i] = TINY_ROUTE_HEAP;
} else {
g_tiny_route_class[i] = TINY_ROUTE_LEGACY;
FREE_DISPATCH_STAT_INC(route_tiny_legacy);
}
}
g_tiny_route_snapshot_done = 1;
}
static inline tiny_route_kind_t tiny_route_for_class(uint8_t ci) {
FREE_DISPATCH_STAT_INC(route_for_class_calls); // Phase FREE-DISPATCHER-OPT-1
if (__builtin_expect(!g_tiny_route_snapshot_done, 0)) {
tiny_route_snapshot_init();
}
if (__builtin_expect(ci >= TINY_NUM_CLASSES, 0)) {
return TINY_ROUTE_LEGACY;
}
return g_tiny_route_class[ci];
}
static inline int tiny_route_is_heap_kind(tiny_route_kind_t route) {
return route == TINY_ROUTE_HEAP ||
route == TINY_ROUTE_HOTHEAP_V2 ||
route == TINY_ROUTE_SMALL_HEAP_V3 ||
route == TINY_ROUTE_SMALL_HEAP_V4 ||
route == TINY_ROUTE_SMALL_HEAP_V5 ||
route == TINY_ROUTE_SMALL_HEAP_V6 ||
route == TINY_ROUTE_SMALL_HEAP_V7;
}
// C7 front が TinyHeap を使うかRoute snapshot 経由で判定)
static inline int tiny_c7_front_uses_heap(void) {
return tiny_route_is_heap_kind(tiny_route_for_class(7));
}
// C6 front が TinyHeap を使うかRoute snapshot 経由で判定)
static inline int tiny_c6_front_uses_heap(void) {
return tiny_route_is_heap_kind(tiny_route_for_class(6));
}