From 11946e9ef705cd39589871c2f8bb2b9d49ed0d8c Mon Sep 17 00:00:00 2001 From: wxue1 Date: Wed, 10 Aug 2022 17:55:01 -0700 Subject: [PATCH] Stop JIT hot spot counting When max_root_trace is reached, JIT in tracing mode will not compile any new code for root trace and side trace, but counting hot code is still going on. This patch stops counting as soon as possible by replacing counter handler with original handler, which increases 1.5% performance. Signed-off-by: Wang, Xue --- ext/opcache/jit/zend_jit_trace.c | 69 ++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 47667cb22490..6cce126d17d7 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -7125,6 +7125,74 @@ static zend_jit_trace_stop zend_jit_compile_root_trace(zend_jit_trace_rec *trace return ret; } +/* Set counting handler back to original VM handler. */ +static void zend_jit_stop_hot_trace_counters(zend_op_array *op_array) +{ + zend_jit_op_array_trace_extension *jit_extension; + uint32_t i; + + jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array); + zend_shared_alloc_lock(); + SHM_UNPROTECT(); + for (i = 0; i < op_array->last; i++) { + /* Opline with Jit-ed code handler is skipped. */ + if (jit_extension->trace_info[i].trace_flags & + (ZEND_JIT_TRACE_JITED|ZEND_JIT_TRACE_BLACKLISTED)) { + continue; + } + if (jit_extension->trace_info[i].trace_flags & + (ZEND_JIT_TRACE_START_LOOP | ZEND_JIT_TRACE_START_ENTER | ZEND_JIT_TRACE_START_RETURN)) { + op_array->opcodes[i].handler = jit_extension->trace_info[i].orig_handler; + } + } + SHM_PROTECT(); + zend_shared_alloc_unlock(); +} + +/* Get the tracing op_array. */ +static void zend_jit_stop_persistent_op_array(zend_op_array *op_array) { + zend_func_info *func_info = ZEND_FUNC_INFO(op_array); + if (!func_info) { + return; + } + if (func_info->flags & ZEND_FUNC_JIT_ON_HOT_TRACE) { + zend_jit_stop_hot_trace_counters(op_array); + } +} + +/* Get all op_arrays with counter handler. */ +static void zend_jit_stop_persistent_script(zend_persistent_script *script) { + zend_class_entry *ce; + zend_op_array *op_array; + + zend_jit_stop_persistent_op_array(&script->script.main_op_array); + + ZEND_HASH_FOREACH_PTR(&script->script.function_table, op_array) { + zend_jit_stop_persistent_op_array(op_array); + } ZEND_HASH_FOREACH_END(); + + ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) { + ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + if (op_array->type == ZEND_USER_FUNCTION) { + zend_jit_stop_persistent_op_array(op_array); + } + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); +} + +/* Get all scripts which are accelerated by JIT */ +static void zend_jit_stop_counter_handlers() { + for (uint32_t i = 0; i < ZCSG(hash).max_num_entries; i++) { + zend_accel_hash_entry *cache_entry; + for (cache_entry = ZCSG(hash).hash_table[i]; cache_entry; cache_entry = cache_entry->next) { + zend_persistent_script *script; + if (cache_entry->indirect) continue; + script = (zend_persistent_script *)cache_entry->data; + zend_jit_stop_persistent_script(script); + } + } +} + static void zend_jit_blacklist_root_trace(const zend_op *opline, size_t offset) { zend_shared_alloc_lock(); @@ -7505,6 +7573,7 @@ int ZEND_FASTCALL zend_jit_trace_hot_root(zend_execute_data *execute_data, const if (ZEND_JIT_TRACE_NUM >= JIT_G(max_root_traces)) { stop = ZEND_JIT_TRACE_STOP_TOO_MANY_TRACES; + zend_jit_stop_counter_handlers(); goto abort; }