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) 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; zend_persistent_script *new_persistent_script;
uint32_t orig_functions_count, orig_class_count;
zend_op_array *orig_active_op_array; zend_op_array *orig_active_op_array;
HashTable *orig_class_table;
zval orig_user_error_handler; zval orig_user_error_handler;
zend_op_array *op_array; zend_op_array *op_array;
int do_bailout = 0; 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 */ /* Save the original values for the op_array, function table and class table */
orig_active_op_array = CG(active_op_array); 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)); ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));
/* Override them with ours */ /* Override them with ours */
EG(class_table) = CG(class_table) = &new_persistent_script->script.class_table;
ZVAL_UNDEF(&EG(user_error_handler)); ZVAL_UNDEF(&EG(user_error_handler));
zend_try { zend_try {
@ -1751,12 +1749,10 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
/* Restore originals */ /* Restore originals */
CG(active_op_array) = orig_active_op_array; 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; EG(user_error_handler) = orig_user_error_handler;
if (!op_array) { if (!op_array) {
/* compilation failed */ /* compilation failed */
free_persistent_script(new_persistent_script, 1);
if (do_bailout) { if (do_bailout) {
zend_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 Here we aren't sure we would store it, but we will need it
further anyway. further anyway.
*/ */
new_persistent_script = create_persistent_script();
new_persistent_script->script.main_op_array = *op_array; 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 = new_persistent_script->script.first_early_binding_opline =
(op_array->fn_flags & ZEND_ACC_EARLY_BINDING) ? (op_array->fn_flags & ZEND_ACC_EARLY_BINDING) ?
zend_build_delayed_early_binding_list(op_array) : 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)); zend_persistent_script *persistent_script = (zend_persistent_script *) emalloc(sizeof(zend_persistent_script));
memset(persistent_script, 0, 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 /* class_table is usually destroyed by free_persistent_script() that
* overrides destructor. ZEND_CLASS_DTOR may be used by standard * overrides destructor. ZEND_CLASS_DTOR may be used by standard
* PHP compiler * 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; return persistent_script;
} }
@ -76,26 +76,65 @@ void free_persistent_script(zend_persistent_script *persistent_script, int destr
efree(persistent_script); 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; Bucket *p, *end;
HashTable *dst = &script->function_table; HashTable *dst;
zend_string *filename = script->main_op_array.filename; zend_string *filename;
dtor_func_t orig_dtor = src->pDestructor; 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; src->pDestructor = NULL;
zend_hash_extend(dst, dst->nNumUsed + src->nNumUsed, 0); zend_hash_extend(dst, count, 0);
ZEND_HASH_REVERSE_FOREACH_BUCKET(src, p) { end = src->arData + src->nNumUsed;
zend_function *function = Z_PTR(p->val); 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) if (EXPECTED(function->type == ZEND_USER_FUNCTION)
&& EXPECTED(function->op_array.filename == filename)) { && EXPECTED(function->op_array.filename == filename)) {
_zend_hash_append_ptr(dst, p->key, function); _zend_hash_append_ptr(dst, p->key, function);
zend_hash_del_bucket(src, p); 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; src->pDestructor = orig_dtor;
} }

View file

@ -28,7 +28,8 @@
zend_persistent_script* create_persistent_script(void); zend_persistent_script* create_persistent_script(void);
void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements); 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); zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory);