From e41b1af644c771856ecce4d1adbdfeb9337582dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sun, 14 Jun 2026 15:09:13 +0200 Subject: [PATCH] zend_types: Convert `HT_*()` macros to inline functions --- Zend/zend_types.h | 190 ++++++++++++++++++++++++++-------------------- 1 file changed, 108 insertions(+), 82 deletions(-) diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 0edc4df37484..4021fbcecfbd 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -446,20 +446,31 @@ struct _zend_array { */ #if SIZEOF_SIZE_T == 4 # define HT_MAX_SIZE 0x02000000 -# define HT_HASH_TO_BUCKET_EX(data, idx) \ - ((Bucket*)((char*)(data) + (idx))) -# define HT_IDX_TO_HASH(idx) \ - ((idx) * sizeof(Bucket)) -# define HT_HASH_TO_IDX(idx) \ - ((idx) / sizeof(Bucket)) + +static zend_always_inline Bucket *HT_HASH_TO_BUCKET_EX(Bucket *data, uint32_t idx) { + return ((Bucket*)((char*)(data) + (idx))); +} + +static zend_always_inline uint32_t HT_IDX_TO_HASH(uint32_t idx) { + return idx * sizeof(Bucket); +} + +static zend_always_inline uint32_t HT_HASH_TO_IDX(uint32_t idx) { + return idx / sizeof(Bucket); +} #elif SIZEOF_SIZE_T == 8 # define HT_MAX_SIZE 0x40000000 -# define HT_HASH_TO_BUCKET_EX(data, idx) \ - ((data) + (idx)) -# define HT_IDX_TO_HASH(idx) \ - (idx) -# define HT_HASH_TO_IDX(idx) \ - (idx) +static zend_always_inline Bucket *HT_HASH_TO_BUCKET_EX(Bucket *data, uint32_t idx) { + return data + idx; +} + +static zend_always_inline uint32_t HT_IDX_TO_HASH(uint32_t idx) { + return idx; +} + +static zend_always_inline uint32_t HT_HASH_TO_IDX(uint32_t idx) { + return idx; +} #else # error "Unknown SIZEOF_SIZE_T" #endif @@ -469,81 +480,96 @@ struct _zend_array { #define HT_HASH(ht, idx) \ HT_HASH_EX((ht)->arHash, idx) -#define HT_SIZE_TO_MASK(nTableSize) \ - ((uint32_t)(-((nTableSize) + (nTableSize)))) -#define HT_HASH_SIZE(nTableMask) \ - (((size_t)-(uint32_t)(nTableMask)) * sizeof(uint32_t)) -#define HT_DATA_SIZE(nTableSize) \ - ((size_t)(nTableSize) * sizeof(Bucket)) -#define HT_SIZE_EX(nTableSize, nTableMask) \ - (HT_DATA_SIZE((nTableSize)) + HT_HASH_SIZE((nTableMask))) -#define HT_SIZE(ht) \ - HT_SIZE_EX((ht)->nTableSize, (ht)->nTableMask) -#define HT_USED_SIZE(ht) \ - (HT_HASH_SIZE((ht)->nTableMask) + ((size_t)(ht)->nNumUsed * sizeof(Bucket))) -#define HT_PACKED_DATA_SIZE(nTableSize) \ - ((size_t)(nTableSize) * sizeof(zval)) -#define HT_PACKED_SIZE_EX(nTableSize, nTableMask) \ - (HT_PACKED_DATA_SIZE((nTableSize)) + HT_HASH_SIZE((nTableMask))) -#define HT_PACKED_SIZE(ht) \ - HT_PACKED_SIZE_EX((ht)->nTableSize, (ht)->nTableMask) -#define HT_PACKED_USED_SIZE(ht) \ - (HT_HASH_SIZE((ht)->nTableMask) + ((size_t)(ht)->nNumUsed * sizeof(zval))) +static zend_always_inline uint32_t HT_SIZE_TO_MASK(uint32_t nTableSize) { + return (uint32_t)(-(nTableSize + nTableSize)); +} + +static zend_always_inline size_t HT_HASH_SIZE(uint32_t nTableMask) { + return ((size_t)(-nTableMask)) * sizeof(uint32_t); +} + +static zend_always_inline size_t HT_DATA_SIZE(uint32_t nTableSize) { + return ((size_t)nTableSize) * sizeof(Bucket); +} + +static zend_always_inline size_t HT_SIZE_EX(uint32_t nTableSize, uint32_t nTableMask) { + return HT_DATA_SIZE(nTableSize) + HT_HASH_SIZE(nTableMask); +} + +static zend_always_inline size_t HT_SIZE(const HashTable *ht) { + return HT_SIZE_EX(ht->nTableSize, ht->nTableMask); +} + +static zend_always_inline size_t HT_USED_SIZE(const HashTable *ht) { + return HT_HASH_SIZE(ht->nTableMask) + ((size_t)ht->nNumUsed * sizeof(Bucket)); +} + +static zend_always_inline size_t HT_PACKED_DATA_SIZE(uint32_t nTableSize) { + return ((size_t)nTableSize) * sizeof(zval); +} + +static zend_always_inline size_t HT_PACKED_SIZE_EX(uint32_t nTableSize, uint32_t nTableMask) { + return HT_PACKED_DATA_SIZE(nTableSize) + HT_HASH_SIZE(nTableMask); +} + +static zend_always_inline size_t HT_PACKED_SIZE(const HashTable *ht) { + return HT_PACKED_SIZE_EX(ht->nTableSize, ht->nTableMask); +} + +static zend_always_inline size_t HT_PACKED_USED_SIZE(const HashTable *ht) { + return HT_HASH_SIZE(ht->nTableMask) + ((size_t)ht->nNumUsed * sizeof(zval)); +} + +static zend_always_inline void HT_HASH_RESET(HashTable *ht) { + char *p = (char*)&HT_HASH(ht, ht->nTableMask); + size_t size = HT_HASH_SIZE(ht->nTableMask); + #if defined(__AVX2__) -# define HT_HASH_RESET(ht) do { \ - char *p = (char*)&HT_HASH(ht, (ht)->nTableMask); \ - size_t size = HT_HASH_SIZE((ht)->nTableMask); \ - __m256i ymm0 = _mm256_setzero_si256(); \ - ymm0 = _mm256_cmpeq_epi64(ymm0, ymm0); \ - ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \ - do { \ - _mm256_storeu_si256((__m256i*)p, ymm0); \ - _mm256_storeu_si256((__m256i*)(p+32), ymm0); \ - p += 64; \ - size -= 64; \ - } while (size != 0); \ - } while (0) + __m256i ymm0 = _mm256_setzero_si256(); + ymm0 = _mm256_cmpeq_epi64(ymm0, ymm0); + ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); + do { + _mm256_storeu_si256((__m256i*)p, ymm0); + _mm256_storeu_si256((__m256i*)(p+32), ymm0); + p += 64; + size -= 64; + } while (size != 0); #elif defined(__SSE2__) -# define HT_HASH_RESET(ht) do { \ - char *p = (char*)&HT_HASH(ht, (ht)->nTableMask); \ - size_t size = HT_HASH_SIZE((ht)->nTableMask); \ - __m128i xmm0 = _mm_setzero_si128(); \ - xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \ - ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \ - do { \ - _mm_storeu_si128((__m128i*)p, xmm0); \ - _mm_storeu_si128((__m128i*)(p+16), xmm0); \ - _mm_storeu_si128((__m128i*)(p+32), xmm0); \ - _mm_storeu_si128((__m128i*)(p+48), xmm0); \ - p += 64; \ - size -= 64; \ - } while (size != 0); \ - } while (0) + __m128i xmm0 = _mm_setzero_si128(); + xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); + ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); + do { + _mm_storeu_si128((__m128i*)p, xmm0); + _mm_storeu_si128((__m128i*)(p+16), xmm0); + _mm_storeu_si128((__m128i*)(p+32), xmm0); + _mm_storeu_si128((__m128i*)(p+48), xmm0); + p += 64; + size -= 64; + } while (size != 0); #elif defined(__aarch64__) || defined(_M_ARM64) -# define HT_HASH_RESET(ht) do { \ - char *p = (char*)&HT_HASH(ht, (ht)->nTableMask); \ - size_t size = HT_HASH_SIZE((ht)->nTableMask); \ - int32x4_t t = vdupq_n_s32(-1); \ - ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \ - do { \ - vst1q_s32((int32_t*)p, t); \ - vst1q_s32((int32_t*)(p+16), t); \ - vst1q_s32((int32_t*)(p+32), t); \ - vst1q_s32((int32_t*)(p+48), t); \ - p += 64; \ - size -= 64; \ - } while (size != 0); \ - } while (0) + int32x4_t t = vdupq_n_s32(-1); + ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); + do { + vst1q_s32((int32_t*)p, t); + vst1q_s32((int32_t*)(p+16), t); + vst1q_s32((int32_t*)(p+32), t); + vst1q_s32((int32_t*)(p+48), t); + p += 64; + size -= 64; + } while (size != 0); #else -# define HT_HASH_RESET(ht) \ - memset(&HT_HASH(ht, (ht)->nTableMask), HT_INVALID_IDX, HT_HASH_SIZE((ht)->nTableMask)) + memset(p, HT_INVALID_IDX, size); #endif -#define HT_HASH_RESET_PACKED(ht) do { \ - HT_HASH(ht, -2) = HT_INVALID_IDX; \ - HT_HASH(ht, -1) = HT_INVALID_IDX; \ - } while (0) -#define HT_HASH_TO_BUCKET(ht, idx) \ - HT_HASH_TO_BUCKET_EX((ht)->arData, idx) +} + +static zend_always_inline void HT_HASH_RESET_PACKED(HashTable *ht) { + HT_HASH(ht, -2) = HT_INVALID_IDX; + HT_HASH(ht, -1) = HT_INVALID_IDX; +} + +static zend_always_inline Bucket *HT_HASH_TO_BUCKET(HashTable *ht, uint32_t idx) { + return HT_HASH_TO_BUCKET_EX(ht->arData, idx); +} #define HT_SET_DATA_ADDR(ht, ptr) do { \ (ht)->arData = (Bucket*)(((char*)(ptr)) + HT_HASH_SIZE((ht)->nTableMask)); \