Commit 125ffe30167 for php
commit 125ffe30167bdcc5482da06625fe523122b80677
Author: Marc <m@pyc.ac>
Date: Thu Oct 29 11:05:02 2026 +0100
JIT: recognize initial-exec TLS relaxation (#25013)
diff --git a/ext/opcache/jit/tls/testing/test.sh b/ext/opcache/jit/tls/testing/test.sh
index c6b003caafd..c49e0439a1c 100755
--- a/ext/opcache/jit/tls/testing/test.sh
+++ b/ext/opcache/jit/tls/testing/test.sh
@@ -136,8 +136,8 @@ dl_def_static_user_no_surplus() {
rm -f main
- $CC $CFLAGS -ggdb3 -fPIC -o tls.o -c $TLSC
- $CC $CFLAGS -ggdb3 -fPIC -o user.o -c user.c
+ $CC $CFLAGS -DTSRM_TLS_MODEL_USE_DEFAULT -ggdb3 -fPIC -o tls.o -c $TLSC
+ $CC $CFLAGS -DTSRM_TLS_MODEL_USE_DEFAULT -ggdb3 -fPIC -o user.o -c user.c
$CC $CFLAGS -DNO_SURPLUS -ggdb3 -fPIC -o def.o -c def.c
$CC $CFLAGS $LDFLAGS -shared -o libdef.so def.o user.o tls.o
@@ -151,8 +151,8 @@ dl_def_shared_user_no_surplus() {
rm -f main
- $CC $CFLAGS -ggdb3 -fPIC -o tls.o -c $TLSC
- $CC $CFLAGS -ggdb3 -fPIC -o user.o -c user.c
+ $CC $CFLAGS -DTSRM_TLS_MODEL_USE_DEFAULT -ggdb3 -fPIC -o tls.o -c $TLSC
+ $CC $CFLAGS -DTSRM_TLS_MODEL_USE_DEFAULT -ggdb3 -fPIC -o user.o -c user.c
$CC $CFLAGS $LDFLAGS -shared -o libuser.so user.o tls.o
$CC $CFLAGS -DNO_SURPLUS -ggdb3 -fPIC -o def.o -c def.c
diff --git a/ext/opcache/jit/tls/testing/user.c b/ext/opcache/jit/tls/testing/user.c
index c27e608f3f4..19e9f06c080 100644
--- a/ext/opcache/jit/tls/testing/user.c
+++ b/ext/opcache/jit/tls/testing/user.c
@@ -3,7 +3,7 @@
#include "../zend_jit_tls.h"
-extern __thread void* _tsrm_ls_cache;
+TSRMLS_MAIN_CACHE_EXTERN()
int test(void)
{
diff --git a/ext/opcache/jit/tls/zend_jit_tls_aarch64.c b/ext/opcache/jit/tls/zend_jit_tls_aarch64.c
index 80d19090312..d3f0467648c 100644
--- a/ext/opcache/jit/tls/zend_jit_tls_aarch64.c
+++ b/ext/opcache/jit/tls/zend_jit_tls_aarch64.c
@@ -192,18 +192,6 @@ zend_result zend_jit_resolve_tsrm_ls_cache_offsets(
/* Code was changed by the linker. Check if we recognize the updated code */
- // movz x0, #0, lsl #16
- if ((insn[0] & ~AARCH64_MOVZ_IMM_MASK) != 0xd2a00000) {
- zend_accel_error(ACCEL_LOG_DEBUG, "movz insn does not match: 0x%08" PRIx32 "\n", insn[0]);
- return FAILURE;
- }
-
- // movk x0, #0x10
- if ((insn[1] & ~AARCH64_MOVK_IMM_MASK) != 0xf2800000) {
- zend_accel_error(ACCEL_LOG_DEBUG, "movk insn does not match: 0x%08" PRIx32 "\n", insn[1]);
- return FAILURE;
- }
-
// nop
for (int i = 0; i < 2; i++) {
if (insn[2+i] != AARCH64_NOP) {
@@ -212,12 +200,29 @@ zend_result zend_jit_resolve_tsrm_ls_cache_offsets(
}
}
- /* Extract immediate values */
+ if ((insn[0] & ~AARCH64_ADRP_IMM_MASK) == 0x90000000) {
+ /* initial-exec */
+ // ldr x0, [x0, #any]
+ if ((insn[1] & ~AARCH64_LDR_UNSIGNED_IMM_MASK) != 0xf9400000) {
+ zend_accel_error(ACCEL_LOG_DEBUG, "ldr insn does not match: 0x%08" PRIx32 "\n", insn[1]);
+ return FAILURE;
+ }
+ } else {
+ /* local-exec */
+ // movz x0, #0, lsl #16
+ if ((insn[0] & ~AARCH64_MOVZ_IMM_MASK) != 0xd2a00000) {
+ zend_accel_error(ACCEL_LOG_DEBUG, "movz insn does not match: 0x%08" PRIx32 "\n", insn[0]);
+ return FAILURE;
+ }
+
+ // movk x0, #0x10
+ if ((insn[1] & ~AARCH64_MOVK_IMM_MASK) != 0xf2800000) {
+ zend_accel_error(ACCEL_LOG_DEBUG, "movk insn does not match: 0x%08" PRIx32 "\n", insn[1]);
+ return FAILURE;
+ }
+ }
- uint64_t movz_imm = (insn[0] & AARCH64_MOVZ_IMM_MASK) >> 5;
- uint64_t movz_shift = (((insn[0] & AARCH64_MOVZ_HW_MASK) >> 21) << 4);
- uint64_t movk_imm = (insn[1] & AARCH64_MOVK_IMM_MASK) >> 5;
- uint64_t offset = (movz_imm << movz_shift) | movk_imm;
+ uintptr_t offset = (uintptr_t)addr - (uintptr_t)thread_pointer;
if ((uintptr_t)&_tsrm_ls_cache - (uintptr_t)thread_pointer == offset) {
zend_accel_error(ACCEL_LOG_DEBUG, "static tls at offset %" PRIxPTR " from thread pointer (inferred from code)\n", offset);
diff --git a/ext/opcache/jit/tls/zend_jit_tls_x86_64.c b/ext/opcache/jit/tls/zend_jit_tls_x86_64.c
index f3495505c52..c67d72e3371 100644
--- a/ext/opcache/jit/tls/zend_jit_tls_x86_64.c
+++ b/ext/opcache/jit/tls/zend_jit_tls_x86_64.c
@@ -166,7 +166,9 @@ zend_result zend_jit_resolve_tsrm_ls_cache_offsets(
/*
* 64 48 8b 04 25 00 00 00 00 movq %fs:0x0,%rax
- * 48 8d 80 f8 ff ff ff leaq -0x8(%rax),%rax
+ * 48 8d 80 f8 ff ff ff leaq -0x8(%rax),%rax (Local Exec)
+ * or
+ * 48 03 05 xx xx xx xx addq any(%rip),%rax (Initial Exec)
*/
// movq %fs:0x0,%rax
@@ -177,20 +179,16 @@ zend_result zend_jit_resolve_tsrm_ls_cache_offsets(
return FAILURE;
}
- // leaq any(%rax),$rax
- if (memcmp(&code[9], "\x48\x8d\x80", 3) != 0) {
+ // leaq any(%rax),%rax or addq any(%rip),%rax
+ if (memcmp(&code[9], "\x48\x8d\x80", 3) != 0
+ && memcmp(&code[9], "\x48\x03\x05", 3) != 0) {
uint64_t bytes;
- memcpy(&bytes, &code[10], 8);
- zend_accel_error(ACCEL_LOG_DEBUG, "leaq insn does not match: 0x%016" PRIx64 "\n", bytes);
+ memcpy(&bytes, &code[9], 8);
+ zend_accel_error(ACCEL_LOG_DEBUG, "leaq/addq insn does not match: 0x%016" PRIx64 "\n", bytes);
return FAILURE;
}
- /* Extract immediate values */
-
- uintptr_t offset = (uintptr_t)(int32_t)(((uint32_t)code[15] << 24)
- | ((uint32_t)code[14] << 16)
- | ((uint32_t)code[13] << 8)
- | ((uint32_t)code[12]));
+ uintptr_t offset = (uintptr_t)addr - (uintptr_t)thread_pointer;
if ((uintptr_t)&_tsrm_ls_cache - (uintptr_t)thread_pointer == offset) {
*tcb_offset = offset;