summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2015-05-19 13:22:58 +0300
committerDmitry Stogov <dmitry@zend.com>2015-05-19 13:22:58 +0300
commit6c8d49b6b0face2a5453f168da385b0964c3194f (patch)
tree3be79601c90a7a7ed48127d04a9225d5fcf37957
parent27b83079fed07ebad369d3d2f774cad6293171a7 (diff)
downloadphp-git-6c8d49b6b0face2a5453f168da385b0964c3194f.tar.gz
Improved hash table copying
-rw-r--r--Zend/zend_hash.h6
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.c74
2 files changed, 44 insertions, 36 deletions
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index dcac9c355c..78a04ce038 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -877,7 +877,7 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht,
__fill_ht->nInternalPointer = 0; \
} while (0)
-static zend_always_inline void _zend_hash_append(HashTable *ht, zend_string *key, zval *zv)
+static zend_always_inline zval *_zend_hash_append(HashTable *ht, zend_string *key, zval *zv)
{
uint32_t idx = ht->nNumUsed++;
uint32_t nIndex;
@@ -896,9 +896,10 @@ static zend_always_inline void _zend_hash_append(HashTable *ht, zend_string *key
HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
ht->nNumUsed = idx + 1;
ht->nNumOfElements++;
+ return &p->val;
}
-static zend_always_inline void _zend_hash_append_ptr(HashTable *ht, zend_string *key, void *ptr)
+static zend_always_inline zval *_zend_hash_append_ptr(HashTable *ht, zend_string *key, void *ptr)
{
uint32_t idx = ht->nNumUsed++;
uint32_t nIndex;
@@ -917,6 +918,7 @@ static zend_always_inline void _zend_hash_append_ptr(HashTable *ht, zend_string
HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
ht->nNumUsed = idx + 1;
ht->nNumOfElements++;
+ return &p->val;
}
static zend_always_inline void _zend_hash_append_ind(HashTable *ht, zend_string *key, zval *ptr)
diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c
index 9407b2ec39..d3abaca7ff 100644
--- a/ext/opcache/zend_accelerator_util_funcs.c
+++ b/ext/opcache/zend_accelerator_util_funcs.c
@@ -124,11 +124,12 @@ void zend_accel_move_user_functions(HashTable *src, HashTable *dst)
dtor_func_t orig_dtor = src->pDestructor;
src->pDestructor = NULL;
+ zend_hash_extend(dst, dst->nNumUsed + src->nNumUsed, 0);
ZEND_HASH_REVERSE_FOREACH_BUCKET(src, p) {
zend_function *function = Z_PTR(p->val);
if (EXPECTED(function->type == ZEND_USER_FUNCTION)) {
- zend_hash_add_new_ptr(dst, p->key, function);
+ _zend_hash_append_ptr(dst, p->key, function);
zend_hash_del_bucket(src, p);
} else {
break;
@@ -636,23 +637,25 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
static void zend_accel_function_hash_copy(HashTable *target, HashTable *source)
{
zend_function *function1, *function2;
- uint idx;
- Bucket *p;
+ Bucket *p, *end;
zval *t;
- for (idx = 0; idx < source->nNumUsed; idx++) {
- p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ zend_hash_extend(target, target->nNumUsed + source->nNumUsed, 0);
+ p = source->arData;
+ end = p + source->nNumUsed;
+ for (; p != end; p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
ZEND_ASSERT(p->key);
- t = zend_hash_add(target, p->key, &p->val);
- if (UNEXPECTED(t == NULL)) {
- if (p->key->len > 0 && p->key->val[0] == 0) {
+ t = zend_hash_find(target, p->key);
+ if (UNEXPECTED(t != NULL)) {
+ if (EXPECTED(p->key->len > 0) && EXPECTED(p->key->val[0] == 0)) {
/* Mangled key */
t = zend_hash_update(target, p->key, &p->val);
} else {
- t = zend_hash_find(target, p->key);
goto failure;
}
+ } else {
+ _zend_hash_append_ptr(target, p->key, Z_PTR(p->val));
}
}
target->nInternalPointer = target->nNumOfElements ? 0 : HT_INVALID_IDX;
@@ -678,25 +681,26 @@ failure:
static void zend_accel_function_hash_copy_from_shm(HashTable *target, HashTable *source)
{
zend_function *function1, *function2;
- uint idx;
- Bucket *p;
+ Bucket *p, *end;
zval *t;
- for (idx = 0; idx < source->nNumUsed; idx++) {
- p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ zend_hash_extend(target, target->nNumUsed + source->nNumUsed, 0);
+ p = source->arData;
+ end = p + source->nNumUsed;
+ for (; p != end; p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
ZEND_ASSERT(p->key);
- t = zend_hash_add(target, p->key, &p->val);
- if (UNEXPECTED(t == NULL)) {
- if (p->key->len > 0 && p->key->val[0] == 0) {
+ t = zend_hash_find(target, p->key);
+ if (UNEXPECTED(t != NULL)) {
+ if (EXPECTED(p->key->len > 0) && EXPECTED(p->key->val[0] == 0)) {
/* Mangled key */
- t = zend_hash_update(target, p->key, &p->val);
+ zend_hash_update_ptr(target, p->key, ARENA_REALLOC(Z_PTR(p->val)));
} else {
- t = zend_hash_find(target, p->key);
goto failure;
}
+ } else {
+ _zend_hash_append_ptr(target, p->key, ARENA_REALLOC(Z_PTR(p->val)));
}
- Z_PTR_P(t) = ARENA_REALLOC(Z_PTR(p->val));
}
target->nInternalPointer = target->nNumOfElements ? 0 : HT_INVALID_IDX;
return;
@@ -721,26 +725,28 @@ failure:
static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor)
{
zend_class_entry *ce1;
- uint idx;
- Bucket *p;
+ Bucket *p, *end;
zval *t;
- for (idx = 0; idx < source->nNumUsed; idx++) {
- p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ zend_hash_extend(target, target->nNumUsed + source->nNumUsed, 0);
+ p = source->arData;
+ end = p + source->nNumUsed;
+ for (; p != end; p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
ZEND_ASSERT(p->key);
- t = zend_hash_add(target, p->key, &p->val);
- if (UNEXPECTED(t == NULL)) {
- if (p->key->len > 0 && p->key->val[0] == 0) {
+ t = zend_hash_find(target, p->key);
+ if (UNEXPECTED(t != NULL)) {
+ if (EXPECTED(p->key->len > 0) && EXPECTED(p->key->val[0] == 0)) {
/* Mangled key - ignore and wait for runtime */
continue;
- } else if (!ZCG(accel_directives).ignore_dups) {
- t = zend_hash_find(target, p->key);
+ } else if (UNEXPECTED(!ZCG(accel_directives).ignore_dups)) {
goto failure;
}
- }
- if (pCopyConstructor) {
- pCopyConstructor(&Z_PTR_P(t));
+ } else {
+ t = _zend_hash_append_ptr(target, p->key, Z_PTR(p->val));
+ if (pCopyConstructor) {
+ pCopyConstructor(&Z_PTR_P(t));
+ }
}
}
target->nInternalPointer = target->nNumOfElements ? 0 : HT_INVALID_IDX;