mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Merge branch 'PHP-7.1'
* PHP-7.1: Introduced HT_IS_PACKED() and HT_IS_WITHOUT_HOLES() macros. (Benjamin Coutu)
This commit is contained in:
commit
65ea250022
6 changed files with 44 additions and 29 deletions
|
@ -34,9 +34,7 @@
|
|||
#define HT_POISONED_PTR ((HashTable *) (intptr_t) -1)
|
||||
|
||||
#if ZEND_DEBUG
|
||||
/*
|
||||
#define HASH_MASK_CONSISTENCY 0xc0
|
||||
*/
|
||||
|
||||
#define HT_OK 0x00
|
||||
#define HT_IS_DESTROYING 0x40
|
||||
#define HT_DESTROYED 0x80
|
||||
|
@ -44,10 +42,10 @@
|
|||
|
||||
static void _zend_is_inconsistent(const HashTable *ht, const char *file, int line)
|
||||
{
|
||||
if ((ht->u.flags & HASH_MASK_CONSISTENCY) == HT_OK) {
|
||||
if (ht->u.v.consistency == HT_OK) {
|
||||
return;
|
||||
}
|
||||
switch ((ht->u.flags & HASH_MASK_CONSISTENCY)) {
|
||||
switch (ht->u.v.consistency) {
|
||||
case HT_IS_DESTROYING:
|
||||
zend_output_debug_string(1, "%s(%d) : ht=%p is being destroyed", file, line, ht);
|
||||
break;
|
||||
|
@ -65,7 +63,7 @@ static void _zend_is_inconsistent(const HashTable *ht, const char *file, int lin
|
|||
}
|
||||
#define IS_CONSISTENT(a) _zend_is_inconsistent(a, __FILE__, __LINE__);
|
||||
#define SET_INCONSISTENT(n) do { \
|
||||
(ht)->u.flags |= n; \
|
||||
(ht)->u.v.consistency = n; \
|
||||
} while (0)
|
||||
#else
|
||||
#define IS_CONSISTENT(a)
|
||||
|
@ -888,7 +886,7 @@ ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht)
|
|||
HT_HASH_RESET(ht);
|
||||
i = 0;
|
||||
p = ht->arData;
|
||||
if (ht->nNumUsed == ht->nNumOfElements) {
|
||||
if (HT_IS_WITHOUT_HOLES(ht)) {
|
||||
do {
|
||||
nIndex = p->h | ht->nTableMask;
|
||||
Z_NEXT(p->val) = HT_HASH(ht, nIndex);
|
||||
|
@ -1229,8 +1227,8 @@ ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
|
|||
if (ht->pDestructor) {
|
||||
SET_INCONSISTENT(HT_IS_DESTROYING);
|
||||
|
||||
if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
|
||||
if (ht->nNumUsed == ht->nNumOfElements) {
|
||||
if (HT_HAS_STATIC_KEYS_ONLY(ht)) {
|
||||
if (HT_IS_WITHOUT_HOLES(ht)) {
|
||||
do {
|
||||
ht->pDestructor(&p->val);
|
||||
} while (++p != end);
|
||||
|
@ -1241,7 +1239,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
|
|||
}
|
||||
} while (++p != end);
|
||||
}
|
||||
} else if (ht->nNumUsed == ht->nNumOfElements) {
|
||||
} else if (HT_IS_WITHOUT_HOLES(ht)) {
|
||||
do {
|
||||
ht->pDestructor(&p->val);
|
||||
if (EXPECTED(p->key)) {
|
||||
|
@ -1261,7 +1259,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
|
|||
|
||||
SET_INCONSISTENT(HT_DESTROYED);
|
||||
} else {
|
||||
if (!(ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS))) {
|
||||
if (!HT_HAS_STATIC_KEYS_ONLY(ht)) {
|
||||
do {
|
||||
if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
|
||||
if (EXPECTED(p->key)) {
|
||||
|
@ -1300,11 +1298,11 @@ ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
|
|||
end = p + ht->nNumUsed;
|
||||
SET_INCONSISTENT(HT_IS_DESTROYING);
|
||||
|
||||
if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
|
||||
if (HT_HAS_STATIC_KEYS_ONLY(ht)) {
|
||||
do {
|
||||
i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
|
||||
} while (++p != end);
|
||||
} else if (ht->nNumUsed == ht->nNumOfElements) {
|
||||
} else if (HT_IS_WITHOUT_HOLES(ht)) {
|
||||
do {
|
||||
i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
|
||||
if (EXPECTED(p->key)) {
|
||||
|
@ -1342,8 +1340,8 @@ ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
|
|||
p = ht->arData;
|
||||
end = p + ht->nNumUsed;
|
||||
if (ht->pDestructor) {
|
||||
if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
|
||||
if (ht->nNumUsed == ht->nNumOfElements) {
|
||||
if (HT_HAS_STATIC_KEYS_ONLY(ht)) {
|
||||
if (HT_IS_WITHOUT_HOLES(ht)) {
|
||||
do {
|
||||
ht->pDestructor(&p->val);
|
||||
} while (++p != end);
|
||||
|
@ -1354,7 +1352,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
|
|||
}
|
||||
} while (++p != end);
|
||||
}
|
||||
} else if (ht->nNumUsed == ht->nNumOfElements) {
|
||||
} else if (HT_IS_WITHOUT_HOLES(ht)) {
|
||||
do {
|
||||
ht->pDestructor(&p->val);
|
||||
if (EXPECTED(p->key)) {
|
||||
|
@ -1372,8 +1370,8 @@ ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
|
|||
} while (++p != end);
|
||||
}
|
||||
} else {
|
||||
if (!(ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS))) {
|
||||
if (ht->nNumUsed == ht->nNumOfElements) {
|
||||
if (!HT_HAS_STATIC_KEYS_ONLY(ht)) {
|
||||
if (HT_IS_WITHOUT_HOLES(ht)) {
|
||||
do {
|
||||
if (EXPECTED(p->key)) {
|
||||
zend_string_release(p->key);
|
||||
|
@ -1410,11 +1408,11 @@ ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht)
|
|||
if (ht->nNumUsed) {
|
||||
p = ht->arData;
|
||||
end = p + ht->nNumUsed;
|
||||
if (ht->u.flags & HASH_FLAG_STATIC_KEYS) {
|
||||
if (HT_HAS_STATIC_KEYS_ONLY(ht)) {
|
||||
do {
|
||||
i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
|
||||
} while (++p != end);
|
||||
} else if (ht->nNumUsed == ht->nNumOfElements) {
|
||||
} else if (HT_IS_WITHOUT_HOLES(ht)) {
|
||||
do {
|
||||
i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
|
||||
if (EXPECTED(p->key)) {
|
||||
|
@ -1802,7 +1800,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source)
|
|||
target->nInternalPointer = source->nInternalPointer;
|
||||
HT_HASH_RESET_PACKED(target);
|
||||
|
||||
if (target->nNumUsed == target->nNumOfElements) {
|
||||
if (HT_IS_WITHOUT_HOLES(target)) {
|
||||
zend_array_dup_packed_elements(source, target, 0);
|
||||
} else {
|
||||
zend_array_dup_packed_elements(source, target, 1);
|
||||
|
@ -1823,14 +1821,14 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source)
|
|||
HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
|
||||
HT_HASH_RESET(target);
|
||||
|
||||
if (target->u.flags & HASH_FLAG_STATIC_KEYS) {
|
||||
if (source->nNumUsed == source->nNumOfElements) {
|
||||
if (HT_HAS_STATIC_KEYS_ONLY(target)) {
|
||||
if (HT_IS_WITHOUT_HOLES(source)) {
|
||||
idx = zend_array_dup_elements(source, target, 1, 0);
|
||||
} else {
|
||||
idx = zend_array_dup_elements(source, target, 1, 1);
|
||||
}
|
||||
} else {
|
||||
if (source->nNumUsed == source->nNumOfElements) {
|
||||
if (HT_IS_WITHOUT_HOLES(source)) {
|
||||
idx = zend_array_dup_elements(source, target, 0, 0);
|
||||
} else {
|
||||
idx = zend_array_dup_elements(source, target, 0, 1);
|
||||
|
@ -2253,7 +2251,7 @@ ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, co
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (ht->nNumUsed == ht->nNumOfElements) {
|
||||
if (HT_IS_WITHOUT_HOLES(ht)) {
|
||||
i = ht->nNumUsed;
|
||||
} else {
|
||||
for (j = 0, i = 0; j < ht->nNumUsed; j++) {
|
||||
|
|
|
@ -39,10 +39,17 @@
|
|||
#define HASH_FLAG_APPLY_PROTECTION (1<<1)
|
||||
#define HASH_FLAG_PACKED (1<<2)
|
||||
#define HASH_FLAG_INITIALIZED (1<<3)
|
||||
#define HASH_FLAG_STATIC_KEYS (1<<4)
|
||||
#define HASH_FLAG_STATIC_KEYS (1<<4) /* long and interned strings */
|
||||
#define HASH_FLAG_HAS_EMPTY_IND (1<<5)
|
||||
|
||||
#define HASH_MASK_CONSISTENCY 0xc0
|
||||
#define HT_IS_PACKED(ht) \
|
||||
(((ht)->u.flags & HASH_FLAG_PACKED) != 0)
|
||||
|
||||
#define HT_IS_WITHOUT_HOLES(ht) \
|
||||
((ht)->nNumUsed == (ht)->nNumOfElements)
|
||||
|
||||
#define HT_HAS_STATIC_KEYS_ONLY(ht) \
|
||||
(((ht)->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) != 0)
|
||||
|
||||
typedef struct _zend_hash_key {
|
||||
zend_ulong h;
|
||||
|
|
|
@ -182,7 +182,7 @@ struct _zend_array {
|
|||
zend_uchar flags,
|
||||
zend_uchar nApplyCount,
|
||||
zend_uchar nIteratorsCount,
|
||||
zend_uchar reserve)
|
||||
zend_uchar consistency)
|
||||
} v;
|
||||
uint32_t flags;
|
||||
} u;
|
||||
|
|
|
@ -45,6 +45,10 @@ static int php_json_determine_array_type(zval *val) /* {{{ */
|
|||
zend_string *key;
|
||||
zend_ulong index, idx;
|
||||
|
||||
if (HT_IS_PACKED(myht) && HT_IS_WITHOUT_HOLES(myht)) {
|
||||
return PHP_JSON_OUTPUT_ARRAY;
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
ZEND_HASH_FOREACH_KEY(myht, index, key) {
|
||||
if (key) {
|
||||
|
|
|
@ -3483,6 +3483,10 @@ static int is_map(zval *array)
|
|||
zend_string *key;
|
||||
zend_ulong i = 0;
|
||||
|
||||
if (HT_IS_PACKED(Z_ARRVAL_P(array)) && HT_IS_WITHOUT_HOLES(Z_ARRVAL_P(array))) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(array), index, key) {
|
||||
if (key || index != i) {
|
||||
return TRUE;
|
||||
|
|
|
@ -2903,7 +2903,9 @@ PHP_FUNCTION(array_slice)
|
|||
|
||||
/* Start at the beginning and go until we hit offset */
|
||||
pos = 0;
|
||||
if ((Z_ARRVAL_P(input)->u.flags & HASH_FLAG_PACKED) && !preserve_keys) {
|
||||
if (HT_IS_PACKED(Z_ARRVAL_P(input)) &&
|
||||
(!preserve_keys ||
|
||||
(offset == 0 && HT_IS_WITHOUT_HOLES(Z_ARRVAL_P(input))))) {
|
||||
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
|
||||
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue