mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
Reduce HT_MAX_SIZE to account for the max load factor of 0.5 (#10242)
zend_hash allocates a hash table twice as big as nTableSize (HT_HASH_SIZE(HT_SIZE_TO_MASK(nTableSize)) == nTableSize*2), so HT_MAX_SIZE must be half the max table size or less. Fixes GH-10240
This commit is contained in:
parent
4fb149390a
commit
0f7625c47c
@ -166,6 +166,8 @@ static zend_always_inline void zend_hash_real_init_mixed_ex(HashTable *ht)
|
||||
void *data;
|
||||
uint32_t nSize = ht->nTableSize;
|
||||
|
||||
ZEND_ASSERT(HT_SIZE_TO_MASK(nSize));
|
||||
|
||||
if (UNEXPECTED(GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)) {
|
||||
data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), 1);
|
||||
} else if (EXPECTED(nSize == HT_MIN_SIZE)) {
|
||||
@ -341,6 +343,8 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht)
|
||||
Bucket *old_buckets = ht->arData;
|
||||
uint32_t nSize = ht->nTableSize;
|
||||
|
||||
ZEND_ASSERT(HT_SIZE_TO_MASK(nSize));
|
||||
|
||||
HT_ASSERT_RC1(ht);
|
||||
HT_FLAGS(ht) &= ~HASH_FLAG_PACKED;
|
||||
new_data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
|
||||
@ -369,7 +373,11 @@ ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht)
|
||||
ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, bool packed)
|
||||
{
|
||||
HT_ASSERT_RC1(ht);
|
||||
|
||||
if (nSize == 0) return;
|
||||
|
||||
ZEND_ASSERT(HT_SIZE_TO_MASK(nSize));
|
||||
|
||||
if (UNEXPECTED(HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED)) {
|
||||
if (nSize > ht->nTableSize) {
|
||||
ht->nTableSize = zend_hash_check_size(nSize);
|
||||
@ -1207,6 +1215,8 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
|
||||
uint32_t nSize = ht->nTableSize + ht->nTableSize;
|
||||
Bucket *old_buckets = ht->arData;
|
||||
|
||||
ZEND_ASSERT(HT_SIZE_TO_MASK(nSize));
|
||||
|
||||
ht->nTableSize = nSize;
|
||||
new_data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
|
||||
ht->nTableMask = HT_SIZE_TO_MASK(ht->nTableSize);
|
||||
|
@ -400,8 +400,15 @@ struct _zend_array {
|
||||
#define HT_MIN_MASK ((uint32_t) -2)
|
||||
#define HT_MIN_SIZE 8
|
||||
|
||||
/* HT_MAX_SIZE is chosen to satisfy the following constraints:
|
||||
* - HT_SIZE_TO_MASK(HT_MAX_SIZE) != 0
|
||||
* - HT_SIZE_EX(HT_MAX_SIZE, HT_SIZE_TO_MASK(HT_MAX_SIZE)) does not overflow or
|
||||
* wrapparound, and is <= the addressable space size
|
||||
* - HT_MAX_SIZE must be a power of two:
|
||||
* (nTableSize<HT_MAX_SIZE ? nTableSize+nTableSize : nTableSize) <= HT_MAX_SIZE
|
||||
*/
|
||||
#if SIZEOF_SIZE_T == 4
|
||||
# define HT_MAX_SIZE 0x04000000 /* small enough to avoid overflow checks */
|
||||
# define HT_MAX_SIZE 0x02000000
|
||||
# define HT_HASH_TO_BUCKET_EX(data, idx) \
|
||||
((Bucket*)((char*)(data) + (idx)))
|
||||
# define HT_IDX_TO_HASH(idx) \
|
||||
@ -409,7 +416,7 @@ struct _zend_array {
|
||||
# define HT_HASH_TO_IDX(idx) \
|
||||
((idx) / sizeof(Bucket))
|
||||
#elif SIZEOF_SIZE_T == 8
|
||||
# define HT_MAX_SIZE 0x80000000
|
||||
# define HT_MAX_SIZE 0x40000000
|
||||
# define HT_HASH_TO_BUCKET_EX(data, idx) \
|
||||
((data) + (idx))
|
||||
# define HT_IDX_TO_HASH(idx) \
|
||||
@ -428,7 +435,7 @@ struct _zend_array {
|
||||
#define HT_SIZE_TO_MASK(nTableSize) \
|
||||
((uint32_t)(-((nTableSize) + (nTableSize))))
|
||||
#define HT_HASH_SIZE(nTableMask) \
|
||||
(((size_t)(uint32_t)-(int32_t)(nTableMask)) * sizeof(uint32_t))
|
||||
(((size_t)-(uint32_t)(nTableMask)) * sizeof(uint32_t))
|
||||
#define HT_DATA_SIZE(nTableSize) \
|
||||
((size_t)(nTableSize) * sizeof(Bucket))
|
||||
#define HT_SIZE_EX(nTableSize, nTableMask) \
|
||||
|
Loading…
Reference in New Issue
Block a user