Add v4 C7/C6 fast classify and small-segment v4 scaffolding

This commit is contained in:
Moe Charm (CI)
2025-12-10 19:14:38 +09:00
parent 3261025995
commit f2ce7256cd
11 changed files with 221 additions and 17 deletions

View File

@ -1,6 +1,6 @@
// smallobject_hotbox_v4.c - SmallObject HotHeap v4 (C7-only real path)
// smallobject_hotbox_v4.c - SmallObject HotHeap v4 (C5/C6/C7 opt-in)
//
// Phase v4-3: C7 クラスについては v4 独自の freelist/current/partial で完結させる
// Phase v4-3.1: C7 は v4 独自の freelist/current/partial で完結。C6/C5 は強ゲート付きで同形パスを使う
#include <stdlib.h>
#include <string.h>
@ -17,8 +17,6 @@
// TLS context
static __thread small_heap_ctx_v4 g_ctx_v4;
#define V4_MAX_PARTIAL_PAGES 1
small_heap_ctx_v4* small_heap_ctx_v4_get(void) {
return &g_ctx_v4;
}
@ -27,6 +25,10 @@ small_heap_ctx_v4* small_heap_ctx_v4_get(void) {
// helpers
// -----------------------------------------------------------------------------
static inline int v4_class_supported(int class_idx) {
return class_idx == 7 || class_idx == 6 || class_idx == 5;
}
static inline void v4_page_push_partial(small_class_heap_v4* h, small_page_v4* page) {
if (!h || !page) return;
page->next = h->partial_head;
@ -53,6 +55,11 @@ static inline void v4_page_push_full(small_class_heap_v4* h, small_page_v4* page
h->full_head = page;
}
static inline uint32_t v4_partial_limit(int class_idx) {
// C7 は refill/retire を抑えるため少し広めに保持
return (class_idx == 7) ? 2u : 1u;
}
static inline int v4_ptr_in_page(const small_page_v4* page, const uint8_t* ptr) {
if (!page || !ptr) return 0;
uint8_t* base = page->base;
@ -97,16 +104,32 @@ static small_page_v4* v4_find_page(small_class_heap_v4* h, const uint8_t* ptr, v
return p;
}
}
// full リストは探さないv4 C7 は partial/current だけで完結する想定)
for (small_page_v4* p = h->full_head; p; prev = p, p = p->next) {
if (v4_ptr_in_page(p, ptr)) {
if (loc) *loc = V4_LOC_FULL;
if (prev_out) *prev_out = prev;
return p;
}
}
return NULL;
}
int smallobject_hotbox_v4_can_own(int class_idx, void* ptr) {
if (__builtin_expect(!v4_class_supported(class_idx), 0)) return 0;
if (!small_heap_v4_class_enabled((uint8_t)class_idx)) return 0;
if (!ptr) return 0;
small_heap_ctx_v4* ctx = small_heap_ctx_v4_get();
if (!ctx) return 0;
small_class_heap_v4* h = &ctx->cls[class_idx];
return v4_find_page(h, (const uint8_t*)ptr, NULL, NULL) != NULL;
}
// -----------------------------------------------------------------------------
// Cold iface (C7-only, Tiny v1 経由)
// Cold iface (C5/C6/C7, Tiny v1 経由)
// -----------------------------------------------------------------------------
static small_page_v4* cold_refill_page_v4(small_heap_ctx_v4* hot_ctx, uint32_t class_idx) {
if (__builtin_expect(class_idx != 7 && class_idx != 6, 0)) return NULL;
if (__builtin_expect(!v4_class_supported((int)class_idx), 0)) return NULL;
(void)hot_ctx;
tiny_heap_ctx_t* tctx = tiny_heap_ctx_for_thread();
if (!tctx) return NULL;
@ -163,13 +186,14 @@ const SmallColdIfaceV4* small_cold_iface_v4_get(void) {
static small_page_v4* small_alloc_slow_v4(small_heap_ctx_v4* ctx, int class_idx) {
small_class_heap_v4* h = &ctx->cls[class_idx];
const uint32_t partial_limit = v4_partial_limit(class_idx);
small_page_v4* cur = h->current;
if (cur && cur->freelist) {
return cur; // usable current
}
if (cur && !cur->freelist) {
// current をいったん partial/full に退避partial を優先)
if (h->partial_count < V4_MAX_PARTIAL_PAGES) {
if (h->partial_count < partial_limit) {
v4_page_push_partial(h, cur);
} else {
v4_page_push_full(h, cur);
@ -193,8 +217,8 @@ static small_page_v4* small_alloc_slow_v4(small_heap_ctx_v4* ctx, int class_idx)
}
void* small_heap_alloc_fast_v4(small_heap_ctx_v4* ctx, int class_idx) {
if (__builtin_expect(class_idx != 7 && class_idx != 6, 0)) {
return NULL; // C6/C7 専用
if (__builtin_expect(!v4_class_supported(class_idx), 0)) {
return NULL; // C5/C6/C7 以外は未対応
}
if (!small_heap_v4_class_enabled((uint8_t)class_idx)) return NULL;
small_class_heap_v4* h = &ctx->cls[class_idx];
@ -240,7 +264,7 @@ static void v4_unlink_from_list(small_class_heap_v4* h, v4_loc_t loc, small_page
}
void small_heap_free_fast_v4(small_heap_ctx_v4* ctx, int class_idx, void* ptr) {
if (__builtin_expect(class_idx != 7 && class_idx != 6, 0)) {
if (__builtin_expect(!v4_class_supported(class_idx), 0)) {
return;
}
if (!small_heap_v4_class_enabled((uint8_t)class_idx)) return;
@ -252,6 +276,8 @@ void small_heap_free_fast_v4(small_heap_ctx_v4* ctx, int class_idx, void* ptr) {
small_page_v4* page = v4_find_page(h, (const uint8_t*)ptr, &loc, &prev);
if (!page) return;
const uint32_t partial_limit = v4_partial_limit(class_idx);
// freelist push
void* head = page->freelist;
memcpy(ptr, &head, sizeof(void*));
@ -274,7 +300,7 @@ void small_heap_free_fast_v4(small_heap_ctx_v4* ctx, int class_idx, void* ptr) {
page->next = NULL;
return;
}
if (h->partial_count < V4_MAX_PARTIAL_PAGES) {
if (h->partial_count < partial_limit) {
v4_page_push_partial(h, page);
return;
}
@ -296,7 +322,7 @@ void small_heap_free_fast_v4(small_heap_ctx_v4* ctx, int class_idx, void* ptr) {
} else if (loc == V4_LOC_FULL && page->freelist) {
// full → partial に戻すcurrent があっても partial 上限までは復帰)
v4_unlink_from_list(h, loc, prev, page);
if (h->partial_count < V4_MAX_PARTIAL_PAGES) {
if (h->partial_count < partial_limit) {
v4_page_push_partial(h, page);
} else {
v4_page_push_full(h, page); // 上限超なら戻す