summaryrefslogtreecommitdiff
path: root/Zend/zend_string.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_string.c')
-rw-r--r--Zend/zend_string.c248
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
}