Skip to content

Commit d377467

Browse files
committed
Keep ZEND_FUNC_INFO() for all run-time JIT triggers
1 parent c3bbcff commit d377467

File tree

4 files changed

+80
-20
lines changed

4 files changed

+80
-20
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 70 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3044,15 +3044,55 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
30443044

30453045
static int zend_jit_collect_calls(zend_op_array *op_array, zend_script *script)
30463046
{
3047-
zend_func_info *func_info =
3048-
zend_arena_calloc(&CG(arena), 1, sizeof(zend_func_info));
3047+
zend_func_info *func_info;
30493048

3050-
ZEND_SET_FUNC_INFO(op_array, func_info);
3049+
if (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC ||
3050+
JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST ||
3051+
JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS) {
3052+
func_info = ZEND_FUNC_INFO(op_array);
3053+
} else {
3054+
func_info = zend_arena_calloc(&CG(arena), 1, sizeof(zend_func_info));
3055+
ZEND_SET_FUNC_INFO(op_array, func_info);
3056+
}
30513057
func_info->num_args = -1;
30523058
func_info->return_value_used = -1;
30533059
return zend_analyze_calls(&CG(arena), script, ZEND_CALL_TREE, op_array, func_info);
30543060
}
30553061

3062+
static void zend_jit_cleanup_func_info(zend_op_array *op_array)
3063+
{
3064+
zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
3065+
zend_call_info *caller_info, *callee_info;
3066+
3067+
if (func_info) {
3068+
caller_info = func_info->caller_info;
3069+
callee_info = func_info->callee_info;
3070+
3071+
if (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC ||
3072+
JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST ||
3073+
JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS) {
3074+
memset(func_info, 0, sizeof(zend_func_info));
3075+
func_info->num_args = -1;
3076+
func_info->return_value_used = -1;
3077+
} else {
3078+
ZEND_SET_FUNC_INFO(op_array, NULL);
3079+
}
3080+
3081+
while (caller_info) {
3082+
if (caller_info->caller_op_array) {
3083+
zend_jit_cleanup_func_info(caller_info->caller_op_array);
3084+
}
3085+
caller_info = caller_info->next_caller;
3086+
}
3087+
while (callee_info) {
3088+
if (callee_info->callee_func && callee_info->callee_func->type == ZEND_USER_FUNCTION) {
3089+
zend_jit_cleanup_func_info(&callee_info->callee_func->op_array);
3090+
}
3091+
callee_info = callee_info->next_callee;
3092+
}
3093+
}
3094+
}
3095+
30563096
static int zend_real_jit_func(zend_op_array *op_array, zend_script *script, const zend_op *rt_opline)
30573097
{
30583098
zend_ssa ssa;
@@ -3074,7 +3114,6 @@ static int zend_real_jit_func(zend_op_array *op_array, zend_script *script, cons
30743114

30753115
if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_OPT_FUNCS) {
30763116
if (zend_jit_collect_calls(op_array, script) != SUCCESS) {
3077-
ZEND_SET_FUNC_INFO(op_array, NULL);
30783117
goto jit_failure;
30793118
}
30803119
func_info = ZEND_FUNC_INFO(op_array);
@@ -3096,14 +3135,12 @@ static int zend_real_jit_func(zend_op_array *op_array, zend_script *script, cons
30963135
goto jit_failure;
30973136
}
30983137

3099-
if (JIT_G(opt_level) >= ZEND_JIT_LEVEL_OPT_FUNCS) {
3100-
ZEND_SET_FUNC_INFO(op_array, NULL);
3101-
}
3102-
3138+
zend_jit_cleanup_func_info(op_array);
31033139
zend_arena_release(&CG(arena), checkpoint);
31043140
return SUCCESS;
31053141

31063142
jit_failure:
3143+
zend_jit_cleanup_func_info(op_array);
31073144
zend_arena_release(&CG(arena), checkpoint);
31083145
return FAILURE;
31093146
}
@@ -3114,6 +3151,7 @@ static void ZEND_FASTCALL zend_runtime_jit(void)
31143151
zend_execute_data *execute_data = EG(current_execute_data);
31153152
zend_op_array *op_array = &EX(func)->op_array;
31163153
zend_op *opline = op_array->opcodes;
3154+
zend_jit_op_array_extension *jit_extension;
31173155

31183156
zend_shared_alloc_lock();
31193157

@@ -3127,8 +3165,8 @@ static void ZEND_FASTCALL zend_runtime_jit(void)
31273165
opline++;
31283166
}
31293167
}
3130-
opline->handler = ZEND_FUNC_INFO(op_array);
3131-
ZEND_SET_FUNC_INFO(op_array, NULL);
3168+
jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array);
3169+
opline->handler = jit_extension->orig_handler;
31323170

31333171
/* perform real JIT for this function */
31343172
zend_real_jit_func(op_array, NULL, NULL);
@@ -3147,6 +3185,7 @@ void zend_jit_check_funcs(HashTable *function_table, zend_bool is_method) {
31473185
zend_function *func;
31483186
zend_op_array *op_array;
31493187
uintptr_t counter;
3188+
zend_jit_op_array_extension *jit_extension;
31503189

31513190
ZEND_HASH_REVERSE_FOREACH_PTR(function_table, func) {
31523191
if (func->type == ZEND_INTERNAL_FUNCTION) {
@@ -3165,8 +3204,8 @@ void zend_jit_check_funcs(HashTable *function_table, zend_bool is_method) {
31653204
}
31663205
counter = (uintptr_t)ZEND_COUNTER_INFO(op_array);
31673206
ZEND_COUNTER_INFO(op_array) = 0;
3168-
opline->handler = ZEND_FUNC_INFO(op_array);
3169-
ZEND_SET_FUNC_INFO(op_array, NULL);
3207+
jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array);
3208+
opline->handler = jit_extension->orig_handler;
31703209
if (((double)counter / (double)zend_jit_profile_counter) > ZEND_JIT_PROF_THRESHOLD) {
31713210
zend_real_jit_func(op_array, NULL, NULL);
31723211
}
@@ -3190,7 +3229,6 @@ void ZEND_FASTCALL zend_jit_hot_func(zend_execute_data *execute_data, const zend
31903229
for (i = 0; i < op_array->last; i++) {
31913230
op_array->opcodes[i].handler = jit_extension->orig_handlers[i];
31923231
}
3193-
ZEND_SET_FUNC_INFO(op_array, NULL);
31943232

31953233
/* perform real JIT for this function */
31963234
zend_real_jit_func(op_array, NULL, opline);
@@ -3274,6 +3312,7 @@ ZEND_EXT_API int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
32743312
}
32753313

32763314
if (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC) {
3315+
zend_jit_op_array_extension *jit_extension;
32773316
zend_op *opline = op_array->opcodes;
32783317

32793318
/* Set run-time JIT handler */
@@ -3283,11 +3322,17 @@ ZEND_EXT_API int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
32833322
opline++;
32843323
}
32853324
}
3286-
ZEND_SET_FUNC_INFO(op_array, (void*)opline->handler);
3325+
jit_extension = (zend_jit_op_array_extension*)zend_shared_alloc(sizeof(zend_jit_op_array_extension));
3326+
memset(&jit_extension->func_info, 0, sizeof(zend_func_info));
3327+
jit_extension->func_info.num_args = -1;
3328+
jit_extension->func_info.return_value_used = -1;
3329+
jit_extension->orig_handler = (void*)opline->handler;
3330+
ZEND_SET_FUNC_INFO(op_array, (void*)jit_extension);
32873331
opline->handler = (const void*)zend_jit_runtime_jit_handler;
32883332

32893333
return SUCCESS;
32903334
} else if (JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST) {
3335+
zend_jit_op_array_extension *jit_extension;
32913336
zend_op *opline = op_array->opcodes;
32923337

32933338
ZEND_ASSERT(zend_jit_profile_jit_handler != NULL);
@@ -3297,7 +3342,12 @@ ZEND_EXT_API int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
32973342
opline++;
32983343
}
32993344
}
3300-
ZEND_SET_FUNC_INFO(op_array, (void*)opline->handler);
3345+
jit_extension = (zend_jit_op_array_extension*)zend_shared_alloc(sizeof(zend_jit_op_array_extension));
3346+
memset(&jit_extension->func_info, 0, sizeof(zend_func_info));
3347+
jit_extension->func_info.num_args = -1;
3348+
jit_extension->func_info.return_value_used = -1;
3349+
jit_extension->orig_handler = (void*)opline->handler;
3350+
ZEND_SET_FUNC_INFO(op_array, (void*)jit_extension);
33013351
opline->handler = (const void*)zend_jit_profile_jit_handler;
33023352
}
33033353

@@ -3344,7 +3394,6 @@ ZEND_EXT_API int zend_jit_script(zend_script *script)
33443394
JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS ||
33453395
JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
33463396
for (i = 0; i < call_graph.op_arrays_count; i++) {
3347-
ZEND_SET_FUNC_INFO(call_graph.op_arrays[i], NULL);
33483397
if (zend_jit_op_array(call_graph.op_arrays[i], script) != SUCCESS) {
33493398
goto jit_failure;
33503399
}
@@ -3435,8 +3484,11 @@ ZEND_EXT_API int zend_jit_script(zend_script *script)
34353484
return SUCCESS;
34363485

34373486
jit_failure:
3438-
for (i = 0; i < call_graph.op_arrays_count; i++) {
3439-
ZEND_SET_FUNC_INFO(call_graph.op_arrays[i], NULL);
3487+
if (JIT_G(trigger) == ZEND_JIT_ON_SCRIPT_LOAD ||
3488+
JIT_G(trigger) == ZEND_JIT_ON_DOC_COMMENT) {
3489+
for (i = 0; i < call_graph.op_arrays_count; i++) {
3490+
ZEND_SET_FUNC_INFO(call_graph.op_arrays[i], NULL);
3491+
}
34403492
}
34413493
zend_arena_release(&CG(arena), checkpoint);
34423494
return FAILURE;

ext/opcache/jit/zend_jit_internal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
#ifndef ZEND_JIT_INTERNAL_H
2121
#define ZEND_JIT_INTERNAL_H
2222

23+
typedef struct _zend_jit_op_array_extension {
24+
zend_func_info func_info;
25+
const void *orig_handler;
26+
} zend_jit_op_array_extension;
27+
2328
/* Profiler */
2429
extern zend_ulong zend_jit_profile_counter;
2530
extern int zend_jit_profile_counter_rid;

ext/opcache/jit/zend_jit_vm_helpers.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ void ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D)
182182
ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_profile_helper(ZEND_OPCODE_HANDLER_ARGS)
183183
{
184184
zend_op_array *op_array = (zend_op_array*)EX(func);
185-
zend_vm_opcode_handler_t handler = (zend_vm_opcode_handler_t)ZEND_FUNC_INFO(op_array);
185+
zend_jit_op_array_extension *jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array);
186+
zend_vm_opcode_handler_t handler = jit_extension->orig_handler;
186187
uintptr_t counter = (uintptr_t)ZEND_COUNTER_INFO(op_array);
187188

188189
ZEND_COUNTER_INFO(op_array) = (void*)(counter + 1);

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2166,8 +2166,10 @@ static int zend_jit_hybrid_profile_jit_stub(dasm_State **Dst)
21662166
# error "Unknown ZEND_MAP_PTR_KIND"
21672167
#endif
21682168
| inc aword [r2 + zend_jit_profile_counter_rid * sizeof(void*)]
2169-
| // handler = (const void*)ZEND_FUNC_INFO(op_array);
2169+
| // jit_extension = (const void*)ZEND_FUNC_INFO(op_array);
21702170
| mov r0, aword [r0 + offsetof(zend_op_array, reserved[zend_func_info_rid])]
2171+
| // handler = jit_extension->orig_handler
2172+
| mov r0, aword [r0 + offsetof(zend_jit_op_array_extension, orig_handler)]
21712173
| // return ((zend_vm_opcode_handler_t)handler)();
21722174
| jmp r0
21732175
return 1;

0 commit comments

Comments
 (0)