From: Dmitry Stogov Date: Tue, 19 May 2020 10:35:02 +0000 (+0300) Subject: Make JIT parameters configurable through opcache.jit_... options X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8c19e611aa6c846d584d04751276c7bd7d703aea;p=php Make JIT parameters configurable through opcache.jit_... options --- diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 6d036256d9..9a04f2dc95 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -369,7 +369,7 @@ static void *dasm_link_and_encode(dasm_State **dasm_state, } else { if (JIT_G(debug) & (ZEND_JIT_DEBUG_ASM_STUBS|ZEND_JIT_DEBUG_ASM)) { zend_jit_disasm_add_symbol(name, (uintptr_t)entry, size); - if (trace_num || (JIT_G(debug) & ZEND_JIT_DEBUG_ASM_STUBS) != 0) { + if ((JIT_G(debug) & (trace_num ? ZEND_JIT_DEBUG_ASM : ZEND_JIT_DEBUG_ASM_STUBS)) != 0) { zend_jit_disasm( name, (op_array && op_array->filename) ? ZSTR_VAL(op_array->filename) : NULL, @@ -3206,7 +3206,7 @@ void zend_jit_check_funcs(HashTable *function_table, zend_bool is_method) { ZEND_COUNTER_INFO(op_array) = 0; jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array); opline->handler = jit_extension->orig_handler; - if (((double)counter / (double)zend_jit_profile_counter) > ZEND_JIT_PROF_THRESHOLD) { + if (((double)counter / (double)zend_jit_profile_counter) > JIT_G(prof_threshold)) { zend_real_jit_func(op_array, NULL, NULL); } } @@ -3651,7 +3651,7 @@ ZEND_EXT_API int zend_jit_config(zend_string *jit, int stage) } failure: - zend_error(E_WARNING, "Invalid opcache.jit setting. Should be \"disable\", \"on\", \"off\" or 4-digit number"); + zend_error(E_WARNING, "Invalid \"opcache.jit\" setting. Should be \"disable\", \"on\", \"off\" or 4-digit number"); JIT_G(enabled) = 0; JIT_G(on) = 0; return FAILURE; diff --git a/ext/opcache/jit/zend_jit.h b/ext/opcache/jit/zend_jit.h index 3dd595d424..8c7e72c580 100644 --- a/ext/opcache/jit/zend_jit.h +++ b/ext/opcache/jit/zend_jit.h @@ -37,28 +37,10 @@ #define ZEND_JIT_REG_ALLOC_GLOBAL (1<<1) /* global linear scan register allocation */ #define ZEND_JIT_CPU_AVX (1<<2) /* use AVX instructions, if available */ -//#define ZEND_JIT_LEVEL(n) ((n) % 10) -//#define ZEND_JIT_TRIGGER(n) (((n) / 10) % 10) -//#define ZEND_JIT_REG_ALLOC(n) (((n) / 100) % 10) -//#define ZEND_JIT_CPU_FLAGS(n) (((n) / 1000) % 10) - #define ZEND_JIT_DEFAULT_OPTIONS "1205" #define ZEND_JIT_DEFAULT_BUFFER_SIZE "0" - -/* Makes profile based JIT (opcache.jit=2*) to generate code only for most - * often called functions (above the threshold). - * TODO: this setting should be configurable - */ -#define ZEND_JIT_PROF_THRESHOLD 0.005 - -/* Hot/Trace Counters based JIT parameters. - * TODO: this setting should be configurable - */ -#define ZEND_JIT_COUNTER_FUNC_COST 1 -#define ZEND_JIT_COUNTER_RET_COST 15 -#define ZEND_JIT_COUNTER_LOOP_COST 2 -#define ZEND_JIT_COUNTER_INIT 127 +#define ZEND_JIT_COUNTER_INIT 32531 #define ZEND_JIT_DEBUG_ASM (1<<0) #define ZEND_JIT_DEBUG_SSA (1<<1) @@ -93,14 +75,7 @@ #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 */ #define ZEND_JIT_TRACE_MAX_RET_DEPTH 4 /* max depth of inlined returns */ -#define ZEND_JIT_TRACE_MAX_RECURSION 2 /* max number of recursive inlined calls */ -#define ZEND_JIT_TRACE_MAX_UNROLL_LOOPS 8 /* max number of unrolled loops */ - -#define ZEND_JIT_TRACE_HOT_SIDE_COUNT 8 /* number of exits before taking side trace */ -#define ZEND_JIT_TRACE_HOT_RETURN_COUNT 8 /* number of returns before taking continuation trace */ - -#define ZEND_JIT_TRACE_MAX_ROOT_FAILURES 16 /* number of attempts to record/compile a root trace */ -#define ZEND_JIT_TRACE_MAX_SIDE_FAILURES 4 /* number of attempts to record/compile a side trace */ +#define ZEND_JIT_TRACE_MAX_LOOPS_UNROLL 10 /* max number of unrolled loops */ #define ZEND_JIT_TRACE_BAD_ROOT_SLOTS 64 /* number of slots in bad root trace cache */ @@ -119,6 +94,15 @@ typedef struct _zend_jit_globals { zend_long buffer_size; zend_long debug; zend_long bisect_limit; + double prof_threshold; + zend_long hot_loop; + zend_long hot_func; + zend_long hot_return; + zend_long hot_side_exit; /* number of exits before taking side trace */ + zend_long blacklist_root_trace; /* number of attempts to JIT a root trace before blacklist it */ + zend_long blacklist_side_trace; /* number of attempts to JIT a side trace before blacklist it */ + zend_long max_recursion_unroll; /* max number of recursive inlined calls/returns unrolls */ + zend_long max_loops_unroll; /* max number of unrolled loops */ zend_sym_node *symbols; /* symbols for disassembler */ diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 5ab3789c55..71f2ab642d 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -4342,7 +4342,7 @@ static zend_bool zend_jit_trace_is_bad_root(const zend_op *opline, zend_jit_trac for (i = 0; i < ZEND_JIT_TRACE_BAD_ROOT_SLOTS; i++) { if (cache_opline[i] == opline) { - if (cache_count[i] >= ZEND_JIT_TRACE_MAX_ROOT_FAILURES - 1) { + if (cache_count[i] >= JIT_G(blacklist_root_trace) - 1) { cache_opline[i] = NULL; return 1; } else { @@ -4749,7 +4749,7 @@ static zend_bool zend_jit_trace_exit_is_bad(uint32_t trace_num, uint32_t exit_nu uint8_t *counter = JIT_G(exit_counters) + zend_jit_traces[trace_num].exit_counters + exit_num; - if (*counter + 1 >= ZEND_JIT_TRACE_HOT_SIDE_COUNT + ZEND_JIT_TRACE_MAX_SIDE_FAILURES) { + if (*counter + 1 >= JIT_G(hot_side_exit) + JIT_G(blacklist_side_trace)) { return 1; } (*counter)++; @@ -4761,7 +4761,7 @@ static zend_bool zend_jit_trace_exit_is_hot(uint32_t trace_num, uint32_t exit_nu uint8_t *counter = JIT_G(exit_counters) + zend_jit_traces[trace_num].exit_counters + exit_num; - if (*counter + 1 >= ZEND_JIT_TRACE_HOT_SIDE_COUNT) { + if (*counter + 1 >= JIT_G(hot_side_exit)) { return 1; } (*counter)++; diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index f5ef32bff7..4bd5259910 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -199,7 +199,7 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_counter_helper(ZEND_OPCODE_H const zend_op *opline = EX(opline); #endif - *(jit_extension->counter) -= ZEND_JIT_COUNTER_FUNC_COST; + *(jit_extension->counter) -= ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_func) - 1) / JIT_G(hot_func)); if (UNEXPECTED(*(jit_extension->counter) <= 0)) { *(jit_extension->counter) = ZEND_JIT_COUNTER_INIT; @@ -219,7 +219,7 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_counter_helper(ZEND_OPCODE_H const zend_op *opline = EX(opline); #endif - *(jit_extension->counter) -= ZEND_JIT_COUNTER_LOOP_COST; + *(jit_extension->counter) -= ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_loop) - 1) / JIT_G(hot_loop)); if (UNEXPECTED(*(jit_extension->counter) <= 0)) { *(jit_extension->counter) = ZEND_JIT_COUNTER_INIT; @@ -313,17 +313,20 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_trace_c ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_trace_helper(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_OPCODE_TAIL_CALL_EX(zend_jit_trace_counter_helper, ZEND_JIT_COUNTER_FUNC_COST); + ZEND_OPCODE_TAIL_CALL_EX(zend_jit_trace_counter_helper, + ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_func) - 1) / JIT_G(hot_func))); } ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_ret_trace_helper(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_OPCODE_TAIL_CALL_EX(zend_jit_trace_counter_helper, ZEND_JIT_COUNTER_RET_COST); + ZEND_OPCODE_TAIL_CALL_EX(zend_jit_trace_counter_helper, + ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_return) - 1) / JIT_G(hot_return))); } ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_trace_helper(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_OPCODE_TAIL_CALL_EX(zend_jit_trace_counter_helper, ZEND_JIT_COUNTER_LOOP_COST); + ZEND_OPCODE_TAIL_CALL_EX(zend_jit_trace_counter_helper, + ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_loop) - 1) / JIT_G(hot_loop))); } #define TRACE_RECORD(_op, _info, _ptr) \ @@ -413,7 +416,7 @@ static int zend_jit_trace_bad_inner_loop(const zend_op *opline) if (cache_opline[i] == opline) { if ((cache_stop[i] == ZEND_JIT_TRACE_STOP_INNER_LOOP || cache_stop[i] == ZEND_JIT_TRACE_STOP_LOOP_EXIT) - && cache_count[i] > ZEND_JIT_TRACE_MAX_ROOT_FAILURES / 2) { + && cache_count[i] > JIT_G(blacklist_root_trace) / 2) { return 1; } break; @@ -432,7 +435,7 @@ static int zend_jit_trace_bad_compiled_loop(const zend_op *opline) for (i = 0; i < ZEND_JIT_TRACE_BAD_ROOT_SLOTS; i++) { if (cache_opline[i] == opline) { if (cache_stop[i] == ZEND_JIT_TRACE_STOP_COMPILED_LOOP - && cache_count[i] >= ZEND_JIT_TRACE_MAX_ROOT_FAILURES - 1) { + && cache_count[i] >= JIT_G(blacklist_root_trace) - 1) { return 1; } break; @@ -451,7 +454,7 @@ static int zend_jit_trace_bad_loop_exit(const zend_op *opline) for (i = 0; i < ZEND_JIT_TRACE_BAD_ROOT_SLOTS; i++) { if (cache_opline[i] == opline) { if (cache_stop[i] == ZEND_JIT_TRACE_STOP_LOOP_EXIT - && cache_count[i] >= ZEND_JIT_TRACE_MAX_ROOT_FAILURES - 1) { + && cache_count[i] >= JIT_G(blacklist_root_trace) - 1) { return 1; } break; @@ -524,9 +527,6 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, int backtrack_ret_recursion_level = 0; int loop_unroll_limit = 0; const zend_op_array *unrolled_calls[ZEND_JIT_TRACE_MAX_CALL_DEPTH + ZEND_JIT_TRACE_MAX_RET_DEPTH]; -#if ZEND_JIT_DETECT_UNROLLED_LOOPS - uint32_t unrolled_loops[ZEND_JIT_TRACE_MAX_UNROLL_LOOPS]; -#endif zend_bool is_toplevel; #ifdef HAVE_GCC_GLOBAL_REGS zend_execute_data *prev_execute_data = ex; @@ -693,12 +693,12 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, count = zend_jit_trace_recursive_call_count(&EX(func)->op_array, unrolled_calls, ret_level, level); if (opline == orig_opline) { - if (count + 1 >= ZEND_JIT_TRACE_MAX_RECURSION) { + if (count + 1 >= JIT_G(max_recursion_unroll)) { stop = ZEND_JIT_TRACE_STOP_RECURSIVE_CALL; break; } backtrack_recursion = idx; - } else if (count >= ZEND_JIT_TRACE_MAX_RECURSION) { + } else if (count >= JIT_G(max_recursion_unroll)) { stop = ZEND_JIT_TRACE_STOP_DEEP_RECURSION; break; } @@ -725,13 +725,13 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, TRACE_RECORD(ZEND_JIT_TRACE_BACK, 0, &EX(func)->op_array); count = zend_jit_trace_recursive_ret_count(&EX(func)->op_array, unrolled_calls, ret_level); if (opline == orig_opline) { - if (count + 1 >= ZEND_JIT_TRACE_MAX_RECURSION) { + if (count + 1 >= JIT_G(max_recursion_unroll)) { stop = ZEND_JIT_TRACE_STOP_RECURSIVE_RET; break; } backtrack_ret_recursion = idx; backtrack_ret_recursion_level = ret_level; - } else if (count >= ZEND_JIT_TRACE_MAX_RECURSION) { + } else if (count >= JIT_G(max_recursion_unroll)) { stop = ZEND_JIT_TRACE_STOP_DEEP_RECURSION; break; } @@ -828,7 +828,7 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, break; } } - if (loop_unroll_limit < ZEND_JIT_TRACE_MAX_UNROLL_LOOPS) { + if (loop_unroll_limit < JIT_G(max_loops_unroll)) { loop_unroll_limit++; } else { stop = ZEND_JIT_TRACE_STOP_LOOP_UNROLL; diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 3bb981ecb7..ab5db6498b 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -2209,7 +2209,7 @@ static int zend_jit_hybrid_func_hot_counter_stub(dasm_State **Dst) | mov r0, EX->func | mov r1, aword [r0 + offsetof(zend_op_array, reserved[zend_func_info_rid])] | mov r2, aword [r1 + offsetof(zend_jit_op_array_hot_extension, counter)] - | sub word [r2], ZEND_JIT_COUNTER_FUNC_COST + | sub word [r2], ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_func) - 1) / JIT_G(hot_func)) | jle >1 | GET_IP r2 | sub r2, aword [r0 + offsetof(zend_op_array, opcodes)] @@ -2246,7 +2246,7 @@ static int zend_jit_hybrid_loop_hot_counter_stub(dasm_State **Dst) | mov r0, EX->func | mov r1, aword [r0 + offsetof(zend_op_array, reserved[zend_func_info_rid])] | mov r2, aword [r1 + offsetof(zend_jit_op_array_hot_extension, counter)] - | sub word [r2], ZEND_JIT_COUNTER_LOOP_COST + | sub word [r2], ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_loop) - 1) / JIT_G(hot_loop)) | jle >1 | GET_IP r2 | sub r2, aword [r0 + offsetof(zend_op_array, opcodes)] @@ -2305,7 +2305,8 @@ static int zend_jit_hybrid_func_trace_counter_stub(dasm_State **Dst) |->hybrid_func_trace_counter: - return zend_jit_hybrid_trace_counter_stub(Dst, ZEND_JIT_COUNTER_FUNC_COST); + return zend_jit_hybrid_trace_counter_stub(Dst, + ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_func) - 1) / JIT_G(hot_func))); } static int zend_jit_hybrid_ret_trace_counter_stub(dasm_State **Dst) @@ -2316,7 +2317,8 @@ static int zend_jit_hybrid_ret_trace_counter_stub(dasm_State **Dst) |->hybrid_ret_trace_counter: - return zend_jit_hybrid_trace_counter_stub(Dst, ZEND_JIT_COUNTER_RET_COST); + return zend_jit_hybrid_trace_counter_stub(Dst, + ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_return) - 1) / JIT_G(hot_return))); } static int zend_jit_hybrid_loop_trace_counter_stub(dasm_State **Dst) @@ -2327,7 +2329,8 @@ static int zend_jit_hybrid_loop_trace_counter_stub(dasm_State **Dst) |->hybrid_loop_trace_counter: - return zend_jit_hybrid_trace_counter_stub(Dst, ZEND_JIT_COUNTER_LOOP_COST); + return zend_jit_hybrid_trace_counter_stub(Dst, + ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_loop) - 1) / JIT_G(hot_loop))); } static int zend_jit_trace_halt_stub(dasm_State **Dst) diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index ec721f77b8..4ed15ff41b 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -214,6 +214,44 @@ static ZEND_INI_MH(OnUpdateJitDebug) } return FAILURE; } + +static ZEND_INI_MH(OnUpdateCounter) +{ + zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + if (val > 0 && val < 256) { + zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); + *p = val; + return SUCCESS; + } + zend_error(E_WARNING, "Invalid \"%s\" setting. Should be between 1 and 256", ZSTR_VAL(entry->name)); + return FAILURE; +} + +static ZEND_INI_MH(OnUpdateUnrollR) +{ + zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + if (val > 0 && val < ZEND_JIT_TRACE_MAX_CALL_DEPTH && val < ZEND_JIT_TRACE_MAX_RET_DEPTH) { + zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); + *p = val; + return SUCCESS; + } + zend_error(E_WARNING, "Invalid \"%s\" setting. Should be between 1 and %d", ZSTR_VAL(entry->name), + MIN(ZEND_JIT_TRACE_MAX_CALL_DEPTH, ZEND_JIT_TRACE_MAX_CALL_DEPTH)); + return FAILURE; +} + +static ZEND_INI_MH(OnUpdateUnrollL) +{ + zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + if (val > 0 && val < ZEND_JIT_TRACE_MAX_LOOPS_UNROLL) { + zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); + *p = val; + return SUCCESS; + } + zend_error(E_WARNING, "Invalid \"%s\" setting. Should be between 1 and %d", ZSTR_VAL(entry->name), + ZEND_JIT_TRACE_MAX_LOOPS_UNROLL); + return FAILURE; +} #endif ZEND_INI_BEGIN() @@ -273,10 +311,19 @@ ZEND_INI_BEGIN() STD_PHP_INI_ENTRY("opcache.cache_id" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.cache_id, zend_accel_globals, accel_globals) #endif #ifdef HAVE_JIT - STD_PHP_INI_ENTRY("opcache.jit" , ZEND_JIT_DEFAULT_OPTIONS, PHP_INI_ALL, OnUpdateJit, options, zend_jit_globals, jit_globals) - STD_PHP_INI_ENTRY("opcache.jit_buffer_size" , ZEND_JIT_DEFAULT_BUFFER_SIZE, PHP_INI_SYSTEM, OnUpdateLong, buffer_size, zend_jit_globals, jit_globals) - STD_PHP_INI_ENTRY("opcache.jit_debug" , "0", PHP_INI_ALL, OnUpdateJitDebug, debug, zend_jit_globals, jit_globals) - STD_PHP_INI_ENTRY("opcache.jit_bisect_limit" , "0", PHP_INI_ALL, OnUpdateLong, bisect_limit, zend_jit_globals, jit_globals) + STD_PHP_INI_ENTRY("opcache.jit" , ZEND_JIT_DEFAULT_OPTIONS, PHP_INI_ALL, OnUpdateJit, options, zend_jit_globals, jit_globals) + STD_PHP_INI_ENTRY("opcache.jit_buffer_size" , ZEND_JIT_DEFAULT_BUFFER_SIZE, PHP_INI_SYSTEM, OnUpdateLong, buffer_size, zend_jit_globals, jit_globals) + STD_PHP_INI_ENTRY("opcache.jit_debug" , "0", PHP_INI_ALL, OnUpdateJitDebug, debug, zend_jit_globals, jit_globals) + STD_PHP_INI_ENTRY("opcache.jit_bisect_limit" , "0", PHP_INI_ALL, OnUpdateLong, bisect_limit, zend_jit_globals, jit_globals) + 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_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) + STD_PHP_INI_ENTRY("opcache.jit_hot_side_exit" , "8", PHP_INI_ALL, OnUpdateCounter, hot_side_exit, zend_jit_globals, jit_globals) + STD_PHP_INI_ENTRY("opcache.jit_blacklist_root_trace" , "16", PHP_INI_ALL, OnUpdateCounter, blacklist_root_trace, zend_jit_globals, jit_globals) + STD_PHP_INI_ENTRY("opcache.jit_blacklist_side_trace" , "8", PHP_INI_ALL, OnUpdateCounter, blacklist_side_trace, zend_jit_globals, jit_globals) + STD_PHP_INI_ENTRY("opcache.jit_max_recursion_unroll" , "2", PHP_INI_ALL, OnUpdateUnrollR, max_recursion_unroll, zend_jit_globals, jit_globals) + STD_PHP_INI_ENTRY("opcache.jit_max_loops_unroll" , "8", PHP_INI_ALL, OnUpdateUnrollL, max_loops_unroll, zend_jit_globals, jit_globals) #endif ZEND_INI_END()