diff options
-rw-r--r-- | Zend/zend_hash.c | 84 | ||||
-rw-r--r-- | Zend/zend_hash.h | 1 | ||||
-rw-r--r-- | Zend/zend_types.h | 18 | ||||
-rw-r--r-- | ext/opcache/zend_accelerator_util_funcs.c | 12 | ||||
-rw-r--r-- | ext/opcache/zend_persist.c | 4 | ||||
-rw-r--r-- | ext/opcache/zend_persist_calc.c | 2 |
6 files changed, 46 insertions, 75 deletions
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index ca2d7e69c7..8e8edc9569 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -82,18 +82,19 @@ static void _zend_is_inconsistent(const HashTable *ht, const char *file, int lin static void zend_hash_do_resize(HashTable *ht); -#define CHECK_INIT(ht, packed) do { \ - if (UNEXPECTED((ht)->nTableMask == 0)) { \ +#define CHECK_INIT(ht, packed) do { \ + if (UNEXPECTED(!((ht)->u.flags & HASH_FLAG_INITIALIZED))) { \ if (packed) { \ - (ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT); \ - (ht)->u.flags |= HASH_FLAG_PACKED; \ + (ht)->u.flags |= HASH_FLAG_INITIALIZED | HASH_FLAG_PACKED; \ + (ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT); \ } else { \ - (ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT); \ - (ht)->arHash = (uint32_t*)((ht)->arData + (ht)->nTableSize); \ - memset((ht)->arHash, INVALID_IDX, (ht)->nTableSize * sizeof(uint32_t)); \ + (ht)->u.flags |= HASH_FLAG_INITIALIZED; \ + (ht)->nTableMask = (ht)->nTableSize - 1; \ + (ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT); \ + (ht)->arHash = (uint32_t*)((ht)->arData + (ht)->nTableSize); \ + memset((ht)->arHash, INVALID_IDX, (ht)->nTableSize * sizeof(uint32_t)); \ } \ - (ht)->nTableMask = (ht)->nTableSize - 1; \ - } \ + } \ } while (0) static const uint32_t uninitialized_bucket = {INVALID_IDX}; @@ -129,7 +130,7 @@ ZEND_API void _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestru # endif #endif - ht->nTableMask = 0; /* 0 means that ht->arBuckets is uninitialized */ + ht->nTableMask = 0; ht->nNumUsed = 0; ht->nNumOfElements = 0; ht->nNextFreeElement = 0; @@ -145,7 +146,6 @@ static void zend_hash_packed_grow(HashTable *ht) HANDLE_BLOCK_INTERRUPTIONS(); ht->arData = (Bucket *) safe_perealloc(ht->arData, (ht->nTableSize << 1), sizeof(Bucket), 0, ht->u.flags & HASH_FLAG_PERSISTENT); ht->nTableSize = (ht->nTableSize << 1); - ht->nTableMask = ht->nTableSize - 1; HANDLE_UNBLOCK_INTERRUPTIONS(); } @@ -170,6 +170,7 @@ ZEND_API void zend_hash_to_packed(HashTable *ht) { HANDLE_BLOCK_INTERRUPTIONS(); ht->u.flags |= HASH_FLAG_PACKED; + ht->nTableMask = 0; ht->arData = erealloc(ht->arData, ht->nTableSize * sizeof(Bucket)); ht->arHash = (uint32_t*)&uninitialized_bucket; HANDLE_UNBLOCK_INTERRUPTIONS(); @@ -267,7 +268,7 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s IS_CONSISTENT(ht); - if (UNEXPECTED(ht->nTableMask == 0)) { + if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) { CHECK_INIT(ht, 0); goto add_to_hash; } else if (ht->u.flags & HASH_FLAG_PACKED) { @@ -418,7 +419,7 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, IS_CONSISTENT(ht); - if (UNEXPECTED(ht->nTableMask == 0)) { + if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) { CHECK_INIT(ht, h < ht->nTableSize); if (h < ht->nTableSize) { p = ht->arData + h; @@ -587,7 +588,7 @@ ZEND_API int zend_hash_rehash(HashTable *ht) IS_CONSISTENT(ht); if (UNEXPECTED(ht->nNumOfElements == 0)) { - if (ht->nTableMask) { + if (ht->u.flags & HASH_FLAG_INITIALIZED) { memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t)); } return SUCCESS; @@ -684,10 +685,6 @@ ZEND_API int zend_hash_del(HashTable *ht, zend_string *key) IS_CONSISTENT(ht); - if (ht->u.flags & HASH_FLAG_PACKED) { - return FAILURE; - } - h = zend_string_hash_val(key); nIndex = h & ht->nTableMask; @@ -718,10 +715,6 @@ ZEND_API int zend_hash_del_ind(HashTable *ht, zend_string *key) IS_CONSISTENT(ht); - if (ht->u.flags & HASH_FLAG_PACKED) { - return FAILURE; - } - h = zend_string_hash_val(key); nIndex = h & ht->nTableMask; @@ -765,10 +758,6 @@ ZEND_API int zend_hash_str_del(HashTable *ht, const char *str, size_t len) IS_CONSISTENT(ht); - if (ht->u.flags & HASH_FLAG_PACKED) { - return FAILURE; - } - h = zend_inline_hash_func(str, len); nIndex = h & ht->nTableMask; @@ -905,7 +894,7 @@ ZEND_API void zend_hash_destroy(HashTable *ht) } while (++p != end); } } - } else if (EXPECTED(!ht->nTableMask)) { + } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) { return; } pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT); @@ -947,7 +936,7 @@ ZEND_API void zend_array_destroy(HashTable *ht) } SET_INCONSISTENT(HT_DESTROYED); - } else if (EXPECTED(!ht->nTableMask)) { + } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) { return; } pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT); @@ -990,16 +979,14 @@ ZEND_API void zend_hash_clean(HashTable *ht) } while (++p != end); } } + if (!(ht->u.flags & HASH_FLAG_PACKED)) { + memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t)); + } } ht->nNumUsed = 0; ht->nNumOfElements = 0; ht->nNextFreeElement = 0; ht->nInternalPointer = INVALID_IDX; - if (ht->nTableMask) { - if (!(ht->u.flags & HASH_FLAG_PACKED)) { - memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t)); - } - } } ZEND_API void zend_symtable_clean(HashTable *ht) @@ -1019,16 +1006,14 @@ ZEND_API void zend_symtable_clean(HashTable *ht) } } } while (++p != end); + if (!(ht->u.flags & HASH_FLAG_PACKED)) { + memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t)); + } } ht->nNumUsed = 0; ht->nNumOfElements = 0; ht->nNextFreeElement = 0; ht->nInternalPointer = INVALID_IDX; - if (ht->nTableMask) { - if (!(ht->u.flags & HASH_FLAG_PACKED)) { - memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t)); - } - } } ZEND_API void zend_hash_graceful_destroy(HashTable *ht) @@ -1043,7 +1028,7 @@ ZEND_API void zend_hash_graceful_destroy(HashTable *ht) if (Z_TYPE(p->val) == IS_UNDEF) continue; _zend_hash_del_el(ht, idx, p); } - if (ht->nTableMask) { + if (ht->u.flags & HASH_FLAG_INITIALIZED) { pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT); } @@ -1065,7 +1050,7 @@ ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht) _zend_hash_del_el(ht, idx, p); } - if (ht->nTableMask) { + if (ht->u.flags & HASH_FLAG_INITIALIZED) { pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT); } @@ -1257,7 +1242,7 @@ ZEND_API void zend_array_dup(HashTable *target, HashTable *source) target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION; target_idx = 0; - if (target->nTableMask) { + if (target->u.flags & HASH_FLAG_INITIALIZED) { if (target->u.flags & HASH_FLAG_PACKED) { target->nNumUsed = source->nNumUsed; target->nNumOfElements = source->nNumOfElements; @@ -1448,10 +1433,6 @@ ZEND_API zval *zend_hash_find(const HashTable *ht, zend_string *key) IS_CONSISTENT(ht); - if (ht->u.flags & HASH_FLAG_PACKED) { - return NULL; - } - p = zend_hash_find_bucket(ht, key); return p ? &p->val : NULL; } @@ -1463,10 +1444,6 @@ ZEND_API zval *zend_hash_str_find(const HashTable *ht, const char *str, size_t l IS_CONSISTENT(ht); - if (ht->u.flags & HASH_FLAG_PACKED) { - return NULL; - } - h = zend_inline_hash_func(str, len); p = zend_hash_str_find_bucket(ht, str, len, h); return p ? &p->val : NULL; @@ -1478,10 +1455,6 @@ ZEND_API zend_bool zend_hash_exists(const HashTable *ht, zend_string *key) IS_CONSISTENT(ht); - if (ht->u.flags & HASH_FLAG_PACKED) { - return 0; - } - p = zend_hash_find_bucket(ht, key); return p ? 1 : 0; } @@ -1493,10 +1466,6 @@ ZEND_API zend_bool zend_hash_str_exists(const HashTable *ht, const char *str, si IS_CONSISTENT(ht); - if (ht->u.flags & HASH_FLAG_PACKED) { - return 0; - } - h = zend_inline_hash_func(str, len); p = zend_hash_str_find_bucket(ht, str, len, h); return p ? 1 : 0; @@ -1744,6 +1713,7 @@ ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, } else { if (renumber) { ht->u.flags |= HASH_FLAG_PACKED; + ht->nTableMask = 0; ht->arData = erealloc(ht->arData, ht->nTableSize * sizeof(Bucket)); ht->arHash = (uint32_t*)&uninitialized_bucket; } else { diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index fd03050947..8f51b1e39f 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -39,6 +39,7 @@ #define HASH_FLAG_PERSISTENT (1<<0) #define HASH_FLAG_APPLY_PROTECTION (1<<1) #define HASH_FLAG_PACKED (1<<2) +#define HASH_FLAG_INITIALIZED (1<<3) #define HASH_MASK_CONSISTENCY 0x60 diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 28885db75a..faf54c556f 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -157,15 +157,6 @@ typedef struct _Bucket { } Bucket; typedef struct _HashTable { - uint32_t nTableSize; - uint32_t nTableMask; - uint32_t nNumUsed; - uint32_t nNumOfElements; - zend_long nNextFreeElement; - Bucket *arData; - uint32_t *arHash; - dtor_func_t pDestructor; - uint32_t nInternalPointer; union { struct { ZEND_ENDIAN_LOHI_3( @@ -175,6 +166,15 @@ typedef struct _HashTable { } v; uint32_t flags; } u; + uint32_t nTableSize; + uint32_t nTableMask; + uint32_t nNumUsed; + uint32_t nNumOfElements; + uint32_t nInternalPointer; + zend_long nNextFreeElement; + Bucket *arData; + uint32_t *arHash; + dtor_func_t pDestructor; } HashTable; struct _zend_array { diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 860e18a299..41d6052b7f 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -301,12 +301,12 @@ static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind) ht->nNumOfElements = source->nNumOfElements; ht->nNextFreeElement = source->nNextFreeElement; ht->pDestructor = ZVAL_PTR_DTOR; - ht->u.flags = HASH_FLAG_APPLY_PROTECTION; + ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED) | HASH_FLAG_APPLY_PROTECTION; ht->arData = NULL; ht->arHash = NULL; ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX; - if (!ht->nTableMask) { + if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) { ht->arHash = (uint32_t*)&uninitialized_bucket; return; } @@ -382,10 +382,10 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class ht->nNumOfElements = source->nNumOfElements; ht->nNextFreeElement = source->nNextFreeElement; ht->pDestructor = ZEND_FUNCTION_DTOR; - ht->u.flags = 0; + ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED); ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX; - if (!ht->nTableMask) { + if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) { ht->arHash = (uint32_t*)&uninitialized_bucket; return; } @@ -458,10 +458,10 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla ht->nNumOfElements = source->nNumOfElements; ht->nNextFreeElement = source->nNextFreeElement; ht->pDestructor = zend_destroy_property_info; - ht->u.flags = 0; + ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED); ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX; - if (!ht->nTableMask) { + if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) { ht->arHash = (uint32_t*)&uninitialized_bucket; return; } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 53811f626e..d9e8765c34 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -74,7 +74,7 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement uint idx; Bucket *p; - if (!ht->nTableMask) { + if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) { ht->arHash = (uint32_t*)&uninitialized_bucket; return; } @@ -111,7 +111,7 @@ static void zend_hash_persist_immutable(HashTable *ht) uint idx; Bucket *p; - if (!ht->nTableMask) { + if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) { ht->arHash = (uint32_t*)&uninitialized_bucket; return; } diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index f3fb7c081d..f06a871d08 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -54,7 +54,7 @@ static void zend_hash_persist_calc(HashTable *ht, void (*pPersistElement)(zval * uint idx; Bucket *p; - if (!ht->nTableMask) { + if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) { return; } if (ht->u.flags & HASH_FLAG_PACKED) { |