From 0da7b6d3b33c9286b53d119ffc840e468bf029c4 Mon Sep 17 00:00:00 2001 From: Moriyoshi Koizumi Date: Mon, 22 May 2017 13:43:07 +0000 Subject: [PATCH] Revert changes to zend_array structures. --- Zend/zend_hash.c | 149 ++++++++++------------ Zend/zend_hash.h | 2 + Zend/zend_types.h | 27 ++-- ext/opcache/ZendAccelerator.c | 5 +- ext/opcache/zend_accelerator_util_funcs.c | 9 +- ext/opcache/zend_file_cache.c | 6 +- ext/opcache/zend_persist.c | 73 +++++++---- sapi/phpdbg/phpdbg_watch.c | 2 +- 8 files changed, 140 insertions(+), 133 deletions(-) diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 5c629e29eeaec..ec8634123b564 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -132,24 +132,24 @@ static zend_always_inline void zend_hash_real_init_ex(HashTable *ht, int packed) HT_ASSERT_RC1(ht); ZEND_ASSERT(!((ht)->u.flags & HASH_FLAG_INITIALIZED)); if (packed) { - HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT)); + HT_SET_HASH_ADDR(ht, uninitialized_bucket); + ht->arData = pemalloc(HT_DATA_SIZE(ht->nTableSize), (ht)->u.flags & HASH_FLAG_PERSISTENT); (ht)->u.flags |= HASH_FLAG_INITIALIZED | HASH_FLAG_PACKED; - HT_HASH_RESET_PACKED(ht); } else { + ht->arHash = (uint32_t *)((char *)pemalloc(HT_HASH_SIZE(-ht->nTableSize), (ht)->u.flags & HASH_FLAG_PERSISTENT) + HT_HASH_SIZE(-ht->nTableSize)); + ht->arData = pemalloc(HT_DATA_SIZE(ht->nTableSize), (ht)->u.flags & HASH_FLAG_PERSISTENT); (ht)->nTableMask = -(ht)->nTableSize; - HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT)); (ht)->u.flags |= HASH_FLAG_INITIALIZED; if (EXPECTED(ht->nTableMask == (uint32_t)-8)) { - Bucket *arData = ht->arData; - - HT_HASH_EX(arData, -8) = -1; - HT_HASH_EX(arData, -7) = -1; - HT_HASH_EX(arData, -6) = -1; - HT_HASH_EX(arData, -5) = -1; - HT_HASH_EX(arData, -4) = -1; - HT_HASH_EX(arData, -3) = -1; - HT_HASH_EX(arData, -2) = -1; - HT_HASH_EX(arData, -1) = -1; + uint32_t *arHash = ht->arHash; + HT_HASH_EX(arHash, -8) = -1; + HT_HASH_EX(arHash, -7) = -1; + HT_HASH_EX(arHash, -6) = -1; + HT_HASH_EX(arHash, -5) = -1; + HT_HASH_EX(arHash, -4) = -1; + HT_HASH_EX(arHash, -3) = -1; + HT_HASH_EX(arHash, -2) = -1; + HT_HASH_EX(arHash, -1) = -1; } else { HT_HASH_RESET(ht); } @@ -167,7 +167,7 @@ static zend_always_inline void zend_hash_check_init(HashTable *ht, int packed) #define CHECK_INIT(ht, packed) \ zend_hash_check_init(ht, packed) -static const uint32_t uninitialized_bucket[-HT_MIN_MASK] = +const uint32_t uninitialized_bucket[-HT_MIN_MASK] = {HT_INVALID_IDX, HT_INVALID_IDX}; ZEND_API void ZEND_FASTCALL _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC) @@ -176,7 +176,8 @@ ZEND_API void ZEND_FASTCALL _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_ GC_TYPE_INFO(ht) = IS_ARRAY | (persistent ? 0 : (GC_COLLECTABLE << GC_FLAGS_SHIFT)); ht->u.flags = (persistent ? HASH_FLAG_PERSISTENT : 0) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS; ht->nTableMask = HT_MIN_MASK; - HT_SET_DATA_ADDR(ht, &uninitialized_bucket); + HT_SET_HASH_ADDR(ht, uninitialized_bucket); + ht->arData = NULL; ht->nNumUsed = 0; ht->nNumOfElements = 0; ht->nInternalPointer = HT_INVALID_IDX; @@ -192,7 +193,7 @@ static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht) zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket)); } ht->nTableSize += ht->nTableSize; - HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE(ht), HT_USED_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT)); + ht->arData = perealloc2(ht->arData, HT_DATA_SIZE(ht->nTableSize), HT_USED_DATA_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT); } ZEND_API void ZEND_FASTCALL zend_hash_real_init(HashTable *ht, zend_bool packed) @@ -205,32 +206,22 @@ ZEND_API void ZEND_FASTCALL zend_hash_real_init(HashTable *ht, zend_bool packed) ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht) { - void *new_data, *old_data = HT_GET_DATA_ADDR(ht); - Bucket *old_buckets = ht->arData; - HT_ASSERT_RC1(ht); ht->u.flags &= ~HASH_FLAG_PACKED; - new_data = pemalloc(HT_SIZE_EX(ht->nTableSize, -ht->nTableSize), (ht)->u.flags & HASH_FLAG_PERSISTENT); + ht->arHash = (uint32_t *)((char *)pemalloc(HT_HASH_SIZE(-ht->nTableSize), (ht)->u.flags & HASH_FLAG_PERSISTENT) + HT_HASH_SIZE(-ht->nTableSize)); ht->nTableMask = -ht->nTableSize; - HT_SET_DATA_ADDR(ht, new_data); - memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed); - pefree(old_data, (ht)->u.flags & HASH_FLAG_PERSISTENT); zend_hash_rehash(ht); } ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht) { - void *new_data, *old_data = HT_GET_DATA_ADDR(ht); - Bucket *old_buckets = ht->arData; - HT_ASSERT_RC1(ht); - new_data = pemalloc(HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), (ht)->u.flags & HASH_FLAG_PERSISTENT); ht->u.flags |= HASH_FLAG_PACKED | HASH_FLAG_STATIC_KEYS; ht->nTableMask = HT_MIN_MASK; - HT_SET_DATA_ADDR(ht, new_data); - HT_HASH_RESET_PACKED(ht); - memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed); - pefree(old_data, (ht)->u.flags & HASH_FLAG_PERSISTENT); + if (HT_GET_HASH_ADDR(ht) != uninitialized_bucket) { + pefree(HT_GET_HASH_ADDR(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT); + } + HT_SET_HASH_ADDR(ht, uninitialized_bucket); } ZEND_API void ZEND_FASTCALL _zend_hash_init_ex(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC) @@ -255,20 +246,16 @@ ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, zend ZEND_ASSERT(ht->u.flags & HASH_FLAG_PACKED); if (nSize > ht->nTableSize) { ht->nTableSize = zend_hash_check_size(nSize); - HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE(ht), HT_USED_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT)); + ht->arData = perealloc2(ht->arData, HT_DATA_SIZE(ht->nTableSize), HT_USED_DATA_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT); } } else { ZEND_ASSERT(!(ht->u.flags & HASH_FLAG_PACKED)); if (nSize > ht->nTableSize) { - void *new_data, *old_data = HT_GET_DATA_ADDR(ht); - Bucket *old_buckets = ht->arData; nSize = zend_hash_check_size(nSize); - new_data = pemalloc(HT_SIZE_EX(nSize, -nSize), ht->u.flags & HASH_FLAG_PERSISTENT); + ht->arHash = (uint32_t *)((char *)perealloc(HT_GET_HASH_ADDR(ht) == uninitialized_bucket ? NULL: HT_GET_HASH_ADDR(ht), HT_HASH_SIZE(-nSize), ht->u.flags & HASH_FLAG_PERSISTENT) + HT_HASH_SIZE(-nSize)); + ht->arData = perealloc2(ht->arData, HT_DATA_SIZE(nSize), HT_USED_DATA_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT); ht->nTableSize = nSize; - ht->nTableMask = -ht->nTableSize; - HT_SET_DATA_ADDR(ht, new_data); - memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed); - pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT); + ht->nTableMask = -nSize; zend_hash_rehash(ht); } } @@ -475,14 +462,13 @@ static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, zen zend_ulong h; uint32_t nIndex; uint32_t idx; - Bucket *p, *arData; + Bucket *p; h = zend_string_hash_val(key); - arData = ht->arData; nIndex = h | ht->nTableMask; - idx = HT_HASH_EX(arData, nIndex); + idx = HT_HASH_EX(ht->arHash, nIndex); while (EXPECTED(idx != HT_INVALID_IDX)) { - p = HT_HASH_TO_BUCKET_EX(arData, idx); + p = HT_HASH_TO_BUCKET_EX(ht->arData, idx); if (EXPECTED(p->key == key)) { /* check for the same interned string */ return p; } else if (EXPECTED(p->h == h) && @@ -500,14 +486,13 @@ static zend_always_inline Bucket *zend_hash_str_find_bucket(const HashTable *ht, { uint32_t nIndex; uint32_t idx; - Bucket *p, *arData; + Bucket *p; - arData = ht->arData; nIndex = h | ht->nTableMask; - idx = HT_HASH_EX(arData, nIndex); + idx = HT_HASH_EX(ht->arHash, nIndex); while (idx != HT_INVALID_IDX) { ZEND_ASSERT(idx < HT_IDX_TO_HASH(ht->nTableSize)); - p = HT_HASH_TO_BUCKET_EX(arData, idx); + p = HT_HASH_TO_BUCKET_EX(ht->arData, idx); if ((p->h == h) && p->key && (ZSTR_LEN(p->key) == len) @@ -523,14 +508,13 @@ static zend_always_inline Bucket *zend_hash_index_find_bucket(const HashTable *h { uint32_t nIndex; uint32_t idx; - Bucket *p, *arData; + Bucket *p; - arData = ht->arData; nIndex = h | ht->nTableMask; - idx = HT_HASH_EX(arData, nIndex); + idx = HT_HASH_EX(ht->arHash, nIndex); while (idx != HT_INVALID_IDX) { ZEND_ASSERT(idx < HT_IDX_TO_HASH(ht->nTableSize)); - p = HT_HASH_TO_BUCKET_EX(arData, idx); + p = HT_HASH_TO_BUCKET_EX(ht->arData, idx); if (p->h == h && !p->key) { return p; } @@ -598,7 +582,7 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s ht->nInternalPointer = idx; } zend_hash_iterators_update(ht, HT_INVALID_IDX, idx); - p = ht->arData + idx; + p = HT_HASH_TO_BUCKET_EX(ht->arData, idx); p->key = key; if (!ZSTR_IS_INTERNED(key)) { zend_string_addref(key); @@ -854,16 +838,11 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht) if (ht->nNumUsed > ht->nNumOfElements + (ht->nNumOfElements >> 5)) { /* additional term is there to amortize the cost of compaction */ zend_hash_rehash(ht); } else if (ht->nTableSize < HT_MAX_SIZE) { /* Let's double the table size */ - void *new_data, *old_data = HT_GET_DATA_ADDR(ht); uint32_t nSize = ht->nTableSize + ht->nTableSize; - Bucket *old_buckets = ht->arData; - - new_data = pemalloc(HT_SIZE_EX(nSize, -nSize), ht->u.flags & HASH_FLAG_PERSISTENT); + ht->arHash = (uint32_t *)((char *)perealloc(HT_GET_HASH_ADDR(ht) == uninitialized_bucket ? NULL: HT_GET_HASH_ADDR(ht), HT_HASH_SIZE(-nSize), ht->u.flags & HASH_FLAG_PERSISTENT) + HT_HASH_SIZE(-nSize)); + ht->arData = perealloc2(ht->arData, HT_DATA_SIZE(nSize), HT_USED_DATA_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT); ht->nTableSize = nSize; - ht->nTableMask = -ht->nTableSize; - HT_SET_DATA_ADDR(ht, new_data); - memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed); - pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT); + ht->nTableMask = -nSize; zend_hash_rehash(ht); } else { zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket)); @@ -1275,7 +1254,10 @@ ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht) } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) { return; } - pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT); + if (HT_GET_HASH_ADDR(ht) != uninitialized_bucket) { + pefree(HT_GET_HASH_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT); + } + pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT); } ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht) @@ -1326,7 +1308,10 @@ ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht) } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) { goto free_ht; } - efree(HT_GET_DATA_ADDR(ht)); + if (HT_GET_HASH_ADDR(ht) != uninitialized_bucket) { + efree(HT_GET_HASH_ADDR(ht)); + } + efree(ht->arData); free_ht: FREE_HASHTABLE(ht); } @@ -1453,7 +1438,10 @@ ZEND_API void ZEND_FASTCALL zend_hash_graceful_destroy(HashTable *ht) _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p); } if (ht->u.flags & HASH_FLAG_INITIALIZED) { - pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT); + if (HT_GET_HASH_ADDR(ht) != uninitialized_bucket) { + pefree(HT_GET_HASH_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT); + } + pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT); } SET_INCONSISTENT(HT_DESTROYED); @@ -1477,7 +1465,10 @@ ZEND_API void ZEND_FASTCALL zend_hash_graceful_reverse_destroy(HashTable *ht) } if (ht->u.flags & HASH_FLAG_INITIALIZED) { - pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT); + if (HT_GET_HASH_ADDR(ht) != uninitialized_bucket) { + pefree(HT_GET_HASH_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT); + } + pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT); } SET_INCONSISTENT(HT_DESTROYED); @@ -1774,16 +1765,19 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source) target->nNumOfElements = 0; target->nNextFreeElement = 0; target->nInternalPointer = HT_INVALID_IDX; - HT_SET_DATA_ADDR(target, &uninitialized_bucket); + HT_SET_HASH_ADDR(target, uninitialized_bucket); + target->arData = NULL; } else if (GC_FLAGS(source) & IS_ARRAY_IMMUTABLE) { target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION; target->nTableMask = source->nTableMask; target->nNumUsed = source->nNumUsed; target->nNumOfElements = source->nNumOfElements; target->nNextFreeElement = source->nNextFreeElement; - HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target))); + HT_SET_HASH_ADDR(target, emalloc(HT_HASH_SIZE(target->nTableMask))); + target->arData = emalloc(HT_DATA_SIZE(target->nTableSize)); target->nInternalPointer = source->nInternalPointer; - memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_USED_SIZE(source)); + memcpy(HT_GET_HASH_ADDR(target), HT_GET_HASH_ADDR(source), HT_HASH_SIZE(source->nTableMask)); + memcpy(target->arData, source->arData, HT_USED_DATA_SIZE(source)); if (target->nNumOfElements > 0 && target->nInternalPointer == HT_INVALID_IDX) { idx = 0; @@ -1794,13 +1788,13 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source) } } else if (source->u.flags & HASH_FLAG_PACKED) { target->u.flags = (source->u.flags & ~(HASH_FLAG_PERSISTENT|ZEND_HASH_APPLY_COUNT_MASK)) | HASH_FLAG_APPLY_PROTECTION; - target->nTableMask = source->nTableMask; + target->nTableMask = HT_MIN_MASK; target->nNumUsed = source->nNumUsed; target->nNumOfElements = source->nNumOfElements; target->nNextFreeElement = source->nNextFreeElement; - HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target))); + HT_SET_HASH_ADDR(target, uninitialized_bucket); + target->arData = emalloc(HT_DATA_SIZE(target->nTableSize)); target->nInternalPointer = source->nInternalPointer; - HT_HASH_RESET_PACKED(target); if (HT_IS_WITHOUT_HOLES(target)) { zend_array_dup_packed_elements(source, target, 0); @@ -1821,7 +1815,8 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source) target->nNextFreeElement = source->nNextFreeElement; target->nInternalPointer = source->nInternalPointer; - HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target))); + HT_SET_HASH_ADDR(target, emalloc(HT_HASH_SIZE(target->nTableMask))); + target->arData = emalloc(HT_DATA_SIZE(target->nTableSize)); HT_HASH_RESET(target); if (HT_HAS_STATIC_KEYS_ONLY(target)) { @@ -2292,16 +2287,12 @@ ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, co } } else { if (renumber) { - void *new_data, *old_data = HT_GET_DATA_ADDR(ht); - Bucket *old_buckets = ht->arData; - - new_data = pemalloc(HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), (ht->u.flags & HASH_FLAG_PERSISTENT)); ht->u.flags |= HASH_FLAG_PACKED | HASH_FLAG_STATIC_KEYS; ht->nTableMask = HT_MIN_MASK; - HT_SET_DATA_ADDR(ht, new_data); - memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed); - pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT & HASH_FLAG_PERSISTENT); - HT_HASH_RESET_PACKED(ht); + if (HT_GET_HASH_ADDR(ht) != uninitialized_bucket) { + pefree(HT_GET_HASH_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT); + } + HT_SET_HASH_ADDR(ht, uninitialized_bucket); } else { zend_hash_rehash(ht); } diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 638fbe27fc02d..87adfaa5fd6fe 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -67,6 +67,8 @@ typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht, zval *source_dat BEGIN_EXTERN_C() +ZEND_API const uint32_t uninitialized_bucket[-HT_MIN_MASK]; + /* startup/shutdown */ ZEND_API void ZEND_FASTCALL _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC); ZEND_API void ZEND_FASTCALL _zend_hash_init_ex(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC); diff --git a/Zend/zend_types.h b/Zend/zend_types.h index caa68e22e84e2..805512d4c4463 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -246,6 +246,7 @@ struct _zend_array { uint32_t flags; } u; uint32_t nTableMask; + uint32_t *arHash; Bucket *arData; uint32_t nNumUsed; uint32_t nNumOfElements; @@ -298,32 +299,26 @@ struct _zend_array { #define HT_HASH_EX(data, idx) \ ((uint32_t*)(data))[(int32_t)(idx)] #define HT_HASH(ht, idx) \ - HT_HASH_EX((ht)->arData, idx) + HT_HASH_EX((ht)->arHash, idx) #define HT_HASH_SIZE(nTableMask) \ (((size_t)(uint32_t)-(int32_t)(nTableMask)) * sizeof(uint32_t)) #define HT_DATA_SIZE(nTableSize) \ ((size_t)(nTableSize) * sizeof(Bucket)) -#define HT_SIZE_EX(nTableSize, nTableMask) \ - (HT_DATA_SIZE((nTableSize)) + HT_HASH_SIZE((nTableMask))) -#define HT_SIZE(ht) \ - HT_SIZE_EX((ht)->nTableSize, (ht)->nTableMask) -#define HT_USED_SIZE(ht) \ - (HT_HASH_SIZE((ht)->nTableMask) + ((size_t)(ht)->nNumUsed * sizeof(Bucket))) +#define HT_USED_DATA_SIZE(ht) \ + (((size_t)(ht)->nNumUsed * sizeof(Bucket))) #define HT_HASH_RESET(ht) \ - memset(&HT_HASH(ht, (ht)->nTableMask), HT_INVALID_IDX, HT_HASH_SIZE((ht)->nTableMask)) -#define HT_HASH_RESET_PACKED(ht) do { \ - HT_HASH(ht, -2) = HT_INVALID_IDX; \ - HT_HASH(ht, -1) = HT_INVALID_IDX; \ - } while (0) + if (HT_GET_HASH_ADDR(ht) != uninitialized_bucket) \ + memset(HT_GET_HASH_ADDR(ht), HT_INVALID_IDX, HT_HASH_SIZE((ht)->nTableMask)) #define HT_HASH_TO_BUCKET(ht, idx) \ HT_HASH_TO_BUCKET_EX((ht)->arData, idx) -#define HT_SET_DATA_ADDR(ht, ptr) do { \ - (ht)->arData = (Bucket*)(((char*)(ptr)) + HT_HASH_SIZE((ht)->nTableMask)); \ +#define HT_SET_HASH_ADDR(ht, ptr) do { \ + (ht)->arHash = (uint32_t*)(((char*)(ptr)) + HT_HASH_SIZE((ht)->nTableMask)); \ } while (0) -#define HT_GET_DATA_ADDR(ht) \ - ((char*)((ht)->arData) - HT_HASH_SIZE((ht)->nTableMask)) +#define HT_GET_HASH_ADDR(ht) \ + (uint32_t *)((char*)((ht)->arHash) - HT_HASH_SIZE((ht)->nTableMask)) + typedef uint32_t HashPosition; diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 0d81b89455a66..2dfc1acd8a931 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2552,14 +2552,15 @@ static int zend_accel_init_shm(void) void *data; ZCSG(interned_strings).nTableMask = -ZCSG(interned_strings).nTableSize; - data = zend_shared_alloc(HT_SIZE(&ZCSG(interned_strings))); + data = zend_shared_alloc(HT_HASH_SIZE(ZCSG(interned_strings).nTableMask) + HT_DATA_SIZE(ZCSG(interned_strings).nTableSize)); ZCSG(interned_strings_start) = zend_shared_alloc((ZCG(accel_directives).interned_strings_buffer * 1024 * 1024)); if (!data || !ZCSG(interned_strings_start)) { zend_accel_error(ACCEL_LOG_FATAL, ACCELERATOR_PRODUCT_NAME " cannot allocate buffer for interned strings"); zend_shared_alloc_unlock(); return FAILURE; } - HT_SET_DATA_ADDR(&ZCSG(interned_strings), data); + HT_SET_HASH_ADDR(&ZCSG(interned_strings), data); + ZCSG(interned_strings).arData = data; HT_HASH_RESET(&ZCSG(interned_strings)); ZCSG(interned_strings_end) = ZCSG(interned_strings_start) + (ZCG(accel_directives).interned_strings_buffer * 1024 * 1024); ZCSG(interned_strings_top) = ZCSG(interned_strings_start); diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 930bcceaf2e2f..a74b507ac0cae 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -190,7 +190,8 @@ static void zend_hash_clone_constants(HashTable *ht, HashTable *source) } ZEND_ASSERT((source->u.flags & HASH_FLAG_PACKED) == 0); - HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht))); + HT_SET_HASH_ADDR(ht, emalloc(HT_HASH_SIZE(ht->nTableMask))); + ht->arData = emalloc(HT_DATA_SIZE(ht->nTableSize)); HT_HASH_RESET(ht); p = source->arData; @@ -241,7 +242,8 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class } ZEND_ASSERT(!(source->u.flags & HASH_FLAG_PACKED)); - HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht))); + HT_SET_HASH_ADDR(ht, emalloc(HT_HASH_SIZE(ht->nTableMask))); + ht->arData = emalloc(HT_DATA_SIZE(ht->nTableSize)); HT_HASH_RESET(ht); p = source->arData; @@ -299,7 +301,8 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla } ZEND_ASSERT(!(source->u.flags & HASH_FLAG_PACKED)); - HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht))); + HT_SET_HASH_ADDR(ht, emalloc(HT_HASH_SIZE(ht->nTableMask))); + ht->arData = emalloc(HT_DATA_SIZE(ht->nTableSize)); HT_HASH_RESET(ht); p = source->arData; diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index fb6827a9fd707..faf6f1020bd55 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -143,9 +143,6 @@ static int zend_file_cache_flock(int fd, int type) } \ } while (0) -static const uint32_t uninitialized_bucket[-HT_MIN_MASK] = - {HT_INVALID_IDX, HT_INVALID_IDX}; - typedef struct _zend_file_cache_metainfo { char magic[8]; char system_id[32]; @@ -862,7 +859,8 @@ static void zend_file_cache_unserialize_hash(HashTable *ht, ht->pDestructor = dtor; if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) { - HT_SET_DATA_ADDR(ht, &uninitialized_bucket); + HT_SET_HASH_ADDR(ht, uninitialized_bucket); + ht->arData = NULL; return; } if (IS_UNSERIALIZED(ht->arData)) { diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 30bbfe08d427c..95eb47cc07d26 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -78,32 +78,32 @@ typedef void (*zend_persist_func_t)(zval*); static void zend_persist_zval(zval *z); -static const uint32_t uninitialized_bucket[-HT_MIN_MASK] = - {HT_INVALID_IDX, HT_INVALID_IDX}; - static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement) { uint32_t idx, nIndex; Bucket *p; if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) { - HT_SET_DATA_ADDR(ht, &uninitialized_bucket); + HT_SET_HASH_ADDR(ht, uninitialized_bucket); return; } if (ht->nNumUsed == 0) { - efree(HT_GET_DATA_ADDR(ht)); + if (HT_GET_HASH_ADDR(ht) != uninitialized_bucket) { + efree(HT_GET_HASH_ADDR(ht)); + } + efree(ht->arData); ht->nTableMask = HT_MIN_MASK; - HT_SET_DATA_ADDR(ht, &uninitialized_bucket); + HT_SET_HASH_ADDR(ht, uninitialized_bucket); ht->u.flags &= ~HASH_FLAG_INITIALIZED; return; } if (ht->u.flags & HASH_FLAG_PACKED) { - void *data = HT_GET_DATA_ADDR(ht); - zend_accel_store(data, HT_USED_SIZE(ht)); - HT_SET_DATA_ADDR(ht, data); + Bucket *data = ht->arData; + zend_accel_store(data, HT_USED_DATA_SIZE(ht)); + ht->arData = data; } else if (ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 2) { /* compact table */ - void *old_data = HT_GET_DATA_ADDR(ht); + uint32_t *old_data = HT_GET_HASH_ADDR(ht); Bucket *old_buckets = ht->arData; uint32_t hash_size; @@ -117,11 +117,14 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement } ht->nTableMask = (uint32_t)(-(int32_t)hash_size); ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ - HT_SET_DATA_ADDR(ht, ZCG(mem)); + HT_SET_HASH_ADDR(ht, ZCG(mem)); + ht->arData = ZCG(mem); ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE((hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket)))); HT_HASH_RESET(ht); - memcpy(ht->arData, old_buckets, ht->nNumUsed * sizeof(Bucket)); + memcpy(HT_GET_HASH_ADDR(ht), old_data, HT_HASH_SIZE(ht->nTableMask)); + memcpy(ht->arData, old_buckets, HT_USED_DATA_SIZE(ht)); efree(old_data); + efree(old_buckets); for (idx = 0; idx < ht->nNumUsed; idx++) { p = ht->arData + idx; @@ -141,14 +144,17 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement } return; } else { - void *data = ZCG(mem); - void *old_data = HT_GET_DATA_ADDR(ht); + void *old_data = HT_GET_HASH_ADDR(ht); + Bucket *old_buckets = ht->arData; ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ - ZCG(mem) = (void*)((char*)data + ZEND_ALIGNED_SIZE(HT_USED_SIZE(ht))); - memcpy(data, old_data, HT_USED_SIZE(ht)); + ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(HT_HASH_SIZE(ht->nTableMask) + HT_USED_DATA_SIZE(ht))); + HT_SET_HASH_ADDR(ht, ZCG(mem)); + ht->arData = ZCG(mem); + memcpy(HT_GET_HASH_ADDR(ht), old_data, HT_HASH_SIZE(ht->nTableMask)); + memcpy(ht->arData, old_buckets, HT_USED_DATA_SIZE(ht)); efree(old_data); - HT_SET_DATA_ADDR(ht, data); + efree(old_buckets); } for (idx = 0; idx < ht->nNumUsed; idx++) { @@ -171,21 +177,24 @@ static void zend_hash_persist_immutable(HashTable *ht) Bucket *p; if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) { - HT_SET_DATA_ADDR(ht, &uninitialized_bucket); + HT_SET_HASH_ADDR(ht, uninitialized_bucket); return; } if (ht->nNumUsed == 0) { - efree(HT_GET_DATA_ADDR(ht)); + if (HT_GET_HASH_ADDR(ht) != uninitialized_bucket) { + efree(HT_GET_HASH_ADDR(ht)); + } + efree(ht->arData); ht->nTableMask = HT_MIN_MASK; - HT_SET_DATA_ADDR(ht, &uninitialized_bucket); + HT_SET_HASH_ADDR(ht, uninitialized_bucket); ht->u.flags &= ~HASH_FLAG_INITIALIZED; return; } if (ht->u.flags & HASH_FLAG_PACKED) { - HT_SET_DATA_ADDR(ht, zend_accel_memdup(HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht))); + ht->arData = zend_accel_memdup(ht->arData, HT_USED_DATA_SIZE(ht)); } else if (ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 2) { /* compact table */ - void *old_data = HT_GET_DATA_ADDR(ht); + uint32_t *old_data = HT_GET_HASH_ADDR(ht); Bucket *old_buckets = ht->arData; uint32_t hash_size; @@ -199,11 +208,14 @@ static void zend_hash_persist_immutable(HashTable *ht) } ht->nTableMask = (uint32_t)(-(int32_t)hash_size); ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ - HT_SET_DATA_ADDR(ht, ZCG(mem)); + HT_SET_HASH_ADDR(ht, ZCG(mem)); + ht->arData = ZCG(mem); ZCG(mem) = (void*)((char*)ZCG(mem) + (hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket))); HT_HASH_RESET(ht); - memcpy(ht->arData, old_buckets, ht->nNumUsed * sizeof(Bucket)); + memcpy(HT_GET_HASH_ADDR(ht), old_data, HT_HASH_SIZE(ht->nTableMask)); + memcpy(ht->arData, old_buckets, HT_USED_DATA_SIZE(ht)); efree(old_data); + efree(old_buckets); for (idx = 0; idx < ht->nNumUsed; idx++) { p = ht->arData + idx; @@ -223,12 +235,17 @@ static void zend_hash_persist_immutable(HashTable *ht) } return; } else { - void *data = ZCG(mem); + void *old_data = HT_GET_HASH_ADDR(ht); + Bucket *old_buckets = ht->arData; ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ - ZCG(mem) = (void*)((char*)data + ZEND_ALIGNED_SIZE(HT_USED_SIZE(ht))); - memcpy(data, HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht)); - HT_SET_DATA_ADDR(ht, data); + ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(HT_HASH_SIZE(ht->nTableMask) + HT_USED_DATA_SIZE(ht))); + HT_SET_HASH_ADDR(ht, ZCG(mem)); + ht->arData = ZCG(mem); + memcpy(HT_GET_HASH_ADDR(ht), old_data, HT_HASH_SIZE(ht->nTableMask)); + memcpy(ht->arData, old_buckets, HT_USED_DATA_SIZE(ht)); + efree(old_data); + efree(old_buckets); } for (idx = 0; idx < ht->nNumUsed; idx++) { p = ht->arData + idx; diff --git a/sapi/phpdbg/phpdbg_watch.c b/sapi/phpdbg/phpdbg_watch.c index 6267f4fadf6bb..8652222d3538f 100644 --- a/sapi/phpdbg/phpdbg_watch.c +++ b/sapi/phpdbg/phpdbg_watch.c @@ -597,7 +597,7 @@ void phpdbg_watch_parent_ht(phpdbg_watch_element *element) { zend_hash_init(&hti->watches, 0, grrrrr, ZVAL_PTR_DTOR, 0); phpdbg_btree_insert(&PHPDBG_G(watch_HashTables), (zend_ulong) hti->ht, hti); - phpdbg_set_addr_watchpoint(HT_GET_DATA_ADDR(hti->ht), HT_HASH_SIZE(hti->ht->nTableMask), &hti->hash_watch); + phpdbg_set_addr_watchpoint(hti->ht->arData, HT_DATA_SIZE(hti->ht->nTableSize), &hti->hash_watch); hti->hash_watch.type = WATCH_ON_HASHDATA; phpdbg_store_watchpoint_btree(&hti->hash_watch); phpdbg_activate_watchpoint(&hti->hash_watch);