Annotation of embedaddon/php/Zend/zend_string.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | Zend Engine                                                          |
                      4:    +----------------------------------------------------------------------+
1.1.1.2 ! misho       5:    | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
1.1       misho       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>