Commit 7c9fcfd7d8c for php.net

commit 7c9fcfd7d8cfc5b9c2bb535ca8a1c268505bd370
Author: Tim Düsterhus <tim@bastelstu.be>
Date:   Wed Jul 1 21:13:29 2026 +0200

    zend_types: Convert `HT_*()` macros to inline functions (#22305)

diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index 0edc4df3748..2cdfdcb1961 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)));
+}
+
+ZEND_ATTRIBUTE_CONST static zend_always_inline uint32_t HT_IDX_TO_HASH(uint32_t idx) {
+	return idx * sizeof(Bucket);
+}
+
+ZEND_ATTRIBUTE_CONST 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;
+}
+
+ZEND_ATTRIBUTE_CONST static zend_always_inline uint32_t HT_IDX_TO_HASH(uint32_t idx) {
+	return idx;
+}
+
+ZEND_ATTRIBUTE_CONST 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)))
+ZEND_ATTRIBUTE_CONST static zend_always_inline uint32_t HT_SIZE_TO_MASK(uint32_t nTableSize) {
+	return (uint32_t)(-(nTableSize + nTableSize));
+}
+
+ZEND_ATTRIBUTE_CONST static zend_always_inline size_t HT_HASH_SIZE(uint32_t nTableMask) {
+	return ((size_t)(-nTableMask)) * sizeof(uint32_t);
+}
+
+ZEND_ATTRIBUTE_CONST static zend_always_inline size_t HT_DATA_SIZE(uint32_t nTableSize) {
+	return ((size_t)nTableSize) * sizeof(Bucket);
+}
+
+ZEND_ATTRIBUTE_CONST 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));
+}
+
+ZEND_ATTRIBUTE_CONST static zend_always_inline size_t HT_PACKED_DATA_SIZE(uint32_t nTableSize) {
+	return ((size_t)nTableSize) * sizeof(zval);
+}
+
+ZEND_ATTRIBUTE_CONST 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)); \