From b076a91c5047da3915080bb8a5ebaa36dcef726e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 23 Nov 2018 03:19:16 +0300 Subject: [PATCH] Refactored script creation and classes/functions copying. --- ext/opcache/ZendAccelerator.c | 14 ++--- ext/opcache/zend_accelerator_util_funcs.c | 67 ++++++++++++++++++----- ext/opcache/zend_accelerator_util_funcs.h | 3 +- 3 files changed, 61 insertions(+), 23 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index d0f99cbc5ff..b72357a1755 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -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) : diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index bf9eb08f7b6..f39bc836972 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -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; } diff --git a/ext/opcache/zend_accelerator_util_funcs.h b/ext/opcache/zend_accelerator_util_funcs.h index 37b46496cf9..0666b17759f 100644 --- a/ext/opcache/zend_accelerator_util_funcs.h +++ b/ext/opcache/zend_accelerator_util_funcs.h @@ -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);