Skip to content

Commit

Permalink
Improved hash copying
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Sep 19, 2018
1 parent 27b9fac commit f5e1868
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 71 deletions.
99 changes: 28 additions & 71 deletions ext/opcache/zend_accelerator_util_funcs.c
Expand Up @@ -97,46 +97,33 @@ void zend_accel_move_user_functions(HashTable *src, zend_script *script)

static void zend_hash_clone_constants(HashTable *ht, HashTable *source)
{
Bucket *p, *q, *end;
zend_ulong nIndex;
Bucket *p, *end;
zend_class_constant *c;

ht->nTableSize = source->nTableSize;
ht->nTableMask = source->nTableMask;
ht->nNumUsed = 0;
ht->nNumUsed = source->nNumUsed;
ht->nNumOfElements = source->nNumOfElements;
ht->nNextFreeElement = source->nNextFreeElement;
ht->pDestructor = NULL;
HT_FLAGS(ht) = (HT_FLAGS(source) & (HASH_FLAG_INITIALIZED | HASH_FLAG_STATIC_KEYS));
HT_FLAGS(ht) = HT_FLAGS(source);
ht->nInternalPointer = 0;

if (!(HT_FLAGS(ht) & HASH_FLAG_INITIALIZED)) {
ht->arData = source->arData;
return;
}

ZEND_ASSERT((HT_FLAGS(source) & HASH_FLAG_PACKED) == 0);
HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht)));
HT_HASH_RESET(ht);
p = emalloc(HT_SIZE(ht));
memcpy(p, HT_GET_DATA_ADDR(source), HT_USED_SIZE(ht));
HT_SET_DATA_ADDR(ht, p);

p = source->arData;
end = p + source->nNumUsed;
p = ht->arData;
end = p + ht->nNumUsed;
for (; p != end; p++) {
ZEND_ASSERT(Z_TYPE(p->val) != IS_UNDEF);
nIndex = p->h | ht->nTableMask;

/* Insert into hash collision list */
q = ht->arData + ht->nNumUsed;
Z_NEXT(q->val) = HT_HASH(ht, nIndex);
HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(ht->nNumUsed++);

/* Initialize key */
q->h = p->h;
q->key = p->key;

/* Copy data */
c = ARENA_REALLOC(Z_PTR(p->val));
ZVAL_PTR(&q->val, c);
Z_PTR(p->val) = c;

if ((void*)c->ce >= ZCG(current_persistent_script)->arena_mem &&
(void*)c->ce < (void*)((char*)ZCG(current_persistent_script)->arena_mem + ZCG(current_persistent_script)->arena_size)) {
Expand All @@ -147,48 +134,33 @@ static void zend_hash_clone_constants(HashTable *ht, HashTable *source)

static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce)
{
Bucket *p, *q, *end;
zend_ulong nIndex;
Bucket *p, *end;
zend_op_array *new_entry;

ht->nTableSize = source->nTableSize;
ht->nTableMask = source->nTableMask;
ht->nNumUsed = 0;
ht->nNumUsed = source->nNumUsed;
ht->nNumOfElements = source->nNumOfElements;
ht->nNextFreeElement = source->nNextFreeElement;
ht->pDestructor = ZEND_FUNCTION_DTOR;
HT_FLAGS(ht) = (HT_FLAGS(source) & (HASH_FLAG_INITIALIZED | HASH_FLAG_STATIC_KEYS));
HT_FLAGS(ht) = HT_FLAGS(source);
ht->nInternalPointer = 0;

if (!(HT_FLAGS(ht) & HASH_FLAG_INITIALIZED)) {
ht->arData = source->arData;
return;
}

ZEND_ASSERT(!(HT_FLAGS(source) & HASH_FLAG_PACKED));
HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht)));
HT_HASH_RESET(ht);
p = emalloc(HT_SIZE(ht));
memcpy(p, HT_GET_DATA_ADDR(source), HT_USED_SIZE(ht));
HT_SET_DATA_ADDR(ht, p);

p = source->arData;
end = p + source->nNumUsed;
p = ht->arData;
end = p + ht->nNumUsed;
for (; p != end; p++) {
ZEND_ASSERT(Z_TYPE(p->val) != IS_UNDEF);

nIndex = p->h | ht->nTableMask;

/* Insert into hash collision list */
q = ht->arData + ht->nNumUsed;
Z_NEXT(q->val) = HT_HASH(ht, nIndex);
HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(ht->nNumUsed++);

/* Initialize key */
q->h = p->h;
ZEND_ASSERT(p->key != NULL);
q->key = p->key;

/* Copy data */
ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val)));
new_entry = (zend_op_array*)Z_PTR(q->val);
new_entry = ARENA_REALLOC(Z_PTR(p->val));
Z_PTR(p->val) = new_entry;

if ((void*)new_entry->scope >= ZCG(current_persistent_script)->arena_mem &&
(void*)new_entry->scope < (void*)((char*)ZCG(current_persistent_script)->arena_mem + ZCG(current_persistent_script)->arena_size)) {
Expand All @@ -205,48 +177,33 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class

static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_class_entry *old_ce)
{
Bucket *p, *q, *end;
zend_ulong nIndex;
Bucket *p, *end;
zend_property_info *prop_info;

ht->nTableSize = source->nTableSize;
ht->nTableMask = source->nTableMask;
ht->nNumUsed = 0;
ht->nNumUsed = source->nNumUsed;
ht->nNumOfElements = source->nNumOfElements;
ht->nNextFreeElement = source->nNextFreeElement;
ht->pDestructor = NULL;
HT_FLAGS(ht) = (HT_FLAGS(source) & (HASH_FLAG_INITIALIZED | HASH_FLAG_STATIC_KEYS));
HT_FLAGS(ht) = HT_FLAGS(source);
ht->nInternalPointer = 0;

if (!(HT_FLAGS(ht) & HASH_FLAG_INITIALIZED)) {
ht->arData = source->arData;
return;
}

ZEND_ASSERT(!(HT_FLAGS(source) & HASH_FLAG_PACKED));
HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht)));
HT_HASH_RESET(ht);
p = emalloc(HT_SIZE(ht));
memcpy(p, HT_GET_DATA_ADDR(source), HT_USED_SIZE(ht));
HT_SET_DATA_ADDR(ht, p);

p = source->arData;
end = p + source->nNumUsed;
p = ht->arData;
end = p + ht->nNumUsed;
for (; p != end; p++) {
ZEND_ASSERT(Z_TYPE(p->val) != IS_UNDEF);

nIndex = p->h | ht->nTableMask;

/* Insert into hash collision list */
q = ht->arData + ht->nNumUsed;
Z_NEXT(q->val) = HT_HASH(ht, nIndex);
HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(ht->nNumUsed++);

/* Initialize key */
q->h = p->h;
ZEND_ASSERT(p->key != NULL);
q->key = p->key;

/* Copy data */
prop_info = ARENA_REALLOC(Z_PTR(p->val));
ZVAL_PTR(&q->val, prop_info);
Z_PTR(p->val) = prop_info;

if ((void*)prop_info->ce >= ZCG(current_persistent_script)->arena_mem &&
(void*)prop_info->ce < (void*)((char*)ZCG(current_persistent_script)->arena_mem + ZCG(current_persistent_script)->arena_size)) {
Expand Down
3 changes: 3 additions & 0 deletions ext/opcache/zend_persist.c
Expand Up @@ -722,6 +722,7 @@ static void zend_persist_class_entry(zval *zv)
zend_accel_store_interned_string(ce->parent_name);
}
zend_hash_persist(&ce->function_table, zend_persist_class_method);
HT_FLAGS(&ce->function_table) &= (HASH_FLAG_INITIALIZED | HASH_FLAG_STATIC_KEYS);
if (ce->default_properties_table) {
int i;

Expand All @@ -744,6 +745,7 @@ static void zend_persist_class_entry(zval *zv)
ce->static_members_table = NULL;

zend_hash_persist(&ce->constants_table, zend_persist_class_constant);
HT_FLAGS(&ce->constants_table) &= (HASH_FLAG_INITIALIZED | HASH_FLAG_STATIC_KEYS);

if (ce->info.user.filename) {
/* do not free! PHP has centralized filename storage, compiler will free it */
Expand All @@ -761,6 +763,7 @@ static void zend_persist_class_entry(zval *zv)
}
}
zend_hash_persist(&ce->properties_info, zend_persist_property_info);
HT_FLAGS(&ce->properties_info) &= (HASH_FLAG_INITIALIZED | HASH_FLAG_STATIC_KEYS);

if (ce->num_interfaces) {
uint32_t i = 0;
Expand Down

0 comments on commit f5e1868

Please sign in to comment.