Skip to content

Commit 49d2273

Browse files
committed
[Proposal] Reduce the minimum size for packed arrays from 8 to 2
Continue to require that associative arrays have a minimum size of 8 and are powers of 8. This can reduce the memory usage of some applications by ~16% in applications that heavily use small arrays. Stop requiring that packed arrays have a size that is a power of 2. There's no reason to for packed arrays, since php isn't doing any hash lookups with bit operations. Add a helper to create an associative array with a minimum size. This may help with clarity/avoiding unnecessary size recalculations. (performance impact may be negligible) https://nikic.github.io/2014/12/22/PHPs-new-hashtable-implementation.html gives some background information on the `HashTable` implementation on master. This is a followup to php#4753 (comment) (I didn't see any other PRs mentioning HT_MIN_SIZE)
1 parent 8b86af4 commit 49d2273

21 files changed

+96
-37
lines changed

Zend/zend_API.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3892,7 +3892,7 @@ ZEND_API bool zend_make_callable(zval *callable, zend_string **callable_name) /*
38923892
if (zend_is_callable_ex(callable, NULL, 0, callable_name, &fcc, NULL)) {
38933893
if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
38943894
zval_ptr_dtor_str(callable);
3895-
array_init(callable);
3895+
array_init_size(callable, 2);
38963896
add_next_index_str(callable, zend_string_copy(fcc.calling_scope->name));
38973897
add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
38983898
}

Zend/zend_API.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,8 +479,10 @@ ZEND_API const char *zend_get_type_by_const(int type);
479479
#define DLEXPORT
480480
#endif
481481

482-
#define array_init(arg) ZVAL_ARR((arg), zend_new_array(0))
483-
#define array_init_size(arg, size) ZVAL_ARR((arg), zend_new_array(size))
482+
#define array_init(arg) ZVAL_ARR((arg), zend_new_array(0))
483+
#define array_init_size(arg, size) ZVAL_ARR((arg), zend_new_array(size))
484+
#define array_init_assoc(arg) ZVAL_ARR((arg), zend_new_array_assoc(0))
485+
#define array_init_assoc_size(arg, size) ZVAL_ARR((arg), zend_new_array_assoc(size))
484486
ZEND_API void object_init(zval *arg);
485487
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *ce);
486488
ZEND_API zend_result object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties);

Zend/zend_ast.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -672,13 +672,15 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast
672672
{
673673
uint32_t i;
674674
zend_ast_list *list = zend_ast_get_list(ast);
675+
uint32_t n_children = list->children;
675676

676-
if (!list->children) {
677+
if (!n_children) {
677678
ZVAL_EMPTY_ARRAY(result);
678679
break;
679680
}
680-
array_init(result);
681-
for (i = 0; i < list->children; i++) {
681+
/** Usually, there won't be an AST_UNPACK or duplicate keys. Assume that's the initial capacity. */
682+
array_init_size(result, n_children);
683+
for (i = 0; i < n_children; i++) {
682684
zend_ast *elem = list->child[i];
683685
if (elem->kind == ZEND_AST_UNPACK) {
684686
if (UNEXPECTED(zend_ast_evaluate(&op1, elem->child[0], scope) != SUCCESS)) {

Zend/zend_builtin_functions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ ZEND_FUNCTION(gc_status)
136136

137137
zend_gc_get_status(&status);
138138

139-
array_init_size(return_value, 3);
139+
array_init_assoc_size(return_value, 4);
140140

141141
add_assoc_long_ex(return_value, "runs", sizeof("runs")-1, (long)status.runs);
142142
add_assoc_long_ex(return_value, "collected", sizeof("collected")-1, (long)status.collected);

Zend/zend_execute.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2294,7 +2294,7 @@ static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *
22942294
return;
22952295
}
22962296
}
2297-
array_init(container);
2297+
array_init(container); /* TODO benchmark and check if array_init_assoc is faster */
22982298
goto fetch_from_array;
22992299
} else {
23002300
goto return_null;

Zend/zend_hash.c

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,18 @@ static zend_always_inline void zend_hash_real_init_mixed_ex(HashTable *ht)
167167
uint32_t nSize = ht->nTableSize;
168168

169169
if (UNEXPECTED(GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)) {
170+
if (nSize < HT_MIN_SIZE_UNPACKED) {
171+
nSize = HT_MIN_SIZE_UNPACKED;
172+
ht->nTableSize = HT_MIN_SIZE_UNPACKED;
173+
}
170174
data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), 1);
171-
} else if (EXPECTED(nSize == HT_MIN_SIZE)) {
172-
data = emalloc(HT_SIZE_EX(HT_MIN_SIZE, HT_SIZE_TO_MASK(HT_MIN_SIZE)));
173-
ht->nTableMask = HT_SIZE_TO_MASK(HT_MIN_SIZE);
175+
} else if (EXPECTED(nSize <= HT_MIN_SIZE_UNPACKED)) {
176+
if (nSize < HT_MIN_SIZE_UNPACKED) {
177+
nSize = HT_MIN_SIZE_UNPACKED;
178+
ht->nTableSize = HT_MIN_SIZE_UNPACKED;
179+
}
180+
data = emalloc(HT_SIZE_EX(HT_MIN_SIZE_UNPACKED, HT_SIZE_TO_MASK(HT_MIN_SIZE_UNPACKED)));
181+
ht->nTableMask = HT_SIZE_TO_MASK(HT_MIN_SIZE_UNPACKED);
174182
HT_SET_DATA_ADDR(ht, data);
175183
/* Don't overwrite iterator count. */
176184
ht->u.v.flags = HASH_FLAG_STATIC_KEYS;
@@ -233,6 +241,7 @@ static zend_always_inline void zend_hash_real_init_ex(HashTable *ht, bool packed
233241
static const uint32_t uninitialized_bucket[-HT_MIN_MASK] =
234242
{HT_INVALID_IDX, HT_INVALID_IDX};
235243

244+
/* XXX: Is MIN_SIZE_UNPACKED the best choice vs this (8 vs 2)? Haven't benchmarked it. This would affect copy on writes for appending to the empty array. */
236245
ZEND_API const HashTable zend_empty_array = {
237246
.gc.refcount = 2,
238247
.gc.u.type_info = IS_ARRAY | (GC_IMMUTABLE << GC_FLAGS_SHIFT),
@@ -241,7 +250,7 @@ ZEND_API const HashTable zend_empty_array = {
241250
.arData = (Bucket*)&uninitialized_bucket[2],
242251
.nNumUsed = 0,
243252
.nNumOfElements = 0,
244-
.nTableSize = HT_MIN_SIZE,
253+
.nTableSize = HT_MIN_SIZE_UNPACKED,
245254
.nInternalPointer = 0,
246255
.nNextFreeElement = 0,
247256
.pDestructor = ZVAL_PTR_DTOR
@@ -259,6 +268,7 @@ static zend_always_inline void _zend_hash_init_int(HashTable *ht, uint32_t nSize
259268
ht->nInternalPointer = 0;
260269
ht->nNextFreeElement = ZEND_LONG_MIN;
261270
ht->pDestructor = pDestructor;
271+
/* Choose the smallest power of 2 that's greater than or equal to nSize and at least HT_MIN_SIZE(2). */
262272
ht->nTableSize = zend_hash_check_size(nSize);
263273
}
264274

@@ -274,17 +284,32 @@ ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void)
274284
return ht;
275285
}
276286

287+
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_assoc_0(void)
288+
{
289+
HashTable *ht = emalloc(sizeof(HashTable));
290+
_zend_hash_init_int(ht, HT_MIN_SIZE_UNPACKED, ZVAL_PTR_DTOR, 0);
291+
return ht;
292+
}
293+
277294
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t nSize)
278295
{
279296
HashTable *ht = emalloc(sizeof(HashTable));
280297
_zend_hash_init_int(ht, nSize, ZVAL_PTR_DTOR, 0);
281298
return ht;
282299
}
283300

301+
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_assoc(uint32_t nSize)
302+
{
303+
HashTable *ht = emalloc(sizeof(HashTable));
304+
_zend_hash_init_int(ht, nSize < HT_MIN_SIZE_UNPACKED ? HT_MIN_SIZE_UNPACKED : nSize, ZVAL_PTR_DTOR, 0);
305+
return ht;
306+
}
307+
284308
ZEND_API HashTable* ZEND_FASTCALL zend_new_pair(zval *val1, zval *val2)
285309
{
286310
zval *zv;
287311
HashTable *ht = emalloc(sizeof(HashTable));
312+
/* XXX: Currently, HT_MIN_SIZE == 2. will need to adjust all calls like this if HT_MIN_SIZE goes below 2 */
288313
_zend_hash_init_int(ht, HT_MIN_SIZE, ZVAL_PTR_DTOR, 0);
289314
ht->nNumUsed = ht->nNumOfElements = ht->nNextFreeElement = 2;
290315
zend_hash_real_init_packed_ex(ht);
@@ -337,11 +362,18 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht)
337362
Bucket *dst;
338363
uint32_t i;
339364
uint32_t nSize = ht->nTableSize;
365+
if (nSize < HT_MIN_SIZE_UNPACKED) {
366+
nSize = HT_MIN_SIZE_UNPACKED;
367+
ht->nTableSize = HT_MIN_SIZE_UNPACKED;
368+
} else if (nSize & (nSize - 1)) {
369+
nSize = zend_hash_check_size(nSize);
370+
ht->nTableSize = nSize;
371+
}
340372

341373
HT_ASSERT_RC1(ht);
342374
HT_FLAGS(ht) &= ~HASH_FLAG_PACKED;
343375
new_data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
344-
ht->nTableMask = HT_SIZE_TO_MASK(ht->nTableSize);
376+
ht->nTableMask = HT_SIZE_TO_MASK(nSize);
345377
HT_SET_DATA_ADDR(ht, new_data);
346378
dst = ht->arData;
347379
for (i = 0; i < ht->nNumUsed; i++) {
@@ -1226,14 +1258,14 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
12261258
ZEND_ASSERT(!HT_IS_PACKED(ht));
12271259
if (ht->nNumUsed > ht->nNumOfElements + (ht->nNumOfElements >> 5)) { /* additional term is there to amortize the cost of compaction */
12281260
zend_hash_rehash(ht);
1229-
} else if (ht->nTableSize < HT_MAX_SIZE) { /* Let's double the table size */
1261+
} else if (EXPECTED(ht->nTableSize < HT_MAX_SIZE)) { /* Let's double the table size */
12301262
void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
1231-
uint32_t nSize = ht->nTableSize + ht->nTableSize;
1263+
uint32_t nSize = zend_hash_check_size(ht->nTableSize + ht->nTableSize);
12321264
Bucket *old_buckets = ht->arData;
12331265

12341266
ht->nTableSize = nSize;
12351267
new_data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
1236-
ht->nTableMask = HT_SIZE_TO_MASK(ht->nTableSize);
1268+
ht->nTableMask = HT_SIZE_TO_MASK(nSize);
12371269
HT_SET_DATA_ADDR(ht, new_data);
12381270
memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
12391271
pefree(old_data, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);

Zend/zend_hash.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,13 +309,27 @@ ZEND_API void ZEND_FASTCALL zend_hash_rehash(HashTable *ht);
309309
: \
310310
_zend_new_array((size)) \
311311
)
312+
# define zend_new_array_assoc(size) \
313+
(__builtin_constant_p(size) ? \
314+
((((uint32_t)(size)) <= HT_MIN_SIZE_UNPACKED) ? \
315+
_zend_new_array_assoc_0() \
316+
: \
317+
_zend_new_array_assoc((size)) \
318+
) \
319+
: \
320+
_zend_new_array_assoc((size)) \
321+
)
312322
#else
313323
# define zend_new_array(size) \
314324
_zend_new_array(size)
325+
# define zend_new_array_assoc(size) \
326+
_zend_new_array_assoc(size)
315327
#endif
316328

317329
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void);
330+
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_assoc_0(void);
318331
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t size);
332+
ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_assoc(uint32_t size);
319333
ZEND_API HashTable* ZEND_FASTCALL zend_new_pair(zval *val1, zval *val2);
320334
ZEND_API uint32_t zend_array_count(HashTable *ht);
321335
ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source);

Zend/zend_operators.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ ZEND_API const unsigned char zend_toupper_map[256] = {
118118
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
119119
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
120120
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
121-
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
121+
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
122122
};
123123

124124

Zend/zend_types.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,8 @@ struct _zend_array {
402402
#define HT_INVALID_IDX ((uint32_t) -1)
403403

404404
#define HT_MIN_MASK ((uint32_t) -2)
405-
#define HT_MIN_SIZE 8
405+
#define HT_MIN_SIZE 2
406+
#define HT_MIN_SIZE_UNPACKED 8
406407

407408
#if SIZEOF_SIZE_T == 4
408409
# define HT_MAX_SIZE 0x04000000 /* small enough to avoid overflow checks */
@@ -430,7 +431,7 @@ struct _zend_array {
430431
HT_HASH_EX((ht)->arHash, idx)
431432

432433
#define HT_SIZE_TO_MASK(nTableSize) \
433-
((uint32_t)(-((nTableSize) + (nTableSize))))
434+
(uint32_t)(-(zend_hash_check_size((nTableSize) + (nTableSize))))
434435
#define HT_HASH_SIZE(nTableMask) \
435436
(((size_t)(uint32_t)-(int32_t)(nTableMask)) * sizeof(uint32_t))
436437
#define HT_DATA_SIZE(nTableSize) \
@@ -455,7 +456,15 @@ struct _zend_array {
455456
size_t size = HT_HASH_SIZE((ht)->nTableMask); \
456457
__m128i xmm0 = _mm_setzero_si128(); \
457458
xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \
458-
ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \
459+
if (size < 64) { \
460+
ZEND_ASSERT(size == 16 || size == 32); \
461+
_mm_storeu_si128((__m128i*)p, xmm0); \
462+
if (size >= 32) { \
463+
_mm_storeu_si128((__m128i*)(p+16), xmm0); \
464+
} \
465+
break; \
466+
} \
467+
ZEND_ASSERT(((size & 0x3f) == 0)); \
459468
do { \
460469
_mm_storeu_si128((__m128i*)p, xmm0); \
461470
_mm_storeu_si128((__m128i*)(p+16), xmm0); \

Zend/zend_vm_def.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6211,7 +6211,7 @@ ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
62116211
}
62126212
Z_OBJ_P(result)->properties = ht;
62136213
} else if (Z_TYPE_P(expr) != IS_NULL) {
6214-
Z_OBJ_P(result)->properties = ht = zend_new_array(1);
6214+
Z_OBJ_P(result)->properties = ht = zend_new_array_assoc(1);
62156215
expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
62166216
if (OP1_TYPE == IS_CONST) {
62176217
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);

Zend/zend_vm_execute.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4824,7 +4824,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_H
48244824
}
48254825
Z_OBJ_P(result)->properties = ht;
48264826
} else if (Z_TYPE_P(expr) != IS_NULL) {
4827-
Z_OBJ_P(result)->properties = ht = zend_new_array(1);
4827+
Z_OBJ_P(result)->properties = ht = zend_new_array_assoc(1);
48284828
expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
48294829
if (IS_CONST == IS_CONST) {
48304830
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
@@ -19104,7 +19104,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC
1910419104
}
1910519105
Z_OBJ_P(result)->properties = ht;
1910619106
} else if (Z_TYPE_P(expr) != IS_NULL) {
19107-
Z_OBJ_P(result)->properties = ht = zend_new_array(1);
19107+
Z_OBJ_P(result)->properties = ht = zend_new_array_assoc(1);
1910819108
expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
1910919109
if (IS_TMP_VAR == IS_CONST) {
1911019110
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
@@ -21714,7 +21714,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC
2171421714
}
2171521715
Z_OBJ_P(result)->properties = ht;
2171621716
} else if (Z_TYPE_P(expr) != IS_NULL) {
21717-
Z_OBJ_P(result)->properties = ht = zend_new_array(1);
21717+
Z_OBJ_P(result)->properties = ht = zend_new_array_assoc(1);
2171821718
expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
2171921719
if (IS_VAR == IS_CONST) {
2172021720
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
@@ -38205,7 +38205,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO
3820538205
}
3820638206
Z_OBJ_P(result)->properties = ht;
3820738207
} else if (Z_TYPE_P(expr) != IS_NULL) {
38208-
Z_OBJ_P(result)->properties = ht = zend_new_array(1);
38208+
Z_OBJ_P(result)->properties = ht = zend_new_array_assoc(1);
3820938209
expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
3821038210
if (IS_CV == IS_CONST) {
3821138211
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);

ext/json/json_parser.y

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ static int php_json_parser_array_append(php_json_parser *parser, zval *array, zv
226226
static int php_json_parser_object_create(php_json_parser *parser, zval *object)
227227
{
228228
if (parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) {
229-
array_init(object);
229+
array_init_assoc(object);
230230
} else {
231231
object_init(object);
232232
}

ext/opcache/zend_persist.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ static void zend_hash_persist(HashTable *ht)
123123
data = zend_shared_memdup_free(data, HT_PACKED_USED_SIZE(ht));
124124
}
125125
HT_SET_DATA_ADDR(ht, data);
126-
} else if (ht->nNumUsed > HT_MIN_SIZE && ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) {
126+
} else if (ht->nNumUsed > HT_MIN_SIZE_UNPACKED && ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) {
127127
/* compact table */
128128
void *old_data = HT_GET_DATA_ADDR(ht);
129129
Bucket *old_buckets = ht->arData;

ext/opcache/zend_persist_calc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static void zend_hash_persist_calc(HashTable *ht)
5656

5757
if (HT_IS_PACKED(ht)) {
5858
ADD_SIZE(HT_PACKED_USED_SIZE(ht));
59-
} else if (ht->nNumUsed > HT_MIN_SIZE && ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) {
59+
} else if (ht->nNumUsed > HT_MIN_SIZE_UNPACKED && ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 4) {
6060
/* compact table */
6161
uint32_t hash_size;
6262

ext/standard/array.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2572,9 +2572,9 @@ PHP_FUNCTION(compact)
25722572
or multiple string names, rather than a combination of both.
25732573
So quickly guess a minimum result size based on that */
25742574
if (num_args && Z_TYPE(args[0]) == IS_ARRAY) {
2575-
array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL(args[0])));
2575+
array_init_assoc_size(return_value, zend_hash_num_elements(Z_ARRVAL(args[0])));
25762576
} else {
2577-
array_init_size(return_value, num_args);
2577+
array_init_assoc_size(return_value, num_args);
25782578
}
25792579

25802580
for (i = 0; i < num_args; i++) {
@@ -2659,7 +2659,7 @@ PHP_FUNCTION(array_fill_keys)
26592659
ZEND_PARSE_PARAMETERS_END();
26602660

26612661
/* Initialize return array */
2662-
array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(keys)));
2662+
array_init_assoc_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(keys)));
26632663

26642664
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) {
26652665
ZVAL_DEREF(entry);

ext/standard/basic_functions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1276,7 +1276,7 @@ PHP_FUNCTION(time_nanosleep)
12761276
if (!nanosleep(&php_req, &php_rem)) {
12771277
RETURN_TRUE;
12781278
} else if (errno == EINTR) {
1279-
array_init(return_value);
1279+
array_init_size(return_value, 2);
12801280
add_assoc_long_ex(return_value, "seconds", sizeof("seconds")-1, php_rem.tv_sec);
12811281
add_assoc_long_ex(return_value, "nanoseconds", sizeof("nanoseconds")-1, php_rem.tv_nsec);
12821282
return;

ext/standard/datetime.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ PHP_FUNCTION(strptime)
8989
RETURN_FALSE;
9090
}
9191

92-
array_init(return_value);
92+
array_init_size(return_value, 9);
9393
add_assoc_long(return_value, "tm_sec", parsed_time.tm_sec);
9494
add_assoc_long(return_value, "tm_min", parsed_time.tm_min);
9595
add_assoc_long(return_value, "tm_hour", parsed_time.tm_hour);

ext/standard/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ PHP_FUNCTION(scandir)
568568
RETURN_FALSE;
569569
}
570570

571-
array_init(return_value);
571+
array_init_size(return_value, n);
572572

573573
for (i = 0; i < n; i++) {
574574
add_next_index_str(return_value, namelist[i]);

ext/standard/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1546,7 +1546,7 @@ PHPAPI void php_fstat(php_stream *stream, zval *return_value)
15461546
RETURN_FALSE;
15471547
}
15481548

1549-
array_init(return_value);
1549+
array_init_size(return_value, 26);
15501550

15511551
ZVAL_LONG(&stat_dev, stat_ssb.sb.st_dev);
15521552
ZVAL_LONG(&stat_ino, stat_ssb.sb.st_ino);

ext/standard/scanf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
627627
zval tmp;
628628

629629
/* allocate an array for return */
630-
array_init(return_value);
630+
array_init_size(return_value, totalVars);
631631

632632
for (i = 0; i < totalVars; i++) {
633633
ZVAL_NULL(&tmp);

ext/standard/streamsfuncs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ PHP_FUNCTION(stream_socket_pair)
6767
RETURN_FALSE;
6868
}
6969

70-
array_init(return_value);
70+
array_init_size(return_value, 2);
7171

7272
s1 = php_stream_sock_open_from_socket(pair[0], 0);
7373
s2 = php_stream_sock_open_from_socket(pair[1], 0);

0 commit comments

Comments
 (0)