File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / Zend / zend_string.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:04:04 2014 UTC (10 years, 3 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | Zend Engine                                                          |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1998-2014 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: zend_string.c,v 1.1.1.3 2014/06/15 20:04:04 misho Exp $ */
   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>