1
0
mirror of https://github.com/php/php-src.git synced 2026-04-02 21:52:36 +02:00

Merge branch 'PHP-5.6' of git.php.net:php-src into PHP-5.6

This commit is contained in:
Andrey Hristov
2014-03-21 14:33:44 +02:00
2 changed files with 82 additions and 183 deletions

View File

@@ -8,6 +8,7 @@ UPGRADE NOTES - PHP X.Y
c. POST data handling
d. Arginfo changes
e. tsrm_virtual_cwd.h moved to zend_virtual_cwd.h
f. empty strings are interned
2. Build system changes
a. Unix build system changes
@@ -115,6 +116,13 @@ UPGRADE NOTES - PHP X.Y
Memory allocation is now managed by emalloc/efree instead of malloc/free.
f. empty strings are interned
String created using STR_EMPTY_ALLOC() are now interned.
convert_to_string use STR_EMPTY_ALLOC() for zval when IS_NULL.
STR_FREE() shoud be prefered as efree on such strings can raise memory corruption.
========================
2. Build system changes
========================

View File

@@ -141,6 +141,51 @@ ZEND_API ulong zend_hash_func(const char *arKey, uint nKeyLength)
static const Bucket *uninitialized_bucket = NULL;
static zend_always_inline void i_zend_hash_bucket_delete(HashTable *ht, Bucket *p)
{
#ifdef ZEND_SIGNALS
TSRMLS_FETCH();
#endif
HANDLE_BLOCK_INTERRUPTIONS();
if (p->pLast) {
p->pLast->pNext = p->pNext;
} else {
ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
}
if (p->pNext) {
p->pNext->pLast = p->pLast;
}
if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext;
} else {
/* Deleting the head of the list */
ht->pListHead = p->pListNext;
}
if (p->pListNext != NULL) {
p->pListNext->pListLast = p->pListLast;
} else {
/* Deleting the tail of the list */
ht->pListTail = p->pListLast;
}
if (ht->pInternalPointer == p) {
ht->pInternalPointer = p->pListNext;
}
ht->nNumOfElements--;
if (ht->pDestructor) {
ht->pDestructor(p->pData);
}
if (p->pData != &p->pDataPtr) {
pefree(p->pData, ht->persistent);
}
pefree(p, ht->persistent);
HANDLE_UNBLOCK_INTERRUPTIONS();
}
static void zend_hash_bucket_delete(HashTable *ht, Bucket *p) {
i_zend_hash_bucket_delete(ht, p);
}
ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
{
uint i = 3;
@@ -358,9 +403,6 @@ ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void
}
UPDATE_DATA(ht, p, pData, nDataSize);
HANDLE_UNBLOCK_INTERRUPTIONS();
if ((long)h >= (long)ht->nNextFreeElement) {
ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX;
}
if (pDest) {
*pDest = p->pData;
}
@@ -438,9 +480,6 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint n
{
uint nIndex;
Bucket *p;
#ifdef ZEND_SIGNALS
TSRMLS_FETCH();
#endif
IS_CONSISTENT(ht);
@@ -455,38 +494,7 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint n
&& (p->nKeyLength == nKeyLength)
&& ((p->nKeyLength == 0) /* Numeric index (short circuits the memcmp() check) */
|| !memcmp(p->arKey, arKey, nKeyLength))) { /* String index */
HANDLE_BLOCK_INTERRUPTIONS();
if (p == ht->arBuckets[nIndex]) {
ht->arBuckets[nIndex] = p->pNext;
} else {
p->pLast->pNext = p->pNext;
}
if (p->pNext) {
p->pNext->pLast = p->pLast;
}
if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext;
} else {
/* Deleting the head of the list */
ht->pListHead = p->pListNext;
}
if (p->pListNext != NULL) {
p->pListNext->pListLast = p->pListLast;
} else {
ht->pListTail = p->pListLast;
}
if (ht->pInternalPointer == p) {
ht->pInternalPointer = p->pListNext;
}
ht->nNumOfElements--;
if (ht->pDestructor) {
ht->pDestructor(p->pData);
}
if (p->pData != &p->pDataPtr) {
pefree(p->pData, ht->persistent);
}
pefree(p, ht->persistent);
HANDLE_UNBLOCK_INTERRUPTIONS();
i_zend_hash_bucket_delete(ht, p);
return SUCCESS;
}
p = p->pNext;
@@ -553,73 +561,14 @@ ZEND_API void zend_hash_clean(HashTable *ht)
}
}
/* This function is used by the various apply() functions.
* It deletes the passed bucket, and returns the address of the
* next bucket. The hash *may* be altered during that time, the
* returned value will still be valid.
*/
static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
{
Bucket *retval;
#ifdef ZEND_SIGNALS
TSRMLS_FETCH();
#endif
HANDLE_BLOCK_INTERRUPTIONS();
if (p->pLast) {
p->pLast->pNext = p->pNext;
} else {
uint nIndex;
nIndex = p->h & ht->nTableMask;
ht->arBuckets[nIndex] = p->pNext;
}
if (p->pNext) {
p->pNext->pLast = p->pLast;
} else {
/* Nothing to do as this list doesn't have a tail */
}
if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext;
} else {
/* Deleting the head of the list */
ht->pListHead = p->pListNext;
}
if (p->pListNext != NULL) {
p->pListNext->pListLast = p->pListLast;
} else {
ht->pListTail = p->pListLast;
}
if (ht->pInternalPointer == p) {
ht->pInternalPointer = p->pListNext;
}
ht->nNumOfElements--;
HANDLE_UNBLOCK_INTERRUPTIONS();
if (ht->pDestructor) {
ht->pDestructor(p->pData);
}
if (p->pData != &p->pDataPtr) {
pefree(p->pData, ht->persistent);
}
retval = p->pListNext;
pefree(p, ht->persistent);
return retval;
}
ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
{
Bucket *p;
IS_CONSISTENT(ht);
p = ht->pListHead;
while (p != NULL) {
p = zend_hash_apply_deleter(ht, p);
while (ht->pListHead != NULL) {
zend_hash_bucket_delete(ht, ht->pListHead);
}
if (ht->nTableMask) {
pefree(ht->arBuckets, ht->persistent);
}
@@ -629,14 +578,10 @@ ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
{
Bucket *p;
IS_CONSISTENT(ht);
p = ht->pListTail;
while (p != NULL) {
zend_hash_apply_deleter(ht, p);
p = ht->pListTail;
while (ht->pListTail != NULL) {
zend_hash_bucket_delete(ht, ht->pListTail);
}
if (ht->nTableMask) {
@@ -665,12 +610,13 @@ ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
p = ht->pListHead;
while (p != NULL) {
int result = apply_func(p->pData TSRMLS_CC);
Bucket *p_next = p->pListNext;
if (result & ZEND_HASH_APPLY_REMOVE) {
p = zend_hash_apply_deleter(ht, p);
} else {
p = p->pListNext;
zend_hash_bucket_delete(ht, p);
}
p = p_next;
if (result & ZEND_HASH_APPLY_STOP) {
break;
}
@@ -690,11 +636,12 @@ ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t appl
while (p != NULL) {
int result = apply_func(p->pData, argument TSRMLS_CC);
Bucket *p_next = p->pListNext;
if (result & ZEND_HASH_APPLY_REMOVE) {
p = zend_hash_apply_deleter(ht, p);
} else {
p = p->pListNext;
zend_hash_bucket_delete(ht, p);
}
p = p_next;
if (result & ZEND_HASH_APPLY_STOP) {
break;
}
@@ -722,11 +669,12 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func
hash_key.h = p->h;
result = apply_func(p->pData TSRMLS_CC, num_args, args, &hash_key);
Bucket *p_next = p->pListNext;
if (result & ZEND_HASH_APPLY_REMOVE) {
p = zend_hash_apply_deleter(ht, p);
} else {
p = p->pListNext;
zend_hash_bucket_delete(ht, p);
}
p = p_next;
if (result & ZEND_HASH_APPLY_STOP) {
va_end(args);
break;
@@ -740,7 +688,7 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func
ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
{
Bucket *p, *q;
Bucket *p;
IS_CONSISTENT(ht);
@@ -749,11 +697,12 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR
while (p != NULL) {
int result = apply_func(p->pData TSRMLS_CC);
q = p;
p = p->pListLast;
Bucket *p_last = p->pListLast;
if (result & ZEND_HASH_APPLY_REMOVE) {
zend_hash_apply_deleter(ht, q);
zend_hash_bucket_delete(ht, p);
}
p = p_last;
if (result & ZEND_HASH_APPLY_STOP) {
break;
}
@@ -1223,8 +1172,6 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
return FAILURE;
}
HANDLE_BLOCK_INTERRUPTIONS();
if (q) {
if (mode != HASH_UPDATE_KEY_ANYWAY) {
Bucket *r = p->pListLast;
@@ -1239,73 +1186,17 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
}
if (mode & found) {
/* delete current bucket */
if (p == ht->arBuckets[p->h & ht->nTableMask]) {
ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
} else {
p->pLast->pNext = p->pNext;
}
if (p->pNext) {
p->pNext->pLast = p->pLast;
}
if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext;
} else {
/* Deleting the head of the list */
ht->pListHead = p->pListNext;
}
if (p->pListNext != NULL) {
p->pListNext->pListLast = p->pListLast;
} else {
ht->pListTail = p->pListLast;
}
if (ht->pInternalPointer == p) {
ht->pInternalPointer = p->pListNext;
}
ht->nNumOfElements--;
if (ht->pDestructor) {
ht->pDestructor(p->pData);
}
if (p->pData != &p->pDataPtr) {
pefree(p->pData, ht->persistent);
}
pefree(p, ht->persistent);
HANDLE_UNBLOCK_INTERRUPTIONS();
zend_hash_bucket_delete(ht, p);
return FAILURE;
}
}
/* delete another bucket with the same key */
if (q == ht->arBuckets[q->h & ht->nTableMask]) {
ht->arBuckets[q->h & ht->nTableMask] = q->pNext;
} else {
q->pLast->pNext = q->pNext;
}
if (q->pNext) {
q->pNext->pLast = q->pLast;
}
if (q->pListLast != NULL) {
q->pListLast->pListNext = q->pListNext;
} else {
/* Deleting the head of the list */
ht->pListHead = q->pListNext;
}
if (q->pListNext != NULL) {
q->pListNext->pListLast = q->pListLast;
} else {
ht->pListTail = q->pListLast;
}
if (ht->pInternalPointer == q) {
ht->pInternalPointer = q->pListNext;
}
ht->nNumOfElements--;
if (ht->pDestructor) {
ht->pDestructor(q->pData);
}
if (q->pData != &q->pDataPtr) {
pefree(q->pData, ht->persistent);
}
pefree(q, ht->persistent);
zend_hash_bucket_delete(ht, q);
}
HANDLE_BLOCK_INTERRUPTIONS();
if (p->pNext) {
p->pNext->pLast = p->pLast;
}