Annotation of embedaddon/php/Zend/zend_string.c, revision 1.1.1.1
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | Zend Engine |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
6: +----------------------------------------------------------------------+
7: | This source file is subject to version 2.00 of the Zend license, |
8: | that is bundled with this package in the file LICENSE, and is |
9: | available through the world-wide-web at the following url: |
10: | http://www.zend.com/license/2_00.txt. |
11: | If you did not receive a copy of the Zend license and are unable to |
12: | obtain it through the world-wide-web, please send a note to |
13: | license@zend.com so we can mail you a copy immediately. |
14: +----------------------------------------------------------------------+
15: | Authors: Dmitry Stogov <dmitry@zend.com> |
16: +----------------------------------------------------------------------+
17: */
18:
19: /* $Id: $ */
20:
21: #include "zend.h"
22: #include "zend_globals.h"
23:
24: #ifndef ZEND_DEBUG_INTERNED_STRINGS
25: # define ZEND_DEBUG_INTERNED_STRINGS 0
26: #endif
27:
28: #if ZEND_DEBUG_INTERNED_STRINGS
29: # include <sys/mman.h>
30: #endif
31:
32: ZEND_API const char *(*zend_new_interned_string)(const char *str, int len, int free_src TSRMLS_DC);
33: ZEND_API void (*zend_interned_strings_snapshot)(TSRMLS_D);
34: ZEND_API void (*zend_interned_strings_restore)(TSRMLS_D);
35:
36: static const char *zend_new_interned_string_int(const char *str, int len, int free_src TSRMLS_DC);
37: static void zend_interned_strings_snapshot_int(TSRMLS_D);
38: static void zend_interned_strings_restore_int(TSRMLS_D);
39:
40: void zend_interned_strings_init(TSRMLS_D)
41: {
42: #ifndef ZTS
43: size_t size = 1024 * 1024;
44:
45: #if ZEND_DEBUG_INTERNED_STRINGS
46: CG(interned_strings_start) = valloc(size);
47: #else
48: CG(interned_strings_start) = malloc(size);
49: #endif
50:
51: CG(interned_strings_top) = CG(interned_strings_start);
52: CG(interned_strings_snapshot_top) = CG(interned_strings_start);
53: CG(interned_strings_end) = CG(interned_strings_start) + size;
54:
55: zend_hash_init(&CG(interned_strings), 0, NULL, NULL, 1);
56:
57: CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
58: CG(interned_strings).arBuckets = (Bucket **) pecalloc(CG(interned_strings).nTableSize, sizeof(Bucket *), CG(interned_strings).persistent);
59:
60: #if ZEND_DEBUG_INTERNED_STRINGS
61: mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
62: #endif
63:
64: #endif
65:
66: zend_new_interned_string = zend_new_interned_string_int;
67: zend_interned_strings_snapshot = zend_interned_strings_snapshot_int;
68: zend_interned_strings_restore = zend_interned_strings_restore_int;
69: }
70:
71: void zend_interned_strings_dtor(TSRMLS_D)
72: {
73: #ifndef ZTS
74: #if ZEND_DEBUG_INTERNED_STRINGS
75: mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ);
76: #endif
77: free(CG(interned_strings).arBuckets);
78: free(CG(interned_strings_start));
79: #endif
80: }
81:
82: static const char *zend_new_interned_string_int(const char *arKey, int nKeyLength, int free_src TSRMLS_DC)
83: {
84: #ifndef ZTS
85: ulong h;
86: uint nIndex;
87: Bucket *p;
88:
89: if (IS_INTERNED(arKey)) {
90: return arKey;
91: }
92:
93: h = zend_inline_hash_func(arKey, nKeyLength);
94: nIndex = h & CG(interned_strings).nTableMask;
95: p = CG(interned_strings).arBuckets[nIndex];
96: while (p != NULL) {
97: if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
98: if (!memcmp(p->arKey, arKey, nKeyLength)) {
99: if (free_src) {
100: efree((void *)arKey);
101: }
102: return p->arKey;
103: }
104: }
105: p = p->pNext;
106: }
107:
108: if (CG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength) >=
109: CG(interned_strings_end)) {
110: /* no memory */
111: return arKey;
112: }
113:
114: p = (Bucket *) CG(interned_strings_top);
115: CG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength);
116:
117: #if ZEND_DEBUG_INTERNED_STRINGS
118: mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ | PROT_WRITE);
119: #endif
120:
121: p->arKey = (char*)(p+1);
122: memcpy((char*)p->arKey, arKey, nKeyLength);
123: if (free_src) {
124: efree((void *)arKey);
125: }
126: p->nKeyLength = nKeyLength;
127: p->h = h;
128: p->pData = &p->pDataPtr;
129: p->pDataPtr = p;
130:
131: p->pNext = CG(interned_strings).arBuckets[nIndex];
132: p->pLast = NULL;
133: if (p->pNext) {
134: p->pNext->pLast = p;
135: }
136:
137: HANDLE_BLOCK_INTERRUPTIONS();
138:
139: p->pListLast = CG(interned_strings).pListTail;
140: CG(interned_strings).pListTail = p;
141: p->pListNext = NULL;
142: if (p->pListLast != NULL) {
143: p->pListLast->pListNext = p;
144: }
145: if (!CG(interned_strings).pListHead) {
146: CG(interned_strings).pListHead = p;
147: }
148:
149: CG(interned_strings).arBuckets[nIndex] = p;
150:
151: HANDLE_UNBLOCK_INTERRUPTIONS();
152:
153: CG(interned_strings).nNumOfElements++;
154:
155: if (CG(interned_strings).nNumOfElements > CG(interned_strings).nTableSize) {
156: if ((CG(interned_strings).nTableSize << 1) > 0) { /* Let's double the table size */
157: Bucket **t = (Bucket **) perealloc_recoverable(CG(interned_strings).arBuckets, (CG(interned_strings).nTableSize << 1) * sizeof(Bucket *), CG(interned_strings).persistent);
158:
159: if (t) {
160: HANDLE_BLOCK_INTERRUPTIONS();
161: CG(interned_strings).arBuckets = t;
162: CG(interned_strings).nTableSize = (CG(interned_strings).nTableSize << 1);
163: CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
164: zend_hash_rehash(&CG(interned_strings));
165: HANDLE_UNBLOCK_INTERRUPTIONS();
166: }
167: }
168: }
169:
170: #if ZEND_DEBUG_INTERNED_STRINGS
171: mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
172: #endif
173:
174: return p->arKey;
175: #else
176: return arKey;
177: #endif
178: }
179:
180: static void zend_interned_strings_snapshot_int(TSRMLS_D)
181: {
182: CG(interned_strings_snapshot_top) = CG(interned_strings_top);
183: }
184:
185: static void zend_interned_strings_restore_int(TSRMLS_D)
186: {
187: #ifndef ZTS
188: Bucket *p;
189: int i;
190: #endif
191:
192: CG(interned_strings_top) = CG(interned_strings_snapshot_top);
193:
194: #ifndef ZTS
195: #if ZEND_DEBUG_INTERNED_STRINGS
196: mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ);
197: #endif
198:
199: for (i = 0; i < CG(interned_strings).nTableSize; i++) {
200: p = CG(interned_strings).arBuckets[i];
201: while (p && p->arKey > CG(interned_strings_top)) {
202: CG(interned_strings).nNumOfElements--;
203: if (p->pListLast != NULL) {
204: p->pListLast->pListNext = p->pListNext;
205: } else {
206: CG(interned_strings).pListHead = p->pListNext;
207: }
208: if (p->pListNext != NULL) {
209: p->pListNext->pListLast = p->pListLast;
210: } else {
211: CG(interned_strings).pListTail = p->pListLast;
212: }
213: p = p->pNext;
214: }
215: if (p) {
216: p->pLast = NULL;
217: }
218: CG(interned_strings).arBuckets[i] = p;
219: }
220:
221: #if ZEND_DEBUG_INTERNED_STRINGS
222: mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
223: #endif
224: #endif
225: }
226:
227: /*
228: * Local variables:
229: * tab-width: 4
230: * c-basic-offset: 4
231: * indent-tabs-mode: t
232: * End:
233: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>