Skip to content

Report fatal error if JIT cannot be enabled #12403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Intl:

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
Expand Down
4 changes: 4 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ PHP 8.4 UPGRADE NOTES
9. Other Changes to Extensions
========================================

- Opcache:
. If JIT is enabled, PHP will now exit with a fatal error on startup
in case of JIT startup initialization issues.

- Intl:
. The class constants are typed now.

Expand Down
13 changes: 5 additions & 8 deletions ext/opcache/ZendAccelerator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 3 additions & 11 deletions ext/opcache/jit/zend_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/jit/zend_jit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
33 changes: 10 additions & 23 deletions ext/opcache/jit/zend_jit_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -2867,7 +2867,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;
Expand All @@ -2886,7 +2886,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;
Expand Down Expand Up @@ -2918,7 +2918,6 @@ static int zend_jit_setup_stubs(void)
}
zend_jit_free_ctx(&jit);
}
return 1;
}

#define REGISTER_HELPER(n) \
Expand Down Expand Up @@ -3119,7 +3118,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;
Expand All @@ -3140,11 +3139,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)
Expand Down Expand Up @@ -3195,12 +3193,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)
Expand Down Expand Up @@ -3233,8 +3230,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
Expand All @@ -3257,8 +3253,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__)
Expand Down Expand Up @@ -3343,17 +3338,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)
Expand Down
14 changes: 6 additions & 8 deletions ext/opcache/jit/zend_jit_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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!");
}
}

Expand All @@ -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)
Expand Down