Skip to content

Commit 08c6319

Browse files
committed
fix jit
1 parent 5801720 commit 08c6319

2 files changed

Lines changed: 119 additions & 5 deletions

File tree

ext/opcache/jit/ir/ir_aarch64.dasc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5868,8 +5868,12 @@ static void ir_emit_tls(ir_ctx *ctx, ir_ref def, ir_insn *insn)
58685868
| ldr Rx(reg), [Rx(reg), #insn->op3]
58695869
|| }
58705870
||# else
5871+
|| /* op2 == 0 with no index requests the bare thread pointer (used to form
5872+
|| * &EG/&CG with an add); a real TLS var never sits at tprel offset 0. */
5873+
|| if (insn->op2 != 0 || insn->op3 != IR_NULL) {
58715874
||//??? IR_ASSERT(insn->op2 <= LDR_STR_PIMM64);
5872-
| ldr Rx(reg), [Rx(reg), #insn->op2]
5875+
| ldr Rx(reg), [Rx(reg), #insn->op2]
5876+
|| }
58735877
||# endif
58745878
||#endif
58755879
if (IR_REG_SPILLED(ctx->regs[def][0])) {

ext/opcache/jit/zend_jit_ir.c

Lines changed: 114 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,17 +205,52 @@ static size_t tsrm_ls_cache_tcb_offset = 0;
205205
static size_t tsrm_tls_index = -1;
206206
static size_t tsrm_tls_offset = -1;
207207

208+
# ifdef ZEND_EG_TLS
209+
/* When nonzero, &executor_globals_tls/&compiler_globals_tls equal the thread
210+
* pointer plus this offset, so the JIT forms them without a runtime call. */
211+
static size_t eg_tls_tcb_offset = 0;
212+
static size_t cg_tls_tcb_offset = 0;
213+
/* gottpoff yields the offset from the %fs-based thread pointer that ir_TLS(0)
214+
* loads. */
215+
# if defined(__ELF__) && defined(__x86_64__) && defined(__GNUC__) && !defined(TSRM_TLS_MODEL_DEFAULT)
216+
# define ZEND_JIT_TLS_TCB_OFFSET(sym) __extension__({ \
217+
size_t _off; \
218+
__asm__ ("movq " #sym "@gottpoff(%%rip),%0" : "=r" (_off)); \
219+
_off; \
220+
})
221+
# elif defined(__ELF__) && defined(__aarch64__) && !defined(__APPLE__) && \
222+
(defined(__GNUC__) || defined(__clang__))
223+
/* The TLS variable sits at a fixed offset from tpidr_el0 (the thread pointer
224+
* the JIT reads with mrs); compute it once on the main thread. Subtracting the
225+
* thread pointer is model-independent (works for both local- and initial-exec)
226+
* and matches tsrm_get_ls_cache_tcb_offset()'s tprel reasoning. */
227+
# define ZEND_JIT_TLS_TCB_OFFSET(sym) __extension__({ \
228+
char *_tp; \
229+
__asm__ ("mrs %0, tpidr_el0" : "=r" (_tp)); \
230+
(size_t)((char*)&(sym) - _tp); \
231+
})
232+
# else
233+
# define ZEND_JIT_TLS_TCB_OFFSET(sym) ((size_t)0)
234+
# endif
235+
# endif
236+
208237
# define EG_TLS_OFFSET(field) \
209238
(executor_globals_offset + offsetof(zend_executor_globals, field))
210239

211240
# define CG_TLS_OFFSET(field) \
212241
(compiler_globals_offset + offsetof(zend_compiler_globals, field))
213242

214-
# define jit_EG(_field) \
243+
# ifdef ZEND_EG_TLS
244+
# define jit_EG(_field) \
245+
ir_ADD_OFFSET(jit_EG_base(jit), offsetof(zend_executor_globals, _field))
246+
# define jit_CG(_field) \
247+
ir_ADD_OFFSET(jit_CG_base(jit), offsetof(zend_compiler_globals, _field))
248+
# else
249+
# define jit_EG(_field) \
215250
ir_ADD_OFFSET(jit_TLS(jit), EG_TLS_OFFSET(_field))
216-
217-
# define jit_CG(_field) \
251+
# define jit_CG(_field) \
218252
ir_ADD_OFFSET(jit_TLS(jit), CG_TLS_OFFSET(_field))
253+
# endif
219254

220255
#else
221256

@@ -299,6 +334,11 @@ typedef struct _zend_jit_ctx {
299334
int b; /* current basic block number or -1 */
300335
#ifdef ZTS
301336
ir_ref tls;
337+
# ifdef ZEND_EG_TLS
338+
ir_ref tp; /* cached thread pointer for &EG/&CG */
339+
ir_ref eg_tls; /* cached base of __thread executor_globals_tls */
340+
ir_ref cg_tls; /* cached base of __thread compiler_globals_tls */
341+
# endif
302342
#endif
303343
ir_ref fp;
304344
ir_ref poly_func_ref; /* restored from parent trace snapshot */
@@ -494,7 +534,64 @@ static void * ZEND_FASTCALL zend_jit_get_tsrm_ls_cache(void)
494534
return _tsrm_ls_cache;
495535
}
496536

497-
static ir_ref jit_TLS(zend_jit_ctx *jit)
537+
# ifdef ZEND_EG_TLS
538+
static void * ZEND_FASTCALL zend_jit_get_eg_tls(void)
539+
{
540+
return &executor_globals_tls;
541+
}
542+
static void * ZEND_FASTCALL zend_jit_get_cg_tls(void)
543+
{
544+
return &compiler_globals_tls;
545+
}
546+
547+
/* Walk the control chain back from the current point: reuse the cached ref if we
548+
* reach it (it still dominates here), but bail at a block start or a call, since
549+
* the cached value lives in a caller-saved register that a call would clobber. */
550+
static ir_ref jit_tls_reuse(zend_jit_ctx *jit, ir_ref cached)
551+
{
552+
ir_ref ref = jit->ctx.control;
553+
554+
while (cached) {
555+
if (ref == cached) {
556+
return cached;
557+
}
558+
ir_insn *insn = &jit->ctx.ir_base[ref];
559+
if (insn->op >= IR_START || insn->op == IR_CALL) {
560+
break;
561+
}
562+
ref = insn->op1;
563+
}
564+
return IR_UNUSED;
565+
}
566+
567+
/* Thread pointer, cached per basic block, used to form &EG/&CG with an add. */
568+
static ir_ref jit_TP(zend_jit_ctx *jit)
569+
{
570+
ZEND_ASSERT(jit->ctx.control);
571+
if (!jit_tls_reuse(jit, jit->tp)) {
572+
jit->tp = ir_TLS(0, IR_NULL);
573+
}
574+
return jit->tp;
575+
}
576+
577+
/* Used where the TCB offset is unknown: resolve the base via a cached call. */
578+
static ir_ref jit_GLOBALS_TLS_call(zend_jit_ctx *jit, ir_ref *cache, const void *fn)
579+
{
580+
ZEND_ASSERT(jit->ctx.control);
581+
if (!jit_tls_reuse(jit, *cache)) {
582+
*cache = ir_CALL(IR_ADDR, ir_CONST_FC_FUNC(fn));
583+
}
584+
return *cache;
585+
}
586+
# define jit_EG_base(jit) (eg_tls_tcb_offset \
587+
? ir_ADD_OFFSET(jit_TP(jit), eg_tls_tcb_offset) \
588+
: jit_GLOBALS_TLS_call((jit), &(jit)->eg_tls, zend_jit_get_eg_tls))
589+
# define jit_CG_base(jit) (cg_tls_tcb_offset \
590+
? ir_ADD_OFFSET(jit_TP(jit), cg_tls_tcb_offset) \
591+
: jit_GLOBALS_TLS_call((jit), &(jit)->cg_tls, zend_jit_get_cg_tls))
592+
# endif
593+
594+
static ZEND_ATTRIBUTE_UNUSED ir_ref jit_TLS(zend_jit_ctx *jit)
498595
{
499596
ZEND_ASSERT(jit->ctx.control);
500597
if (jit->tls) {
@@ -2821,6 +2918,11 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags)
28212918
jit->b = -1;
28222919
#ifdef ZTS
28232920
jit->tls = IR_UNUSED;
2921+
# ifdef ZEND_EG_TLS
2922+
jit->tp = IR_UNUSED;
2923+
jit->eg_tls = IR_UNUSED;
2924+
jit->cg_tls = IR_UNUSED;
2925+
# endif
28242926
#endif
28252927
jit->fp = IR_UNUSED;
28262928
jit->poly_func_ref = IR_UNUSED;
@@ -3215,6 +3317,10 @@ static void zend_jit_setup_disasm(void)
32153317
REGISTER_DATA(CG(map_ptr_base));
32163318
#else /* ZTS */
32173319
REGISTER_HELPER(zend_jit_get_tsrm_ls_cache);
3320+
# ifdef ZEND_EG_TLS
3321+
REGISTER_HELPER(zend_jit_get_eg_tls);
3322+
REGISTER_HELPER(zend_jit_get_cg_tls);
3323+
# endif
32183324
#endif
32193325
#endif
32203326
}
@@ -3434,6 +3540,10 @@ static void zend_jit_setup(bool reattached)
34343540
zend_accel_error(ACCEL_LOG_INFO,
34353541
"Could not get _tsrm_ls_cache offsets, will fallback to runtime resolution");
34363542
}
3543+
# ifdef ZEND_EG_TLS
3544+
eg_tls_tcb_offset = ZEND_JIT_TLS_TCB_OFFSET(executor_globals_tls);
3545+
cg_tls_tcb_offset = ZEND_JIT_TLS_TCB_OFFSET(compiler_globals_tls);
3546+
# endif
34373547
#endif
34383548

34393549
#if !defined(ZEND_WIN32) && !defined(IR_TARGET_AARCH64)

0 commit comments

Comments
 (0)