// 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 #include #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)); }