@@ -144,10 +144,18 @@ static zend_always_inline void zend_hash_real_init_mixed_ex(HashTable *ht)
144
144
uint32_t nSize = ht -> nTableSize ;
145
145
146
146
if (UNEXPECTED (GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT )) {
147
+ if (nSize < HT_MIN_SIZE_UNPACKED ) {
148
+ nSize = HT_MIN_SIZE_UNPACKED ;
149
+ ht -> nTableSize = HT_MIN_SIZE_UNPACKED ;
150
+ }
147
151
data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), 1 );
148
- } else if (EXPECTED (nSize == HT_MIN_SIZE )) {
149
- data = emalloc (HT_SIZE_EX (HT_MIN_SIZE , HT_SIZE_TO_MASK (HT_MIN_SIZE )));
150
- ht -> nTableMask = HT_SIZE_TO_MASK (HT_MIN_SIZE );
152
+ } else if (EXPECTED (nSize <= HT_MIN_SIZE_UNPACKED )) {
153
+ if (nSize < HT_MIN_SIZE_UNPACKED ) {
154
+ nSize = HT_MIN_SIZE_UNPACKED ;
155
+ ht -> nTableSize = HT_MIN_SIZE_UNPACKED ;
156
+ }
157
+ data = emalloc (HT_SIZE_EX (HT_MIN_SIZE_UNPACKED , HT_SIZE_TO_MASK (HT_MIN_SIZE_UNPACKED )));
158
+ ht -> nTableMask = HT_SIZE_TO_MASK (HT_MIN_SIZE_UNPACKED );
151
159
HT_SET_DATA_ADDR (ht , data );
152
160
/* Don't overwrite iterator count. */
153
161
ht -> u .v .flags = HASH_FLAG_STATIC_KEYS ;
@@ -210,6 +218,7 @@ static zend_always_inline void zend_hash_real_init_ex(HashTable *ht, int packed)
210
218
static const uint32_t uninitialized_bucket [- HT_MIN_MASK ] =
211
219
{HT_INVALID_IDX , HT_INVALID_IDX };
212
220
221
+ // XXX: Is MIN_SIZE_UNPACKED the best choice vs this (8 vs 2)? Haven't benchmarked it.
213
222
ZEND_API const HashTable zend_empty_array = {
214
223
.gc .refcount = 2 ,
215
224
.gc .u .type_info = IS_ARRAY | (GC_IMMUTABLE << GC_FLAGS_SHIFT ),
@@ -218,7 +227,7 @@ ZEND_API const HashTable zend_empty_array = {
218
227
.arData = (Bucket * )& uninitialized_bucket [2 ],
219
228
.nNumUsed = 0 ,
220
229
.nNumOfElements = 0 ,
221
- .nTableSize = HT_MIN_SIZE ,
230
+ .nTableSize = HT_MIN_SIZE_UNPACKED ,
222
231
.nInternalPointer = 0 ,
223
232
.nNextFreeElement = 0 ,
224
233
.pDestructor = ZVAL_PTR_DTOR
@@ -244,6 +253,7 @@ ZEND_API void ZEND_FASTCALL _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_
244
253
_zend_hash_init_int (ht , nSize , pDestructor , persistent );
245
254
}
246
255
256
+ // TODO should this be 2 or 8? also see zend_new_array
247
257
ZEND_API HashTable * ZEND_FASTCALL _zend_new_array_0 (void )
248
258
{
249
259
HashTable * ht = emalloc (sizeof (HashTable ));
@@ -262,6 +272,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_new_pair(zval *val1, zval *val2)
262
272
{
263
273
Bucket * p ;
264
274
HashTable * ht = emalloc (sizeof (HashTable ));
275
+ // XXX will need to adjust all calls like this if HT_MIN_SIZE goes below 2
265
276
_zend_hash_init_int (ht , HT_MIN_SIZE , ZVAL_PTR_DTOR , 0 );
266
277
ht -> nNumUsed = ht -> nNumOfElements = ht -> nNextFreeElement = 2 ;
267
278
zend_hash_real_init_packed_ex (ht );
@@ -317,11 +328,12 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht)
317
328
void * new_data , * old_data = HT_GET_DATA_ADDR (ht );
318
329
Bucket * old_buckets = ht -> arData ;
319
330
uint32_t nSize = ht -> nTableSize ;
331
+ uint32_t nNewSize = nSize >= HT_MIN_SIZE_UNPACKED ? nSize : HT_MIN_SIZE_UNPACKED ;
320
332
321
333
HT_ASSERT_RC1 (ht );
322
334
HT_FLAGS (ht ) &= ~HASH_FLAG_PACKED ;
323
- new_data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
324
- ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
335
+ new_data = pemalloc (HT_SIZE_EX (nNewSize , HT_SIZE_TO_MASK (nNewSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
336
+ ht -> nTableMask = HT_SIZE_TO_MASK (nNewSize );
325
337
HT_SET_DATA_ADDR (ht , new_data );
326
338
memcpy (ht -> arData , old_buckets , sizeof (Bucket ) * ht -> nNumUsed );
327
339
pefree (old_data , GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
@@ -1158,6 +1170,9 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
1158
1170
} else if (ht -> nTableSize < HT_MAX_SIZE ) { /* Let's double the table size */
1159
1171
void * new_data , * old_data = HT_GET_DATA_ADDR (ht );
1160
1172
uint32_t nSize = ht -> nTableSize + ht -> nTableSize ;
1173
+ if (nSize < HT_MIN_SIZE_UNPACKED ) {
1174
+ nSize = HT_MIN_SIZE_UNPACKED ;
1175
+ }
1161
1176
Bucket * old_buckets = ht -> arData ;
1162
1177
1163
1178
ht -> nTableSize = nSize ;
0 commit comments