Skip to content

Commit fc8d6b6

Browse files
committed
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.
1 parent 850b53d commit fc8d6b6

6 files changed

+27
-82
lines changed

Zend/zend_compile.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -1186,9 +1186,11 @@ void zend_do_early_binding(void) /* {{{ */
11861186
zend_class_entry *ce;
11871187

11881188
parent_name = CT_CONSTANT(opline->op2);
1189-
if (((ce = zend_lookup_class_ex(Z_STR_P(parent_name), parent_name + 1, 0)) == NULL) ||
1190-
((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
1191-
(ce->type == ZEND_INTERNAL_CLASS))) {
1189+
ce = zend_lookup_class_ex(Z_STR_P(parent_name), parent_name + 1, 0);
1190+
if (!ce
1191+
|| ((ce->type == ZEND_INTERNAL_CLASS) && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES))
1192+
|| ((ce->type == ZEND_USER_CLASS) && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && (ce->info.user.filename != CG(active_op_array)->filename))
1193+
) {
11921194
if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
11931195
CG(active_op_array)->fn_flags |= ZEND_ACC_EARLY_BINDING;
11941196
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
35403542
if (!fbc
35413543
|| (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
35423544
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS))
3545+
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename)
35433546
) {
35443547
zend_string_release_ex(lcname, 0);
35453548
return FAILURE;
@@ -4016,6 +4019,7 @@ void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
40164019
if (!fbc
40174020
|| (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
40184021
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS))
4022+
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename)
40194023
) {
40204024
zend_string_release_ex(lcname, 0);
40214025
zend_compile_dynamic_call(result, &name_node, args_ast);

Zend/zend_compile.h

+3
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,9 @@ END_EXTERN_C()
10481048
/* result of compilation may be stored in file cache */
10491049
#define ZEND_COMPILE_WITH_FILE_CACHE (1<<11)
10501050

1051+
/* ignore functions and classes declared in other files */
1052+
#define ZEND_COMPILE_IGNORE_OTHER_FILES (1<<12)
1053+
10511054
/* The default value for CG(compiler_options) */
10521055
#define ZEND_COMPILE_DEFAULT ZEND_COMPILE_HANDLE_OP_ARRAY
10531056

ext/opcache/ZendAccelerator.c

+11-37
Original file line numberDiff line numberDiff line change
@@ -1660,7 +1660,7 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
16601660
{
16611661
zend_persistent_script *new_persistent_script;
16621662
zend_op_array *orig_active_op_array;
1663-
HashTable *orig_function_table, *orig_class_table;
1663+
HashTable *orig_class_table;
16641664
zval orig_user_error_handler;
16651665
zend_op_array *op_array;
16661666
int do_bailout = 0;
@@ -1724,12 +1724,10 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
17241724

17251725
/* Save the original values for the op_array, function table and class table */
17261726
orig_active_op_array = CG(active_op_array);
1727-
orig_function_table = CG(function_table);
17281727
orig_class_table = CG(class_table);
17291728
ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));
17301729

17311730
/* Override them with ours */
1732-
CG(function_table) = &ZCG(function_table);
17331731
EG(class_table) = CG(class_table) = &new_persistent_script->script.class_table;
17341732
ZVAL_UNDEF(&EG(user_error_handler));
17351733

@@ -1739,6 +1737,7 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
17391737
CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES;
17401738
CG(compiler_options) |= ZEND_COMPILE_DELAYED_BINDING;
17411739
CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION;
1740+
CG(compiler_options) |= ZEND_COMPILE_IGNORE_OTHER_FILES;
17421741
#ifdef HAVE_OPCACHE_FILE_CACHE
17431742
if (ZCG(accel_directives).file_cache) {
17441743
CG(compiler_options) |= ZEND_COMPILE_WITH_FILE_CACHE;
@@ -1754,14 +1753,12 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
17541753

17551754
/* Restore originals */
17561755
CG(active_op_array) = orig_active_op_array;
1757-
CG(function_table) = orig_function_table;
17581756
EG(class_table) = CG(class_table) = orig_class_table;
17591757
EG(user_error_handler) = orig_user_error_handler;
17601758

17611759
if (!op_array) {
17621760
/* compilation failed */
17631761
free_persistent_script(new_persistent_script, 1);
1764-
zend_accel_free_user_functions(&ZCG(function_table));
17651762
if (do_bailout) {
17661763
zend_bailout();
17671764
}
@@ -1772,12 +1769,12 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
17721769
Here we aren't sure we would store it, but we will need it
17731770
further anyway.
17741771
*/
1775-
zend_accel_move_user_functions(&ZCG(function_table), &new_persistent_script->script.function_table);
1772+
new_persistent_script->script.main_op_array = *op_array;
1773+
zend_accel_move_user_functions(CG(function_table), &new_persistent_script->script);
17761774
new_persistent_script->script.first_early_binding_opline =
17771775
(op_array->fn_flags & ZEND_ACC_EARLY_BINDING) ?
17781776
zend_build_delayed_early_binding_list(op_array) :
17791777
(uint32_t)-1;
1780-
new_persistent_script->script.main_op_array = *op_array;
17811778

17821779
efree(op_array); /* we have valid persistent_script, so it's safe to free op_array */
17831780

@@ -2304,11 +2301,6 @@ static void accel_activate(void)
23042301
return;
23052302
}
23062303

2307-
if (!ZCG(function_table).nTableSize) {
2308-
zend_hash_init(&ZCG(function_table), zend_hash_num_elements(CG(function_table)), NULL, ZEND_FUNCTION_DTOR, 1);
2309-
zend_accel_copy_internal_functions();
2310-
}
2311-
23122304
/* PHP-5.4 and above return "double", but we use 1 sec precision */
23132305
ZCG(auto_globals_mask) = 0;
23142306
ZCG(request_time) = (time_t)sapi_get_request_time();
@@ -2317,11 +2309,6 @@ static void accel_activate(void)
23172309
ZCG(include_path_key_len) = 0;
23182310
ZCG(include_path_check) = 1;
23192311

2320-
/* check if ZCG(function_table) wasn't somehow polluted on the way */
2321-
if (ZCG(internal_functions_count) != (zend_long)zend_hash_num_elements(&ZCG(function_table))) {
2322-
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)));
2323-
}
2324-
23252312
ZCG(cwd) = NULL;
23262313
ZCG(cwd_key_len) = 0;
23272314
ZCG(cwd_check) = 1;
@@ -2605,14 +2592,6 @@ static void accel_globals_ctor(zend_accel_globals *accel_globals)
26052592
accel_gen_system_id();
26062593
}
26072594

2608-
static void accel_globals_dtor(zend_accel_globals *accel_globals)
2609-
{
2610-
if (accel_globals->function_table.nTableSize) {
2611-
accel_globals->function_table.pDestructor = NULL;
2612-
zend_hash_destroy(&accel_globals->function_table);
2613-
}
2614-
}
2615-
26162595
#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)
26172596

26182597
static void accel_gen_system_id(void)
@@ -2752,7 +2731,7 @@ static void accel_move_code_to_huge_pages(void)
27522731
static int accel_startup(zend_extension *extension)
27532732
{
27542733
#ifdef ZTS
2755-
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);
2734+
accel_globals_id = ts_allocate_id(&accel_globals_id, sizeof(zend_accel_globals), (ts_allocate_ctor) accel_globals_ctor, NULL);
27562735
#else
27572736
accel_globals_ctor(&accel_globals);
27582737
#endif
@@ -2941,15 +2920,6 @@ static int accel_post_startup(void)
29412920
return SUCCESS;
29422921
}
29432922

2944-
static void accel_free_ts_resources()
2945-
{
2946-
#ifndef ZTS
2947-
accel_globals_dtor(&accel_globals);
2948-
#else
2949-
ts_free_id(accel_globals_id);
2950-
#endif
2951-
}
2952-
29532923
void accel_shutdown(void)
29542924
{
29552925
zend_ini_entry *ini_entry;
@@ -2960,7 +2930,9 @@ void accel_shutdown(void)
29602930
zend_accel_blacklist_shutdown(&accel_blacklist);
29612931

29622932
if (!ZCG(enabled) || !accel_startup_ok) {
2963-
accel_free_ts_resources();
2933+
#ifdef ZTS
2934+
ts_free_id(accel_globals_id);
2935+
#endif
29642936
return;
29652937
}
29662938

@@ -2970,7 +2942,9 @@ void accel_shutdown(void)
29702942

29712943
accel_reset_pcre_cache();
29722944

2973-
accel_free_ts_resources();
2945+
#ifdef ZTS
2946+
ts_free_id(accel_globals_id);
2947+
#endif
29742948

29752949
if (!_file_cache_only) {
29762950
zend_shared_alloc_shutdown();

ext/opcache/ZendAccelerator.h

-4
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,6 @@ typedef struct _zend_accel_directives {
215215
} zend_accel_directives;
216216

217217
typedef struct _zend_accel_globals {
218-
/* copy of CG(function_table) used for compilation scripts into cache */
219-
/* initially it contains only internal functions */
220-
HashTable function_table;
221-
int internal_functions_count;
222218
int counted; /* the process uses shared memory */
223219
zend_bool enabled;
224220
zend_bool locked; /* thread obtained exclusive lock */

ext/opcache/zend_accelerator_util_funcs.c

+5-34
Original file line numberDiff line numberDiff line change
@@ -72,35 +72,20 @@ void free_persistent_script(zend_persistent_script *persistent_script, int destr
7272
efree(persistent_script);
7373
}
7474

75-
void zend_accel_free_user_functions(HashTable *ht)
76-
{
77-
Bucket *p;
78-
dtor_func_t orig_dtor = ht->pDestructor;
79-
80-
ht->pDestructor = NULL;
81-
ZEND_HASH_REVERSE_FOREACH_BUCKET(ht, p) {
82-
zend_function *function = Z_PTR(p->val);
83-
84-
if (EXPECTED(function->type == ZEND_USER_FUNCTION)) {
85-
zend_hash_del_bucket(ht, p);
86-
} else {
87-
break;
88-
}
89-
} ZEND_HASH_FOREACH_END();
90-
ht->pDestructor = orig_dtor;
91-
}
92-
93-
void zend_accel_move_user_functions(HashTable *src, HashTable *dst)
75+
void zend_accel_move_user_functions(HashTable *src, zend_script *script)
9476
{
9577
Bucket *p;
78+
HashTable *dst = &script->function_table;
79+
zend_string *filename = script->main_op_array.filename;
9680
dtor_func_t orig_dtor = src->pDestructor;
9781

9882
src->pDestructor = NULL;
9983
zend_hash_extend(dst, dst->nNumUsed + src->nNumUsed, 0);
10084
ZEND_HASH_REVERSE_FOREACH_BUCKET(src, p) {
10185
zend_function *function = Z_PTR(p->val);
10286

103-
if (EXPECTED(function->type == ZEND_USER_FUNCTION)) {
87+
if (EXPECTED(function->type == ZEND_USER_FUNCTION)
88+
&& EXPECTED(function->op_array.filename == filename)) {
10489
_zend_hash_append_ptr(dst, p->key, function);
10590
zend_hash_del_bucket(src, p);
10691
} else {
@@ -110,20 +95,6 @@ void zend_accel_move_user_functions(HashTable *src, HashTable *dst)
11095
src->pDestructor = orig_dtor;
11196
}
11297

113-
void zend_accel_copy_internal_functions(void)
114-
{
115-
zend_string *key;
116-
zval *val;
117-
118-
ZEND_HASH_FOREACH_STR_KEY_VAL(CG(function_table), key, val) {
119-
zend_internal_function *function = Z_PTR_P(val);
120-
if (function->type == ZEND_INTERNAL_FUNCTION) {
121-
zend_hash_add_new_ptr(&ZCG(function_table), key, function);
122-
}
123-
} ZEND_HASH_FOREACH_END();
124-
ZCG(internal_functions_count) = zend_hash_num_elements(&ZCG(function_table));
125-
}
126-
12798
static inline void zend_clone_zval(zval *src)
12899
{
129100
void *ptr;

ext/opcache/zend_accelerator_util_funcs.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,10 @@
2525
#include "zend.h"
2626
#include "ZendAccelerator.h"
2727

28-
void zend_accel_copy_internal_functions(void);
29-
3028
zend_persistent_script* create_persistent_script(void);
3129
void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements);
3230

33-
void zend_accel_free_user_functions(HashTable *ht);
34-
void zend_accel_move_user_functions(HashTable *str, HashTable *dst);
31+
void zend_accel_move_user_functions(HashTable *str, zend_script *script);
3532

3633
zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory);
3734

0 commit comments

Comments
 (0)