diff options
Diffstat (limited to 'Zend/zend_string.c')
-rw-r--r-- | Zend/zend_string.c | 248 |
1 files changed, 111 insertions, 137 deletions
diff --git a/Zend/zend_string.c b/Zend/zend_string.c index f1162f0b4c..05cd6a2d19 100644 --- a/Zend/zend_string.c +++ b/Zend/zend_string.c @@ -21,48 +21,40 @@ #include "zend.h" #include "zend_globals.h" -#ifndef ZEND_DEBUG_INTERNED_STRINGS -# define ZEND_DEBUG_INTERNED_STRINGS 0 -#endif - -#if ZEND_DEBUG_INTERNED_STRINGS -# include <sys/mman.h> -#endif - -ZEND_API const char *(*zend_new_interned_string)(const char *str, int len, int free_src TSRMLS_DC); +ZEND_API zend_string *(*zend_new_interned_string)(zend_string *str TSRMLS_DC); ZEND_API void (*zend_interned_strings_snapshot)(TSRMLS_D); ZEND_API void (*zend_interned_strings_restore)(TSRMLS_D); -static const char *zend_new_interned_string_int(const char *str, int len, int free_src TSRMLS_DC); +static zend_string *zend_new_interned_string_int(zend_string *str TSRMLS_DC); static void zend_interned_strings_snapshot_int(TSRMLS_D); static void zend_interned_strings_restore_int(TSRMLS_D); +ZEND_API zend_ulong zend_hash_func(const char *str, uint len) +{ + return zend_inline_hash_func(str, len); +} + void zend_interned_strings_init(TSRMLS_D) { #ifndef ZTS - size_t size = 1024 * 1024; - -#if ZEND_DEBUG_INTERNED_STRINGS - CG(interned_strings_start) = valloc(size); -#else - CG(interned_strings_start) = malloc(size); -#endif - - CG(interned_strings_top) = CG(interned_strings_start); - CG(interned_strings_snapshot_top) = CG(interned_strings_start); - CG(interned_strings_end) = CG(interned_strings_start) + size; + zend_string *str; zend_hash_init(&CG(interned_strings), 0, NULL, NULL, 1); CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1; - CG(interned_strings).arBuckets = (Bucket **) pecalloc(CG(interned_strings).nTableSize, sizeof(Bucket *), CG(interned_strings).persistent); - -#if ZEND_DEBUG_INTERNED_STRINGS - mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ); -#endif - - /* interned empty string */ - CG(interned_empty_string) = zend_new_interned_string_int("", sizeof(""), 0 TSRMLS_CC); + CG(interned_strings).arData = (Bucket*) pecalloc(CG(interned_strings).nTableSize, sizeof(Bucket), CG(interned_strings).flags & HASH_FLAG_PERSISTENT); + CG(interned_strings).arHash = (zend_uint*) pecalloc(CG(interned_strings).nTableSize, sizeof(zend_uint), CG(interned_strings).flags & HASH_FLAG_PERSISTENT); + memset(CG(interned_strings).arHash, INVALID_IDX, CG(interned_strings).nTableSize * sizeof(zend_uint)); + + /* interned empty string */ + str = STR_ALLOC(sizeof("")-1, 1); + str->val[0] = '\000'; + CG(empty_string) = zend_new_interned_string_int(str TSRMLS_CC); +#else + str = STR_ALLOC(sizeof("")-1, 1); + str->val[0] = '\000'; + str->gc.u.v.flags |= IS_STR_INTERNED; + CG(empty_string) = str; #endif zend_new_interned_string = zend_new_interned_string_int; @@ -73,94 +65,68 @@ void zend_interned_strings_init(TSRMLS_D) void zend_interned_strings_dtor(TSRMLS_D) { #ifndef ZTS -#if ZEND_DEBUG_INTERNED_STRINGS - mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ); -#endif - free(CG(interned_strings).arBuckets); - free(CG(interned_strings_start)); + free(CG(interned_strings).arData); + free(CG(interned_strings).arHash); #endif } -static const char *zend_new_interned_string_int(const char *arKey, int nKeyLength, int free_src TSRMLS_DC) +static zend_string *zend_new_interned_string_int(zend_string *str TSRMLS_DC) { #ifndef ZTS ulong h; uint nIndex; + uint idx; Bucket *p; - if (IS_INTERNED(arKey)) { - return arKey; + if (IS_INTERNED(str)) { + return str; } - h = zend_inline_hash_func(arKey, nKeyLength); + h = STR_HASH_VAL(str); nIndex = h & CG(interned_strings).nTableMask; - p = CG(interned_strings).arBuckets[nIndex]; - while (p != NULL) { - if ((p->h == h) && (p->nKeyLength == nKeyLength)) { - if (!memcmp(p->arKey, arKey, nKeyLength)) { - if (free_src) { - efree((void *)arKey); - } - return p->arKey; + idx = CG(interned_strings).arHash[nIndex]; + while (idx != INVALID_IDX) { + p = CG(interned_strings).arData + idx; + if ((p->h == h) && (p->key->len == str->len)) { + if (!memcmp(p->key->val, str->val, str->len)) { +//??? if (free_src) { +//??? efree((void *)arKey); +//??? } + return p->key; } } - p = p->pNext; - } - - if (CG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength) >= - CG(interned_strings_end)) { - /* no memory */ - return arKey; + idx = p->val.u.next; } - - p = (Bucket *) CG(interned_strings_top); - CG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength); - -#if ZEND_DEBUG_INTERNED_STRINGS - mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ | PROT_WRITE); -#endif - p->arKey = (char*)(p+1); - memcpy((char*)p->arKey, arKey, nKeyLength); - if (free_src) { - efree((void *)arKey); - } - p->nKeyLength = nKeyLength; - p->h = h; - p->pData = &p->pDataPtr; - p->pDataPtr = p; + str->gc.refcount = 1; +// str->gc.u.v.type = IS_INTERNED_STRING; + str->gc.u.v.flags |= IS_STR_INTERNED; + +//??? if (CG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength) >= +//??? CG(interned_strings_end)) { +//??? /* no memory */ +//??? return arKey; +//??? } + +//??? info = (zend_string_info*) CG(interned_strings_top); +//??? CG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(zend_string_info) + nKeyLength); + +//??? memcpy((char*)(info+1), arKey, nKeyLength); +//??? if (free_src) { +//??? efree((void *)arKey); +//??? } +//??? info->nKeyLength = nKeyLength; +//??? info->h = h; - p->pNext = CG(interned_strings).arBuckets[nIndex]; - p->pLast = NULL; - if (p->pNext) { - p->pNext->pLast = p; - } - - HANDLE_BLOCK_INTERRUPTIONS(); - - p->pListLast = CG(interned_strings).pListTail; - CG(interned_strings).pListTail = p; - p->pListNext = NULL; - if (p->pListLast != NULL) { - p->pListLast->pListNext = p; - } - if (!CG(interned_strings).pListHead) { - CG(interned_strings).pListHead = p; - } - - CG(interned_strings).arBuckets[nIndex] = p; - - HANDLE_UNBLOCK_INTERRUPTIONS(); - - CG(interned_strings).nNumOfElements++; - - if (CG(interned_strings).nNumOfElements > CG(interned_strings).nTableSize) { + if (CG(interned_strings).nNumUsed >= CG(interned_strings).nTableSize) { if ((CG(interned_strings).nTableSize << 1) > 0) { /* Let's double the table size */ - Bucket **t = (Bucket **) perealloc_recoverable(CG(interned_strings).arBuckets, (CG(interned_strings).nTableSize << 1) * sizeof(Bucket *), CG(interned_strings).persistent); + Bucket *d = (Bucket *) perealloc_recoverable(CG(interned_strings).arData, (CG(interned_strings).nTableSize << 1) * sizeof(Bucket), CG(interned_strings).flags & HASH_FLAG_PERSISTENT); + zend_uint *h = (zend_uint *) perealloc_recoverable(CG(interned_strings).arHash, (CG(interned_strings).nTableSize << 1) * sizeof(zend_uint), CG(interned_strings).flags & HASH_FLAG_PERSISTENT); - if (t) { + if (d && h) { HANDLE_BLOCK_INTERRUPTIONS(); - CG(interned_strings).arBuckets = t; + CG(interned_strings).arData = d; + CG(interned_strings).arHash = h; CG(interned_strings).nTableSize = (CG(interned_strings).nTableSize << 1); CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1; zend_hash_rehash(&CG(interned_strings)); @@ -169,60 +135,68 @@ static const char *zend_new_interned_string_int(const char *arKey, int nKeyLengt } } -#if ZEND_DEBUG_INTERNED_STRINGS - mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ); -#endif + HANDLE_BLOCK_INTERRUPTIONS(); + + idx = CG(interned_strings).nNumUsed++; + CG(interned_strings).nNumOfElements++; + p = CG(interned_strings).arData + idx; + p->h = h; + p->key = str; + Z_STR(p->val) = str; + Z_TYPE(p->val) = IS_STRING; + nIndex = h & CG(interned_strings).nTableMask; + p->val.u.next = CG(interned_strings).arHash[nIndex]; + CG(interned_strings).arHash[nIndex] = idx; + + HANDLE_UNBLOCK_INTERRUPTIONS(); - return p->arKey; + return str; #else - return arKey; + return str; #endif } static void zend_interned_strings_snapshot_int(TSRMLS_D) { - CG(interned_strings_snapshot_top) = CG(interned_strings_top); +#ifndef ZTS + uint idx; + Bucket *p; + + idx = CG(interned_strings).nNumUsed; + while (idx > 0) { + idx--; + p = CG(interned_strings).arData + idx; + p->key->gc.u.v.flags |= IS_STR_PERMANENT; + } +#endif } static void zend_interned_strings_restore_int(TSRMLS_D) { #ifndef ZTS + uint nIndex; + uint idx; Bucket *p; - int i; -#endif - - CG(interned_strings_top) = CG(interned_strings_snapshot_top); - -#ifndef ZTS -#if ZEND_DEBUG_INTERNED_STRINGS - mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ); -#endif - for (i = 0; i < CG(interned_strings).nTableSize; i++) { - p = CG(interned_strings).arBuckets[i]; - while (p && p->arKey > CG(interned_strings_top)) { - CG(interned_strings).nNumOfElements--; - if (p->pListLast != NULL) { - p->pListLast->pListNext = p->pListNext; - } else { - CG(interned_strings).pListHead = p->pListNext; - } - if (p->pListNext != NULL) { - p->pListNext->pListLast = p->pListLast; - } else { - CG(interned_strings).pListTail = p->pListLast; - } - p = p->pNext; - } - if (p) { - p->pLast = NULL; - } - CG(interned_strings).arBuckets[i] = p; - } - -#if ZEND_DEBUG_INTERNED_STRINGS - mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ); -#endif + idx = CG(interned_strings).nNumUsed; + while (idx > 0) { + idx--; + p = CG(interned_strings).arData + idx; + if (!(p->key->gc.u.v.flags & IS_STR_PERMANENT)) break; + CG(interned_strings).nNumUsed--; + CG(interned_strings).nNumOfElements--; + + nIndex = p->h & CG(interned_strings).nTableMask; + if (CG(interned_strings).arHash[nIndex] == idx) { + CG(interned_strings).arHash[nIndex] = p->val.u.next; + } else { + uint prev = CG(interned_strings).arHash[nIndex]; + while (CG(interned_strings).arData[prev].val.u.next != idx) { + prev = CG(interned_strings).arData[prev].val.u.next; + } + CG(interned_strings).arData[prev].val.u.next = p->val.u.next; + } + } #endif } |