Refactored script creation and classes/functions copying.

This commit is contained in:
Dmitry Stogov 2018-11-23 03:19:16 +03:00
parent c6009dae34
commit b076a91c50
3 changed files with 61 additions and 23 deletions

View file

@ -1657,8 +1657,8 @@ static void zend_accel_init_auto_globals(void)
static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handle, int type, const char *key, zend_op_array **op_array_p)
{
zend_persistent_script *new_persistent_script;
uint32_t orig_functions_count, orig_class_count;
zend_op_array *orig_active_op_array;
HashTable *orig_class_table;
zval orig_user_error_handler;
zend_op_array *op_array;
int do_bailout = 0;
@ -1718,15 +1718,13 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
}
}
new_persistent_script = create_persistent_script();
/* Save the original values for the op_array, function table and class table */
orig_active_op_array = CG(active_op_array);
orig_class_table = CG(class_table);
orig_functions_count = EG(function_table)->nNumUsed;
orig_class_count = EG(class_table)->nNumUsed;
ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));
/* Override them with ours */
EG(class_table) = CG(class_table) = &new_persistent_script->script.class_table;
ZVAL_UNDEF(&EG(user_error_handler));
zend_try {
@ -1751,12 +1749,10 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
/* Restore originals */
CG(active_op_array) = orig_active_op_array;
EG(class_table) = CG(class_table) = orig_class_table;
EG(user_error_handler) = orig_user_error_handler;
if (!op_array) {
/* compilation failed */
free_persistent_script(new_persistent_script, 1);
if (do_bailout) {
zend_bailout();
}
@ -1767,8 +1763,10 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
Here we aren't sure we would store it, but we will need it
further anyway.
*/
new_persistent_script = create_persistent_script();
new_persistent_script->script.main_op_array = *op_array;
zend_accel_move_user_functions(CG(function_table), &new_persistent_script->script);
zend_accel_move_user_functions(CG(function_table), CG(function_table)->nNumUsed - orig_functions_count, &new_persistent_script->script);
zend_accel_move_user_classes(CG(class_table), CG(class_table)->nNumUsed - orig_class_count, &new_persistent_script->script);
new_persistent_script->script.first_early_binding_opline =
(op_array->fn_flags & ZEND_ACC_EARLY_BINDING) ?
zend_build_delayed_early_binding_list(op_array) :

View file

@ -49,12 +49,12 @@ zend_persistent_script* create_persistent_script(void)
zend_persistent_script *persistent_script = (zend_persistent_script *) emalloc(sizeof(zend_persistent_script));
memset(persistent_script, 0, sizeof(zend_persistent_script));
zend_hash_init(&persistent_script->script.function_table, 128, NULL, ZEND_FUNCTION_DTOR, 0);
zend_hash_init(&persistent_script->script.function_table, 0, NULL, ZEND_FUNCTION_DTOR, 0);
/* class_table is usually destroyed by free_persistent_script() that
* overrides destructor. ZEND_CLASS_DTOR may be used by standard
* PHP compiler
*/
zend_hash_init(&persistent_script->script.class_table, 16, NULL, ZEND_CLASS_DTOR, 0);
zend_hash_init(&persistent_script->script.class_table, 0, NULL, ZEND_CLASS_DTOR, 0);
return persistent_script;
}
@ -76,26 +76,65 @@ void free_persistent_script(zend_persistent_script *persistent_script, int destr
efree(persistent_script);
}
void zend_accel_move_user_functions(HashTable *src, zend_script *script)
void zend_accel_move_user_functions(HashTable *src, uint32_t count, zend_script *script)
{
Bucket *p;
HashTable *dst = &script->function_table;
zend_string *filename = script->main_op_array.filename;
dtor_func_t orig_dtor = src->pDestructor;
Bucket *p, *end;
HashTable *dst;
zend_string *filename;
dtor_func_t orig_dtor;
zend_function *function;
if (!count) {
return;
}
dst = &script->function_table;
filename = script->main_op_array.filename;
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);
zend_hash_extend(dst, count, 0);
end = src->arData + src->nNumUsed;
p = end - count;
for (; p != end; p++) {
if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
function = Z_PTR(p->val);
if (EXPECTED(function->type == ZEND_USER_FUNCTION)
&& EXPECTED(function->op_array.filename == filename)) {
_zend_hash_append_ptr(dst, p->key, function);
zend_hash_del_bucket(src, p);
} else {
break;
}
} ZEND_HASH_FOREACH_END();
}
src->pDestructor = orig_dtor;
}
void zend_accel_move_user_classes(HashTable *src, uint32_t count, zend_script *script)
{
Bucket *p, *end;
HashTable *dst;
zend_string *filename;
dtor_func_t orig_dtor;
zend_class_entry *ce;
if (!count) {
return;
}
dst = &script->class_table;
filename = script->main_op_array.filename;
orig_dtor = src->pDestructor;
src->pDestructor = NULL;
zend_hash_extend(dst, count, 0);
end = src->arData + src->nNumUsed;
p = end - count;
for (; p != end; p++) {
if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
ce = Z_PTR(p->val);
if (EXPECTED(ce->type == ZEND_USER_CLASS)
&& EXPECTED(ce->info.user.filename == filename)) {
_zend_hash_append_ptr(dst, p->key, ce);
zend_hash_del_bucket(src, p);
}
}
src->pDestructor = orig_dtor;
}

View file

@ -28,7 +28,8 @@
zend_persistent_script* create_persistent_script(void);
void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements);
void zend_accel_move_user_functions(HashTable *str, zend_script *script);
void zend_accel_move_user_functions(HashTable *str, uint32_t count, zend_script *script);
void zend_accel_move_user_classes(HashTable *str, uint32_t count, zend_script *script);
zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory);