Browse Source

Introduced ZEND_COMPILE_IGNORE_OTHER_FILES compiler option, to allow "separate" file compilation (unaffected but previously compiled files), without CG(function_table)/CG(class_table) manipulation.

pull/3460/head
Dmitry Stogov 7 years ago
parent
commit
fc8d6b6797
  1. 10
      Zend/zend_compile.c
  2. 3
      Zend/zend_compile.h
  3. 48
      ext/opcache/ZendAccelerator.c
  4. 4
      ext/opcache/ZendAccelerator.h
  5. 39
      ext/opcache/zend_accelerator_util_funcs.c
  6. 5
      ext/opcache/zend_accelerator_util_funcs.h

10
Zend/zend_compile.c

@ -1186,9 +1186,11 @@ void zend_do_early_binding(void) /* {{{ */
zend_class_entry *ce;
parent_name = CT_CONSTANT(opline->op2);
if (((ce = zend_lookup_class_ex(Z_STR_P(parent_name), parent_name + 1, 0)) == NULL) ||
((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
(ce->type == ZEND_INTERNAL_CLASS))) {
ce = zend_lookup_class_ex(Z_STR_P(parent_name), parent_name + 1, 0);
if (!ce
|| ((ce->type == ZEND_INTERNAL_CLASS) && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES))
|| ((ce->type == ZEND_USER_CLASS) && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && (ce->info.user.filename != CG(active_op_array)->filename))
) {
if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
CG(active_op_array)->fn_flags |= ZEND_ACC_EARLY_BINDING;
opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
@ -3540,6 +3542,7 @@ static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t
if (!fbc
|| (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS))
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename)
) {
zend_string_release_ex(lcname, 0);
return FAILURE;
@ -4016,6 +4019,7 @@ void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
if (!fbc
|| (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS))
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename)
) {
zend_string_release_ex(lcname, 0);
zend_compile_dynamic_call(result, &name_node, args_ast);

3
Zend/zend_compile.h

@ -1048,6 +1048,9 @@ END_EXTERN_C()
/* result of compilation may be stored in file cache */
#define ZEND_COMPILE_WITH_FILE_CACHE (1<<11)
/* ignore functions and classes declared in other files */
#define ZEND_COMPILE_IGNORE_OTHER_FILES (1<<12)
/* The default value for CG(compiler_options) */
#define ZEND_COMPILE_DEFAULT ZEND_COMPILE_HANDLE_OP_ARRAY

48
ext/opcache/ZendAccelerator.c

@ -1660,7 +1660,7 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
{
zend_persistent_script *new_persistent_script;
zend_op_array *orig_active_op_array;
HashTable *orig_function_table, *orig_class_table;
HashTable *orig_class_table;
zval orig_user_error_handler;
zend_op_array *op_array;
int do_bailout = 0;
@ -1724,12 +1724,10 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
/* Save the original values for the op_array, function table and class table */
orig_active_op_array = CG(active_op_array);
orig_function_table = CG(function_table);
orig_class_table = CG(class_table);
ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));
/* Override them with ours */
CG(function_table) = &ZCG(function_table);
EG(class_table) = CG(class_table) = &new_persistent_script->script.class_table;
ZVAL_UNDEF(&EG(user_error_handler));
@ -1739,6 +1737,7 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES;
CG(compiler_options) |= ZEND_COMPILE_DELAYED_BINDING;
CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION;
CG(compiler_options) |= ZEND_COMPILE_IGNORE_OTHER_FILES;
#ifdef HAVE_OPCACHE_FILE_CACHE
if (ZCG(accel_directives).file_cache) {
CG(compiler_options) |= ZEND_COMPILE_WITH_FILE_CACHE;
@ -1754,14 +1753,12 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
/* Restore originals */
CG(active_op_array) = orig_active_op_array;
CG(function_table) = orig_function_table;
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);
zend_accel_free_user_functions(&ZCG(function_table));
if (do_bailout) {
zend_bailout();
}
@ -1772,12 +1769,12 @@ 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.
*/
zend_accel_move_user_functions(&ZCG(function_table), &new_persistent_script->script.function_table);
new_persistent_script->script.main_op_array = *op_array;
zend_accel_move_user_functions(CG(function_table), &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) :
(uint32_t)-1;
new_persistent_script->script.main_op_array = *op_array;
efree(op_array); /* we have valid persistent_script, so it's safe to free op_array */
@ -2304,11 +2301,6 @@ static void accel_activate(void)
return;
}
if (!ZCG(function_table).nTableSize) {
zend_hash_init(&ZCG(function_table), zend_hash_num_elements(CG(function_table)), NULL, ZEND_FUNCTION_DTOR, 1);
zend_accel_copy_internal_functions();
}
/* PHP-5.4 and above return "double", but we use 1 sec precision */
ZCG(auto_globals_mask) = 0;
ZCG(request_time) = (time_t)sapi_get_request_time();
@ -2317,11 +2309,6 @@ static void accel_activate(void)
ZCG(include_path_key_len) = 0;
ZCG(include_path_check) = 1;
/* check if ZCG(function_table) wasn't somehow polluted on the way */
if (ZCG(internal_functions_count) != (zend_long)zend_hash_num_elements(&ZCG(function_table))) {
zend_accel_error(ACCEL_LOG_WARNING, "Internal functions count changed - was %d, now %d", ZCG(internal_functions_count), zend_hash_num_elements(&ZCG(function_table)));
}
ZCG(cwd) = NULL;
ZCG(cwd_key_len) = 0;
ZCG(cwd_check) = 1;
@ -2605,14 +2592,6 @@ static void accel_globals_ctor(zend_accel_globals *accel_globals)
accel_gen_system_id();
}
static void accel_globals_dtor(zend_accel_globals *accel_globals)
{
if (accel_globals->function_table.nTableSize) {
accel_globals->function_table.pDestructor = NULL;
zend_hash_destroy(&accel_globals->function_table);
}
}
#define ZEND_BIN_ID "BIN_" ZEND_TOSTR(SIZEOF_CHAR) ZEND_TOSTR(SIZEOF_INT) ZEND_TOSTR(SIZEOF_LONG) ZEND_TOSTR(SIZEOF_SIZE_T) ZEND_TOSTR(SIZEOF_ZEND_LONG) ZEND_TOSTR(ZEND_MM_ALIGNMENT)
static void accel_gen_system_id(void)
@ -2752,7 +2731,7 @@ static void accel_move_code_to_huge_pages(void)
static int accel_startup(zend_extension *extension)
{
#ifdef ZTS
accel_globals_id = ts_allocate_id(&accel_globals_id, sizeof(zend_accel_globals), (ts_allocate_ctor) accel_globals_ctor, (ts_allocate_dtor) accel_globals_dtor);
accel_globals_id = ts_allocate_id(&accel_globals_id, sizeof(zend_accel_globals), (ts_allocate_ctor) accel_globals_ctor, NULL);
#else
accel_globals_ctor(&accel_globals);
#endif
@ -2941,15 +2920,6 @@ file_cache_fallback:
return SUCCESS;
}
static void accel_free_ts_resources()
{
#ifndef ZTS
accel_globals_dtor(&accel_globals);
#else
ts_free_id(accel_globals_id);
#endif
}
void accel_shutdown(void)
{
zend_ini_entry *ini_entry;
@ -2960,7 +2930,9 @@ void accel_shutdown(void)
zend_accel_blacklist_shutdown(&accel_blacklist);
if (!ZCG(enabled) || !accel_startup_ok) {
accel_free_ts_resources();
#ifdef ZTS
ts_free_id(accel_globals_id);
#endif
return;
}
@ -2970,7 +2942,9 @@ void accel_shutdown(void)
accel_reset_pcre_cache();
accel_free_ts_resources();
#ifdef ZTS
ts_free_id(accel_globals_id);
#endif
if (!_file_cache_only) {
zend_shared_alloc_shutdown();

4
ext/opcache/ZendAccelerator.h

@ -215,10 +215,6 @@ typedef struct _zend_accel_directives {
} zend_accel_directives;
typedef struct _zend_accel_globals {
/* copy of CG(function_table) used for compilation scripts into cache */
/* initially it contains only internal functions */
HashTable function_table;
int internal_functions_count;
int counted; /* the process uses shared memory */
zend_bool enabled;
zend_bool locked; /* thread obtained exclusive lock */

39
ext/opcache/zend_accelerator_util_funcs.c

@ -72,27 +72,11 @@ void free_persistent_script(zend_persistent_script *persistent_script, int destr
efree(persistent_script);
}
void zend_accel_free_user_functions(HashTable *ht)
{
Bucket *p;
dtor_func_t orig_dtor = ht->pDestructor;
ht->pDestructor = NULL;
ZEND_HASH_REVERSE_FOREACH_BUCKET(ht, p) {
zend_function *function = Z_PTR(p->val);
if (EXPECTED(function->type == ZEND_USER_FUNCTION)) {
zend_hash_del_bucket(ht, p);
} else {
break;
}
} ZEND_HASH_FOREACH_END();
ht->pDestructor = orig_dtor;
}
void zend_accel_move_user_functions(HashTable *src, HashTable *dst)
void zend_accel_move_user_functions(HashTable *src, 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;
src->pDestructor = NULL;
@ -100,7 +84,8 @@ void zend_accel_move_user_functions(HashTable *src, HashTable *dst)
ZEND_HASH_REVERSE_FOREACH_BUCKET(src, p) {
zend_function *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)) {
_zend_hash_append_ptr(dst, p->key, function);
zend_hash_del_bucket(src, p);
} else {
@ -110,20 +95,6 @@ void zend_accel_move_user_functions(HashTable *src, HashTable *dst)
src->pDestructor = orig_dtor;
}
void zend_accel_copy_internal_functions(void)
{
zend_string *key;
zval *val;
ZEND_HASH_FOREACH_STR_KEY_VAL(CG(function_table), key, val) {
zend_internal_function *function = Z_PTR_P(val);
if (function->type == ZEND_INTERNAL_FUNCTION) {
zend_hash_add_new_ptr(&ZCG(function_table), key, function);
}
} ZEND_HASH_FOREACH_END();
ZCG(internal_functions_count) = zend_hash_num_elements(&ZCG(function_table));
}
static inline void zend_clone_zval(zval *src)
{
void *ptr;

5
ext/opcache/zend_accelerator_util_funcs.h

@ -25,13 +25,10 @@
#include "zend.h"
#include "ZendAccelerator.h"
void zend_accel_copy_internal_functions(void);
zend_persistent_script* create_persistent_script(void);
void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements);
void zend_accel_free_user_functions(HashTable *ht);
void zend_accel_move_user_functions(HashTable *str, HashTable *dst);
void zend_accel_move_user_functions(HashTable *str, zend_script *script);
zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory);

Loading…
Cancel
Save