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:
Dmitry Stogov 2016-10-19 23:12:17 +03:00
commit 65ea250022
6 changed files with 44 additions and 29 deletions

View file

@ -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++) {

View file

@ -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;

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -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) {