From fde41bc7138e0aca374a1529640239f9e7177806 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 16 Nov 2023 20:36:34 +0100 Subject: [PATCH] Report fatal error if JIT cannot be enabled Closes GH-12403 --- NEWS | 2 ++ UPGRADING | 4 ++++ ext/opcache/ZendAccelerator.c | 13 +++++-------- ext/opcache/jit/zend_jit.c | 14 +++----------- ext/opcache/jit/zend_jit.h | 2 +- ext/opcache/jit/zend_jit_ir.c | 33 ++++++++++---------------------- ext/opcache/jit/zend_jit_trace.c | 14 ++++++-------- 7 files changed, 31 insertions(+), 51 deletions(-) diff --git a/NEWS b/NEWS index e5f43f66ec2..5221cff4a01 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,8 @@ MBString: Opcache: . Added large shared segments support for FreeBSD. (David Carlier) + . If JIT is enabled, PHP will now exit with a fatal error on startup in case + of JIT startup initialization issues. (danog) PDO_PGSQL: . Fixed GH-12423, DSN credentials being prioritized over the user/password diff --git a/UPGRADING b/UPGRADING index 5c90712f535..a7db0c144e8 100644 --- a/UPGRADING +++ b/UPGRADING @@ -163,6 +163,10 @@ PHP 8.4 UPGRADE NOTES . Added mb_trim, mb_ltrim and mb_rtrim functions. RFC: https://wiki.php.net/rfc/mb_trim +- Opcache: + . If JIT is enabled, PHP will now exit with a fatal error on startup in case + of JIT startup initialization issues. + ======================================== 7. New Classes and Interfaces ======================================== diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index a21c640d916..7201e2e91df 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3248,16 +3248,13 @@ static zend_result accel_post_startup(void) zend_shared_alloc_lock(); #ifdef HAVE_JIT if (JIT_G(enabled)) { - if (JIT_G(buffer_size) == 0 - || !ZSMMG(reserved) - || zend_jit_startup(ZSMMG(reserved), jit_size, reattached) != SUCCESS) { + if (JIT_G(buffer_size) == 0) { JIT_G(enabled) = false; JIT_G(on) = false; - /* The JIT is implicitly disabled with opcache.jit_buffer_size=0, so we don't want to - * emit a warning here. */ - if (JIT_G(buffer_size) != 0) { - zend_accel_error(ACCEL_LOG_WARNING, "Could not enable JIT!"); - } + } else if (!ZSMMG(reserved)) { + zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not enable JIT: could not use reserved buffer!"); + } else { + zend_jit_startup(ZSMMG(reserved), jit_size, reattached); } } #endif diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index bef5d2fd996..ac91fdcbb86 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -3419,7 +3419,7 @@ ZEND_EXT_API int zend_jit_check_support(void) return SUCCESS; } -ZEND_EXT_API int zend_jit_startup(void *buf, size_t size, bool reattached) +ZEND_EXT_API void zend_jit_startup(void *buf, size_t size, bool reattached) { zend_jit_halt_op = zend_get_halt_op(); zend_jit_profile_counter_rid = zend_get_op_array_extension_handle(ACCELERATOR_PRODUCT_NAME); @@ -3494,24 +3494,16 @@ ZEND_EXT_API int zend_jit_startup(void *buf, size_t size, bool reattached) } zend_jit_unprotect(); - if (zend_jit_setup() != SUCCESS) { - zend_jit_protect(); - // TODO: error reporting and cleanup ??? - return FAILURE; - } + zend_jit_setup(); zend_jit_protect(); zend_jit_init_handlers(); - if (zend_jit_trace_startup(reattached) != SUCCESS) { - return FAILURE; - } + zend_jit_trace_startup(reattached); zend_jit_unprotect(); /* save JIT buffer pos */ dasm_ptr[1] = dasm_ptr[0]; zend_jit_protect(); - - return SUCCESS; } ZEND_EXT_API void zend_jit_shutdown(void) diff --git a/ext/opcache/jit/zend_jit.h b/ext/opcache/jit/zend_jit.h index d9f0f72a4b6..06e91bb63c9 100644 --- a/ext/opcache/jit/zend_jit.h +++ b/ext/opcache/jit/zend_jit.h @@ -158,7 +158,7 @@ ZEND_EXT_API void zend_jit_init(void); ZEND_EXT_API int zend_jit_config(zend_string *jit_options, int stage); ZEND_EXT_API int zend_jit_debug_config(zend_long old_val, zend_long new_val, int stage); ZEND_EXT_API int zend_jit_check_support(void); -ZEND_EXT_API int zend_jit_startup(void *jit_buffer, size_t size, bool reattached); +ZEND_EXT_API void zend_jit_startup(void *jit_buffer, size_t size, bool reattached); ZEND_EXT_API void zend_jit_shutdown(void); ZEND_EXT_API void zend_jit_activate(void); ZEND_EXT_API void zend_jit_deactivate(void); diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 97185c2f641..758a848b383 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -2869,7 +2869,7 @@ static void *zend_jit_ir_compile(ir_ctx *ctx, size_t *size, const char *name) return entry; } -static int zend_jit_setup_stubs(void) +static void zend_jit_setup_stubs(void) { zend_jit_ctx jit; void *entry; @@ -2888,7 +2888,7 @@ static int zend_jit_setup_stubs(void) entry = zend_jit_ir_compile(&jit.ctx, &size, zend_jit_stubs[i].name); if (!entry) { zend_jit_free_ctx(&jit); - return 0; + zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not enable JIT: could not compile stub"); } zend_jit_stub_handlers[i] = entry; @@ -2920,7 +2920,6 @@ static int zend_jit_setup_stubs(void) } zend_jit_free_ctx(&jit); } - return 1; } #define REGISTER_HELPER(n) \ @@ -3121,7 +3120,7 @@ static void zend_jit_setup_disasm(void) #endif } -static int zend_jit_calc_trace_prologue_size(void) +static void zend_jit_calc_trace_prologue_size(void) { zend_jit_ctx jit_ctx; zend_jit_ctx *jit = &jit_ctx; @@ -3142,11 +3141,10 @@ static int zend_jit_calc_trace_prologue_size(void) zend_jit_free_ctx(jit); if (!entry) { - return 0; + zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not enable JIT: could not compile prologue"); } zend_jit_trace_prologue_size = size; - return 1; } #if !ZEND_WIN32 && !defined(IR_TARGET_AARCH64) @@ -3197,12 +3195,11 @@ static zend_never_inline void zend_jit_set_sp_adj_vm(void) } #endif -static int zend_jit_setup(void) +static void zend_jit_setup(void) { #if defined(IR_TARGET_X86) if (!zend_cpu_supports_sse2()) { - zend_error(E_CORE_ERROR, "CPU doesn't support SSE2"); - return FAILURE; + zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not enable JIT: CPU doesn't support SSE2"); } #endif #if defined(IR_TARGET_X86) || defined(IR_TARGET_X64) @@ -3235,8 +3232,7 @@ static int zend_jit_setup(void) offset += sizeof(void*); } if (offset >= size) { - // TODO: error message ??? - return FAILURE; + zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not enable JIT: offset >= size"); } } while(0); # elif ZEND_WIN32 @@ -3259,8 +3255,7 @@ static int zend_jit_setup(void) offset += sizeof(void*); } if (offset >= size) { - // TODO: error message ??? - return FAILURE; + zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not enable JIT: offset >= size"); } } while(0); # elif defined(__APPLE__) && defined(__x86_64__) @@ -3345,17 +3340,9 @@ static int zend_jit_setup(void) ZEND_JIT_DEBUG_IR_AFTER_SCCP|ZEND_JIT_DEBUG_IR_AFTER_SCHEDULE|ZEND_JIT_DEBUG_IR_AFTER_REGS); } - if (!zend_jit_calc_trace_prologue_size()) { - JIT_G(debug) = debug; - return FAILURE; - } - if (!zend_jit_setup_stubs()) { - JIT_G(debug) = debug; - return FAILURE; - } + zend_jit_calc_trace_prologue_size(); + zend_jit_setup_stubs(); JIT_G(debug) = debug; - - return SUCCESS; } static void zend_jit_shutdown_ir(void) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index eb4798446cc..7f263fed93d 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -46,16 +46,16 @@ static zend_always_inline const char *zend_jit_trace_star_desc(uint8_t trace_fla } } -static int zend_jit_trace_startup(bool reattached) +static void zend_jit_trace_startup(bool reattached) { if (!reattached) { zend_jit_traces = (zend_jit_trace_info*)zend_shared_alloc(sizeof(zend_jit_trace_info) * JIT_G(max_root_traces)); if (!zend_jit_traces) { - return FAILURE; + zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not allocate JIT root traces buffer!"); } zend_jit_exit_groups = (const void**)zend_shared_alloc(sizeof(void*) * (ZEND_JIT_TRACE_MAX_EXITS/ZEND_JIT_EXIT_POINTS_PER_GROUP)); if (!zend_jit_exit_groups) { - return FAILURE; + zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not allocate JIT exit groups buffer!"); } ZEND_JIT_TRACE_NUM = 1; ZEND_JIT_COUNTER_NUM = 0; @@ -67,11 +67,11 @@ static int zend_jit_trace_startup(bool reattached) } else { zend_jit_traces = ZCSG(jit_traces); if (!zend_jit_traces) { - return FAILURE; + zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not obtain JIT traces buffer!"); } zend_jit_exit_groups = ZCSG(jit_exit_groups); if (!zend_jit_exit_groups) { - return FAILURE; + zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not obtain JIT exit groups buffer!"); } } @@ -80,10 +80,8 @@ static int zend_jit_trace_startup(bool reattached) JIT_G(exit_counters) = calloc(JIT_G(max_exit_counters), 1); if (JIT_G(exit_counters) == NULL) { - return FAILURE; + zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not allocate JIT exit counters buffer!"); } - - return SUCCESS; } static const void *zend_jit_trace_allocate_exit_point(uint32_t n)