root/Zend/zend_string.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zend_interned_strings_init
  2. zend_interned_strings_dtor
  3. zend_new_interned_string_int
  4. zend_interned_strings_snapshot_int
  5. zend_interned_strings_restore_int

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend Engine                                                          |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 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     /* interned empty string */
  65         CG(interned_empty_string) = zend_new_interned_string_int("", sizeof(""), 0 TSRMLS_CC);
  66 #endif
  67 
  68         zend_new_interned_string = zend_new_interned_string_int;
  69         zend_interned_strings_snapshot = zend_interned_strings_snapshot_int;
  70         zend_interned_strings_restore = zend_interned_strings_restore_int;
  71 }
  72 
  73 void zend_interned_strings_dtor(TSRMLS_D)
  74 {
  75 #ifndef ZTS
  76 #if ZEND_DEBUG_INTERNED_STRINGS
  77         mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ);
  78 #endif
  79         free(CG(interned_strings).arBuckets);
  80         free(CG(interned_strings_start));
  81 #endif
  82 }
  83 
  84 static const char *zend_new_interned_string_int(const char *arKey, int nKeyLength, int free_src TSRMLS_DC)
  85 {
  86 #ifndef ZTS
  87         ulong h;
  88         uint nIndex;
  89         Bucket *p;
  90 
  91         if (IS_INTERNED(arKey)) {
  92                 return arKey;
  93         }
  94 
  95         h = zend_inline_hash_func(arKey, nKeyLength);
  96         nIndex = h & CG(interned_strings).nTableMask;
  97         p = CG(interned_strings).arBuckets[nIndex];
  98         while (p != NULL) {
  99                 if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
 100                         if (!memcmp(p->arKey, arKey, nKeyLength)) {
 101                                 if (free_src) {
 102                                         efree((void *)arKey);
 103                                 }
 104                                 return p->arKey;
 105                         }
 106                 }
 107                 p = p->pNext;
 108         }
 109         
 110         if (CG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength) >=
 111             CG(interned_strings_end)) {
 112             /* no memory */
 113                 return arKey;
 114         }
 115 
 116         p = (Bucket *) CG(interned_strings_top);
 117         CG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength);
 118 
 119 #if ZEND_DEBUG_INTERNED_STRINGS
 120         mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ | PROT_WRITE);
 121 #endif
 122         
 123         p->arKey = (char*)(p+1);
 124         memcpy((char*)p->arKey, arKey, nKeyLength);
 125         if (free_src) {
 126                 efree((void *)arKey);
 127         }
 128         p->nKeyLength = nKeyLength;
 129         p->h = h;
 130         p->pData = &p->pDataPtr;
 131         p->pDataPtr = p;
 132         
 133         p->pNext = CG(interned_strings).arBuckets[nIndex];
 134         p->pLast = NULL;
 135         if (p->pNext) {
 136                 p->pNext->pLast = p;
 137         }
 138 
 139         HANDLE_BLOCK_INTERRUPTIONS();
 140         
 141         p->pListLast = CG(interned_strings).pListTail;
 142         CG(interned_strings).pListTail = p;
 143         p->pListNext = NULL;
 144         if (p->pListLast != NULL) {
 145                 p->pListLast->pListNext = p;
 146         }
 147         if (!CG(interned_strings).pListHead) {
 148                 CG(interned_strings).pListHead = p;
 149         }
 150 
 151         CG(interned_strings).arBuckets[nIndex] = p;
 152 
 153         HANDLE_UNBLOCK_INTERRUPTIONS();
 154 
 155         CG(interned_strings).nNumOfElements++;
 156 
 157         if (CG(interned_strings).nNumOfElements > CG(interned_strings).nTableSize) {
 158                 if ((CG(interned_strings).nTableSize << 1) > 0) {       /* Let's double the table size */
 159                         Bucket **t = (Bucket **) perealloc_recoverable(CG(interned_strings).arBuckets, (CG(interned_strings).nTableSize << 1) * sizeof(Bucket *), CG(interned_strings).persistent);
 160 
 161                         if (t) {
 162                                 HANDLE_BLOCK_INTERRUPTIONS();
 163                                 CG(interned_strings).arBuckets = t;
 164                                 CG(interned_strings).nTableSize = (CG(interned_strings).nTableSize << 1);
 165                                 CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
 166                                 zend_hash_rehash(&CG(interned_strings));
 167                                 HANDLE_UNBLOCK_INTERRUPTIONS();
 168                         }
 169                 }
 170         }
 171 
 172 #if ZEND_DEBUG_INTERNED_STRINGS
 173         mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
 174 #endif
 175 
 176         return p->arKey;
 177 #else
 178         return arKey;
 179 #endif
 180 }
 181 
 182 static void zend_interned_strings_snapshot_int(TSRMLS_D)
 183 {
 184         CG(interned_strings_snapshot_top) = CG(interned_strings_top);
 185 }
 186 
 187 static void zend_interned_strings_restore_int(TSRMLS_D)
 188 {
 189 #ifndef ZTS
 190         Bucket *p;
 191         int i;
 192 #endif
 193 
 194         CG(interned_strings_top) = CG(interned_strings_snapshot_top);
 195 
 196 #ifndef ZTS
 197 #if ZEND_DEBUG_INTERNED_STRINGS
 198         mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ);
 199 #endif
 200 
 201         for (i = 0; i < CG(interned_strings).nTableSize; i++) {
 202                 p = CG(interned_strings).arBuckets[i];
 203                 while (p && p->arKey > CG(interned_strings_top)) {
 204                         CG(interned_strings).nNumOfElements--;
 205                         if (p->pListLast != NULL) {
 206                                 p->pListLast->pListNext = p->pListNext;
 207                         } else { 
 208                                 CG(interned_strings).pListHead = p->pListNext;
 209                         }
 210                         if (p->pListNext != NULL) {
 211                                 p->pListNext->pListLast = p->pListLast;
 212                         } else {
 213                                 CG(interned_strings).pListTail = p->pListLast;
 214                         }
 215                         p = p->pNext;
 216                 }
 217                 if (p) {
 218                         p->pLast = NULL;
 219                 }
 220                 CG(interned_strings).arBuckets[i] = p;
 221         }
 222 
 223 #if ZEND_DEBUG_INTERNED_STRINGS
 224         mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
 225 #endif
 226 #endif
 227 }
 228 
 229 /*
 230  * Local variables:
 231  * tab-width: 4
 232  * c-basic-offset: 4
 233  * indent-tabs-mode: t
 234  * End:
 235  */

/* [<][>][^][v][top][bottom][index][help] */