Guard madvise ENOMEM and stabilize pool/tiny front v3

This commit is contained in:
Moe Charm (CI)
2025-12-09 21:50:15 +09:00
parent e274d5f6a9
commit a905e0ffdd
45 changed files with 3154 additions and 242 deletions

View File

@ -40,6 +40,8 @@
#include "../box/tiny_c7_hotbox.h" // Optional: C7 専用ホットボックス
#include "../box/tiny_heap_box.h" // TinyHeap 汎用 Box
#include "../box/tiny_hotheap_v2_box.h" // TinyHotHeap v2 (Phase31 A/B)
#include "../box/smallobject_hotbox_v3_box.h" // SmallObject HotHeap v3 skeleton
#include "../box/tiny_front_v3_env_box.h" // Tiny front v3 snapshot gate
#include "../box/tiny_heap_env_box.h" // ENV gate for TinyHeap front (A/B)
#include "../box/tiny_route_env_box.h" // Route snapshot (Heap vs Legacy)
#include "../box/tiny_front_stats_box.h" // Front class distribution counters
@ -102,24 +104,58 @@ static inline int front_gate_unified_enabled(void) {
//
__attribute__((always_inline))
static inline void* malloc_tiny_fast(size_t size) {
// size → class_idx を 1 回だけ決定
int class_idx = hak_tiny_size_to_class(size);
if (__builtin_expect(class_idx < 0 || class_idx >= TINY_NUM_CLASSES, 0)) {
return NULL;
const int front_v3_on = tiny_front_v3_enabled();
const TinyFrontV3Snapshot* front_snap =
__builtin_expect(front_v3_on, 0) ? tiny_front_v3_snapshot_get() : NULL;
const bool route_fast_on = front_v3_on && tiny_front_v3_lut_enabled() &&
tiny_front_v3_route_fast_enabled();
int class_idx = -1;
tiny_route_kind_t route = TINY_ROUTE_LEGACY;
bool route_trusted = false;
if (front_v3_on && tiny_front_v3_lut_enabled()) {
const TinyFrontV3SizeClassEntry* e = tiny_front_v3_lut_lookup(size);
if (e && e->class_idx != TINY_FRONT_V3_INVALID_CLASS) {
class_idx = (int)e->class_idx;
route = (tiny_route_kind_t)e->route_kind;
route_trusted = route_fast_on;
}
}
if (__builtin_expect(class_idx < 0 || class_idx >= TINY_NUM_CLASSES, 0)) {
class_idx = hak_tiny_size_to_class(size);
if (__builtin_expect(class_idx < 0 || class_idx >= TINY_NUM_CLASSES, 0)) {
return NULL;
}
route = tiny_route_for_class((uint8_t)class_idx);
route_trusted = false;
} else if (!route_trusted &&
route != TINY_ROUTE_LEGACY && route != TINY_ROUTE_HEAP &&
route != TINY_ROUTE_HOTHEAP_V2 && route != TINY_ROUTE_SMALL_HEAP_V3) {
route = tiny_route_for_class((uint8_t)class_idx);
}
tiny_front_alloc_stat_inc(class_idx);
tiny_route_kind_t route = tiny_route_for_class((uint8_t)class_idx);
switch (route) {
case TINY_ROUTE_HOTHEAP_V2: {
if (class_idx == 7) {
void* v2p = tiny_hotheap_v2_alloc(7);
if (TINY_HOT_LIKELY(v2p != NULL)) {
return v2p;
}
tiny_hotheap_v2_record_route_fallback();
case TINY_ROUTE_SMALL_HEAP_V3: {
void* v3p = so_alloc((uint32_t)class_idx);
if (TINY_HOT_LIKELY(v3p != NULL)) {
return v3p;
}
so_v3_record_alloc_fallback((uint8_t)class_idx);
// fallthrough to v2/v1
__attribute__((fallthrough));
}
case TINY_ROUTE_HOTHEAP_V2: {
void* v2p = tiny_hotheap_v2_alloc((uint8_t)class_idx);
if (TINY_HOT_LIKELY(v2p != NULL)) {
return v2p;
}
tiny_hotheap_v2_record_route_fallback((uint8_t)class_idx);
// fallthrough to TinyHeap v1
__attribute__((fallthrough));
}
case TINY_ROUTE_HEAP: {
void* heap_ptr = NULL;
@ -139,7 +175,10 @@ static inline void* malloc_tiny_fast(size_t size) {
}
// Legacy Tiny front
void* ptr = tiny_hot_alloc_fast(class_idx);
void* ptr = NULL;
if (!front_snap || front_snap->unified_cache_on) {
ptr = tiny_hot_alloc_fast(class_idx);
}
if (TINY_HOT_LIKELY(ptr != NULL)) {
return ptr;
}
@ -192,6 +231,8 @@ static inline int free_tiny_fast(void* ptr) {
tiny_front_free_stat_inc(class_idx);
tiny_route_kind_t route = tiny_route_for_class((uint8_t)class_idx);
const int use_tiny_heap = tiny_route_is_heap_kind(route);
const TinyFrontV3Snapshot* front_snap =
__builtin_expect(tiny_front_v3_enabled(), 0) ? tiny_front_v3_snapshot_get() : NULL;
// TWO-SPEED: SuperSlab registration check is DEBUG-ONLY to keep HOT PATH fast.
// In Release builds, we trust header magic (0xA0) as sufficient validation.
@ -255,6 +296,9 @@ static inline int free_tiny_fast(void* ptr) {
// Same-thread + TinyHeap route → route-based free
if (__builtin_expect(use_tiny_heap, 0)) {
switch (route) {
case TINY_ROUTE_SMALL_HEAP_V3:
so_free((uint32_t)class_idx, base);
return 1;
case TINY_ROUTE_HOTHEAP_V2:
tiny_hotheap_v2_free((uint8_t)class_idx, base, meta);
return 1;
@ -276,7 +320,9 @@ static inline int free_tiny_fast(void* ptr) {
if (use_tiny_heap) {
// fallback: lookup failed but TinyHeap front is ON → use generic TinyHeap free
if (route == TINY_ROUTE_HOTHEAP_V2) {
tiny_hotheap_v2_record_free_fallback();
tiny_hotheap_v2_record_free_fallback((uint8_t)class_idx);
} else if (route == TINY_ROUTE_SMALL_HEAP_V3) {
so_v3_record_free_fallback((uint8_t)class_idx);
}
tiny_heap_free_class_fast(tiny_heap_ctx_for_thread(), class_idx, ptr);
return 1;
@ -300,7 +346,10 @@ static inline int free_tiny_fast(void* ptr) {
}
#endif
int pushed = unified_cache_push(class_idx, HAK_BASE_FROM_RAW(base));
int pushed = 0;
if (!front_snap || front_snap->unified_cache_on) {
pushed = unified_cache_push(class_idx, HAK_BASE_FROM_RAW(base));
}
if (__builtin_expect(pushed, 1)) {
return 1; // Success
}