]> granicus.if.org Git - php/commitdiff
Introduced HT_IS_PACKED() and HT_IS_WITHOUT_HOLES() macros. (Benjamin Coutu)
authorDmitry Stogov <dmitry@zend.com>
Wed, 19 Oct 2016 20:10:42 +0000 (23:10 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 19 Oct 2016 20:10:42 +0000 (23:10 +0300)
Zend/zend_hash.c
Zend/zend_hash.h
Zend/zend_types.h
ext/json/json_encoder.c
ext/soap/php_encoding.c
ext/standard/array.c

index ec9a5ba486609bec87151c9f617f12cc0c28ba0d..fdbdcac5a09f4bdf8b8f9072d460a53d83f83e48 100644 (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
 
 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)
@@ -891,7 +889,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);
@@ -1232,8 +1230,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);
@@ -1244,7 +1242,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)) {
@@ -1264,7 +1262,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)) {
@@ -1303,11 +1301,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)) {
@@ -1345,8 +1343,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);
@@ -1357,7 +1355,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)) {
@@ -1375,8 +1373,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);
@@ -1413,11 +1411,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)) {
@@ -1805,7 +1803,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);
@@ -1826,14 +1824,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);
@@ -2256,7 +2254,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++) {
index b7e6f37f71fe3cb123c33614da34cdacce74b46d..190551d3f127e9768523406673d0c5ebb9748142 100644 (file)
 #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;
index 29dec8e97f84565595aba0939a3371e986753e40..2a108877bfd40cbeb9f8407e4ca470988047c2b4 100644 (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;
index f94674831a11bda4ae52d9e0c03175681a7774ac..473726c569d77c1bad2a03e0df227abbc12a0a9e 100644 (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) {
index c0e22d741bd3922f3b7cfc8daeced0a3a61a28c2..c6a3f865cb0e605ea6a234429a6773e63f460b65 100644 (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;
index 078b84ab8f198cab644beed8b28dc3fe77095ee2..8cf417bcfa353f3d9da92062db5ffc28dbe3c704 100644 (file)
@@ -2909,7 +2909,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) {