Esempio n. 1
0
void zend_interned_strings_init(TSRMLS_D)
{
	zend_string *str;

#ifndef ZTS
	zend_hash_init(&CG(interned_strings), 1024, NULL, _str_dtor, 1);
	
	CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
	CG(interned_strings).arData = (Bucket*) pecalloc(CG(interned_strings).nTableSize, sizeof(Bucket), 1);
	CG(interned_strings).arHash = (zend_uint*) pecalloc(CG(interned_strings).nTableSize, sizeof(zend_uint), 1);
	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_HASH_VAL(str);
	str->gc.u.v.flags |= IS_STR_INTERNED;
	CG(empty_string) = str;
#endif

	/* one char strings (the actual interned strings are going to be created by ext/opcache) */
	memset(CG(one_char_string), 0, sizeof(CG(one_char_string)));

	zend_new_interned_string = zend_new_interned_string_int;
	zend_interned_strings_snapshot = zend_interned_strings_snapshot_int;
	zend_interned_strings_restore = zend_interned_strings_restore_int;
}
Esempio n. 2
0
static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, zend_string *key)
{
	zend_uint_t h;
	uint nIndex;
	uint idx;
	Bucket *p;

	h = STR_HASH_VAL(key);
	nIndex = h & ht->nTableMask;
	idx = ht->arHash[nIndex];
	while (idx != INVALID_IDX) {
		p = ht->arData + idx;
		if ((p->key == key) || /* check for the the same interned string */
			(p->h == h &&
			 p->key &&
			 p->key->len == key->len &&
			 memcmp(p->key->val, key->val, key->len) == 0)) {
			return p;
		}
		idx = Z_NEXT(p->val);
	}
	return NULL;
}
Esempio n. 3
0
static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_string *key, zval *pData, int flag ZEND_FILE_LINE_DC)
{
	zend_uint_t h;
	uint nIndex;
	uint idx;
	Bucket *p;
#ifdef ZEND_SIGNALS
	TSRMLS_FETCH();
#endif

	IS_CONSISTENT(ht);

	CHECK_INIT(ht, 0);
	if (ht->u.flags & HASH_FLAG_PACKED) {
		zend_hash_packed_to_hash(ht);
	}

	h = STR_HASH_VAL(key);

	if ((flag & HASH_ADD_NEW) == 0) {
		p = zend_hash_find_bucket(ht, key);

		if (p) {
			zval *data;

			if (flag & HASH_ADD) {
				return NULL;
			}
			ZEND_ASSERT(&p->val != pData);
			data = &p->val;
			if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
				data = Z_INDIRECT_P(data);
			}
			HANDLE_BLOCK_INTERRUPTIONS();
			if (ht->pDestructor) {
				ht->pDestructor(data);
			}
			ZVAL_COPY_VALUE(data, pData);
			HANDLE_UNBLOCK_INTERRUPTIONS();
			return data;
		}
	}
	
	ZEND_HASH_IF_FULL_DO_RESIZE(ht);		/* If the Hash table is full, resize it */

	HANDLE_BLOCK_INTERRUPTIONS();
	idx = ht->nNumUsed++;
	ht->nNumOfElements++;
	if (ht->nInternalPointer == INVALID_IDX) {
		ht->nInternalPointer = idx;
	}
	p = ht->arData + idx; 
	p->h = h;
	p->key = key;
	STR_ADDREF(key);
	ZVAL_COPY_VALUE(&p->val, pData);
	nIndex = h & ht->nTableMask;
	Z_NEXT(p->val) = ht->arHash[nIndex];
	ht->arHash[nIndex] = idx;
	HANDLE_UNBLOCK_INTERRUPTIONS();

	return &p->val;
}