Skip to content

Commit 4a57b5d

Browse files
committed
Fixed preloading of classes linked with traits
1 parent 68c4f99 commit 4a57b5d

File tree

5 files changed

+46
-7
lines changed

5 files changed

+46
-7
lines changed

Zend/zend_compile.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ typedef struct _zend_oparray_context {
260260
/* User class has methods with static variables | | | */
261261
#define ZEND_HAS_STATIC_IN_METHODS (1 << 15) /* X | | | */
262262
/* | | | */
263-
/* Function Flags (unused: 26...30) | | | */
263+
/* Function Flags (unused: 27...30) | | | */
264264
/* ============== | | | */
265265
/* | | | */
266266
/* deprecation flag | | | */
@@ -310,6 +310,9 @@ typedef struct _zend_oparray_context {
310310
/* internal function is allocated at arena (int only) | | | */
311311
#define ZEND_ACC_ARENA_ALLOCATED (1 << 25) /* | X | | */
312312
/* | | | */
313+
/* op_array is a clone of trait method | | | */
314+
#define ZEND_ACC_TRAIT_CLONE (1 << 26) /* | X | | */
315+
/* | | | */
313316
/* op_array uses strict mode types | | | */
314317
#define ZEND_ACC_STRICT_TYPES (1 << 31) /* | X | | */
315318

Zend/zend_inheritance.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,7 @@ static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_s
13081308
} else {
13091309
new_fn = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
13101310
memcpy(new_fn, fn, sizeof(zend_op_array));
1311+
new_fn->op_array.fn_flags |= ZEND_ACC_TRAIT_CLONE;
13111312
new_fn->op_array.fn_flags &= ~ZEND_ACC_IMMUTABLE;
13121313
}
13131314
function_add_ref(new_fn);

ext/opcache/Optimizer/zend_call_graph.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ static int zend_foreach_op_array(zend_call_graph *call_graph, zend_script *scrip
6767

6868
ZEND_HASH_FOREACH_PTR(&script->class_table, ce) {
6969
ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
70-
if (op_array->scope == ce) {
70+
if (op_array->scope == ce && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
7171
if (func(call_graph, op_array) != SUCCESS) {
7272
return FAILURE;
7373
}

ext/opcache/Optimizer/zend_optimizer.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,7 +1442,7 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level, zend
14421442

14431443
ZEND_HASH_FOREACH_PTR(&script->class_table, ce) {
14441444
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, name, op_array) {
1445-
if (op_array->scope == ce) {
1445+
if (op_array->scope == ce && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
14461446
zend_optimize_op_array(op_array, &ctx);
14471447
}
14481448
} ZEND_HASH_FOREACH_END();
@@ -1546,7 +1546,7 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level, zend
15461546

15471547
ZEND_HASH_FOREACH_PTR(&script->class_table, ce) {
15481548
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, name, op_array) {
1549-
if (op_array->scope == ce) {
1549+
if (op_array->scope == ce && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
15501550
zend_adjust_fcall_stack_size(op_array, &ctx);
15511551
}
15521552
} ZEND_HASH_FOREACH_END();
@@ -1582,7 +1582,7 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level, zend
15821582

15831583
ZEND_HASH_FOREACH_PTR(&script->class_table, ce) {
15841584
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, name, op_array) {
1585-
if (op_array->scope == ce) {
1585+
if (op_array->scope == ce && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
15861586
zend_dump_op_array(op_array, ZEND_DUMP_RT_CONSTANTS, "after optimizer", NULL);
15871587
}
15881588
} ZEND_HASH_FOREACH_END();

ext/opcache/ZendAccelerator.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3534,9 +3534,44 @@ static void preload_remove_empty_includes(void)
35343534

35353535
static int preload_optimize(zend_persistent_script *script)
35363536
{
3537+
zend_class_entry *ce;
3538+
zend_op_array *op_array;
3539+
3540+
zend_shared_alloc_init_xlat_table();
3541+
3542+
ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) {
3543+
if (ce->ce_flags & ZEND_ACC_TRAIT) {
3544+
ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
3545+
if (!(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
3546+
zend_shared_alloc_register_xlat_entry(op_array->opcodes, op_array);
3547+
}
3548+
} ZEND_HASH_FOREACH_END();
3549+
}
3550+
} ZEND_HASH_FOREACH_END();
3551+
35373552
if (!zend_optimize_script(&script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
35383553
return FAILURE;
35393554
}
3555+
3556+
ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) {
3557+
if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) {
3558+
ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
3559+
if (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE) {
3560+
zend_op_array *orig_op_array = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
3561+
uint32_t fn_flags = op_array->fn_flags;
3562+
zend_function *prototype = op_array->prototype;
3563+
HashTable *ht = op_array->static_variables;
3564+
*op_array = *orig_op_array;
3565+
op_array->fn_flags = fn_flags;
3566+
op_array->prototype = prototype;
3567+
op_array->static_variables = ht;
3568+
}
3569+
} ZEND_HASH_FOREACH_END();
3570+
}
3571+
} ZEND_HASH_FOREACH_END();
3572+
3573+
zend_shared_alloc_destroy_xlat_table();
3574+
35403575
ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
35413576
if (!zend_optimize_script(&script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
35423577
return FAILURE;
@@ -3729,8 +3764,6 @@ static int accel_preload(const char *config)
37293764
script->ping_auto_globals_mask = zend_accel_get_auto_globals_no_jit();
37303765
}
37313766

3732-
zend_shared_alloc_init_xlat_table();
3733-
37343767
/* Store all functions and classes in a single pseudo-file */
37353768
filename = zend_string_init("$PRELOAD$", strlen("$PRELOAD$"), 0);
37363769
#if ZEND_USE_ABS_CONST_ADDR
@@ -3767,6 +3800,8 @@ static int accel_preload(const char *config)
37673800
return FAILURE;
37683801
}
37693802

3803+
zend_shared_alloc_init_xlat_table();
3804+
37703805
HANDLE_BLOCK_INTERRUPTIONS();
37713806
SHM_UNPROTECT();
37723807

0 commit comments

Comments
 (0)