diff --git a/Zend/tests/nullsafe_operator/029.phpt b/Zend/tests/nullsafe_operator/029.phpt new file mode 100644 index 00000000000..2aee652140b --- /dev/null +++ b/Zend/tests/nullsafe_operator/029.phpt @@ -0,0 +1,8 @@ +--TEST-- +Refcount of constant LHS with nullsafe operator +--FILE-- +a; +?> +--EXPECTF-- +Warning: Attempt to read property "a" on array in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 28abcf272d9..ac9d5497564 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2308,6 +2308,9 @@ static void zend_short_circuiting_commit(uint32_t checkpoint, znode *result, zen static void zend_emit_jmp_null(znode *obj_node) { uint32_t jmp_null_opnum = get_next_op_number(); + if (obj_node->op_type == IS_CONST) { + Z_TRY_ADDREF(obj_node->u.constant); + } zend_emit_op(NULL, ZEND_JMP_NULL, obj_node, NULL); zend_stack_push(&CG(short_circuiting_opnums), &jmp_null_opnum); } diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 4e7929662a9..1968eff8d53 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -3953,6 +3953,9 @@ ZEND_EXT_API void zend_jit_shutdown(void) zend_jit_perf_jitdump_close(); } #endif + if (JIT_G(exit_counters)) { + free(JIT_G(exit_counters)); + } } static void zend_jit_reset_counters(void) diff --git a/ext/opcache/jit/zend_jit.h b/ext/opcache/jit/zend_jit.h index 99a0d76ae64..7afcd613c07 100644 --- a/ext/opcache/jit/zend_jit.h +++ b/ext/opcache/jit/zend_jit.h @@ -69,7 +69,6 @@ #define ZEND_JIT_TRACE_MAX_LENGTH 1024 /* max length of single trace */ #define ZEND_JIT_TRACE_MAX_EXITS 512 /* max number of side exits per trace */ -#define ZEND_JIT_TRACE_MAX_EXIT_COUNTERS 8192 /* max number of side exits for all trace */ #define ZEND_JIT_TRACE_MAX_FUNCS 30 /* max number of different functions in a single trace */ #define ZEND_JIT_TRACE_MAX_CALL_DEPTH 10 /* max depth of inlined calls */ @@ -96,6 +95,7 @@ typedef struct _zend_jit_globals { double prof_threshold; zend_long max_root_traces; /* max number of root traces */ zend_long max_side_traces; /* max number of side traces (per root trace) */ + zend_long max_exit_counters; /* max total number of side exits for all traces */ zend_long hot_loop; zend_long hot_func; zend_long hot_return; @@ -119,7 +119,7 @@ typedef struct _zend_jit_globals { uint8_t bad_root_cache_stop[ZEND_JIT_TRACE_BAD_ROOT_SLOTS]; uint32_t bad_root_slot; - uint8_t exit_counters[ZEND_JIT_TRACE_MAX_EXIT_COUNTERS]; + uint8_t *exit_counters; } zend_jit_globals; #ifdef ZTS diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index abedddec7c6..d1215b3734c 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -64,6 +64,11 @@ static int zend_jit_trace_startup(void) memset(&dummy_op_array, 0, sizeof(dummy_op_array)); dummy_op_array.fn_flags = ZEND_ACC_DONE_PASS_TWO; + JIT_G(exit_counters) = calloc(JIT_G(max_exit_counters), 1); + if (JIT_G(exit_counters) == NULL) { + return FAILURE; + } + return SUCCESS; } @@ -4579,7 +4584,7 @@ done: ZEND_ASSERT(0 && p->stop); } - if (ZEND_JIT_EXIT_COUNTERS + t->exit_count >= ZEND_JIT_TRACE_MAX_EXIT_COUNTERS) { + if (ZEND_JIT_EXIT_COUNTERS + t->exit_count >= JIT_G(max_exit_counters)) { goto jit_failure; } @@ -4788,7 +4793,7 @@ static zend_jit_trace_stop zend_jit_compile_root_trace(zend_jit_trace_rec *trace ret = ZEND_JIT_TRACE_STOP_COMPILED; } else if (t->exit_count >= ZEND_JIT_TRACE_MAX_EXITS || - ZEND_JIT_EXIT_COUNTERS + t->exit_count >= ZEND_JIT_TRACE_MAX_EXIT_COUNTERS) { + ZEND_JIT_EXIT_COUNTERS + t->exit_count >= JIT_G(max_exit_counters)) { if (t->stack_map) { efree(t->stack_map); t->stack_map = NULL; @@ -5388,7 +5393,7 @@ static zend_jit_trace_stop zend_jit_compile_side_trace(zend_jit_trace_rec *trace ret = ZEND_JIT_TRACE_STOP_COMPILED; } else if (t->exit_count >= ZEND_JIT_TRACE_MAX_EXITS || - ZEND_JIT_EXIT_COUNTERS + t->exit_count >= ZEND_JIT_TRACE_MAX_EXIT_COUNTERS) { + ZEND_JIT_EXIT_COUNTERS + t->exit_count >= JIT_G(max_exit_counters)) { if (t->stack_map) { efree(t->stack_map); t->stack_map = NULL; @@ -5766,7 +5771,9 @@ static void zend_jit_trace_init_caches(void) memset(JIT_G(bad_root_cache_stop), 0, sizeof(JIT_G(bad_root_cache_count))); JIT_G(bad_root_slot) = 0; - memset(JIT_G(exit_counters), 0, sizeof(JIT_G(exit_counters))); + if (JIT_G(exit_counters)) { + memset(JIT_G(exit_counters), 0, JIT_G(max_exit_counters)); + } } static void zend_jit_trace_reset_caches(void) diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 2e0d5e44157..7b243931b28 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -294,6 +294,7 @@ ZEND_INI_BEGIN() STD_PHP_INI_ENTRY("opcache.jit_prof_threshold" , "0.005", PHP_INI_ALL, OnUpdateReal, prof_threshold, zend_jit_globals, jit_globals) STD_PHP_INI_ENTRY("opcache.jit_max_root_traces" , "1024", PHP_INI_SYSTEM, OnUpdateLong, max_root_traces, zend_jit_globals, jit_globals) STD_PHP_INI_ENTRY("opcache.jit_max_side_traces" , "128", PHP_INI_SYSTEM, OnUpdateLong, max_side_traces, zend_jit_globals, jit_globals) + STD_PHP_INI_ENTRY("opcache.jit_max_exit_counters" , "8192", PHP_INI_SYSTEM, OnUpdateLong, max_exit_counters, zend_jit_globals, jit_globals) STD_PHP_INI_ENTRY("opcache.jit_hot_loop" , "64", PHP_INI_SYSTEM, OnUpdateCounter, hot_loop, zend_jit_globals, jit_globals) STD_PHP_INI_ENTRY("opcache.jit_hot_func" , "127", PHP_INI_SYSTEM, OnUpdateCounter, hot_func, zend_jit_globals, jit_globals) STD_PHP_INI_ENTRY("opcache.jit_hot_return" , "8", PHP_INI_SYSTEM, OnUpdateCounter, hot_return, zend_jit_globals, jit_globals) @@ -783,6 +784,7 @@ ZEND_FUNCTION(opcache_get_configuration) add_assoc_long(&directives, "opcache.jit_hot_loop", JIT_G(hot_loop)); add_assoc_long(&directives, "opcache.jit_hot_return", JIT_G(hot_return)); add_assoc_long(&directives, "opcache.jit_hot_side_exit", JIT_G(hot_side_exit)); + add_assoc_long(&directives, "opcache.jit_max_exit_counters", JIT_G(max_exit_counters)); add_assoc_long(&directives, "opcache.jit_max_loops_unroll", JIT_G(max_loops_unroll)); add_assoc_long(&directives, "opcache.jit_max_polymorphic_calls", JIT_G(max_polymorphic_calls)); add_assoc_long(&directives, "opcache.jit_max_recursive_calls", JIT_G(max_recursive_calls));