@@ -201,35 +201,21 @@ static uint32_t default_mflags = 0;
201201static bool delayed_call_chain = false; // TODO: remove this var (use jit->delayed_call_level) ???
202202
203203#ifdef ZTS
204- static size_t eg_tls_tcb_offset = 0;
205- static size_t cg_tls_tcb_offset = 0;
206- /* gottpoff yields the offset from the %fs-based thread pointer that ir_TLS(0)
207- * loads. */
208- # if defined(__ELF__) && defined(__x86_64__) && defined(__GNUC__) && !defined(TSRM_TLS_MODEL_DEFAULT)
209- # define ZEND_JIT_TLS_TCB_OFFSET(sym) __extension__({ \
210- size_t _off; \
211- __asm__ ("movq " #sym "@gottpoff(%%rip),%0" : "=r" (_off)); \
212- _off; \
213- })
214- # elif defined(__ELF__) && defined(__aarch64__) && !defined(__APPLE__) && \
215- (defined(__GNUC__) || defined(__clang__))
216- /* The TLS variable sits at a fixed offset from tpidr_el0 (the thread pointer
217- * the JIT reads with mrs); compute it once on the main thread. Subtracting the
218- * thread pointer is model-independent (works for both local- and initial-exec)
219- * and matches tsrm_get_ls_cache_tcb_offset()'s tprel reasoning. */
220- # define ZEND_JIT_TLS_TCB_OFFSET(sym) __extension__({ \
221- char *_tp; \
222- __asm__ ("mrs %0, tpidr_el0" : "=r" (_tp)); \
223- (size_t)((char*)&(sym) - _tp); \
224- })
225- # else
226- # define ZEND_JIT_TLS_TCB_OFFSET(sym) ((size_t)0)
227- # endif
204+ static size_t tsrm_ls_cache_tcb_offset = 0;
205+ static size_t tsrm_tls_index = -1;
206+ static size_t tsrm_tls_offset = -1;
207+
208+ # define EG_TLS_OFFSET(field) \
209+ (tsrm_ls_cache_tcb_offset + offsetof(zend_tsrm_ls_cache, eg) + offsetof(zend_executor_globals, field))
210+
211+ # define CG_TLS_OFFSET(field) \
212+ (tsrm_ls_cache_tcb_offset + offsetof(zend_tsrm_ls_cache, cg) + offsetof(zend_compiler_globals, field))
228213
229214# define jit_EG(_field) \
230- ir_ADD_OFFSET(jit_EG_base(jit), offsetof(zend_executor_globals, _field))
215+ ir_ADD_OFFSET(jit_TLS(jit), EG_TLS_OFFSET(_field))
216+
231217# define jit_CG(_field) \
232- ir_ADD_OFFSET(jit_CG_base (jit), offsetof(zend_compiler_globals, _field))
218+ ir_ADD_OFFSET(jit_TLS (jit), CG_TLS_OFFSET( _field))
233219
234220#else
235221
@@ -312,9 +298,7 @@ typedef struct _zend_jit_ctx {
312298 uint32_t delayed_call_level;
313299 int b; /* current basic block number or -1 */
314300#ifdef ZTS
315- ir_ref tp; /* cached thread pointer for &EG/&CG */
316- ir_ref eg_tls; /* cached base of __thread executor_globals_tls */
317- ir_ref cg_tls; /* cached base of __thread compiler_globals_tls */
301+ ir_ref tls;
318302#endif
319303 ir_ref fp;
320304 ir_ref poly_func_ref; /* restored from parent trace snapshot */
@@ -505,60 +489,41 @@ static const char* zend_reg_name(int8_t reg)
505489/* IR helpers */
506490
507491#ifdef ZTS
508- static void * ZEND_FASTCALL zend_jit_get_eg_tls(void)
509- {
510- return &executor_globals_tls;
511- }
512- static void * ZEND_FASTCALL zend_jit_get_cg_tls(void)
492+ static void * ZEND_FASTCALL zend_jit_get_tsrm_ls_cache(void)
513493{
514- return &compiler_globals_tls ;
494+ return &_tsrm_ls_cache ;
515495}
516496
517- /* Walk the control chain back from the current point: reuse the cached ref if we
518- * reach it (it still dominates here), but bail at a block start or a call, since
519- * the cached value lives in a caller-saved register that a call would clobber. */
520- static ir_ref jit_tls_reuse(zend_jit_ctx *jit, ir_ref cached)
497+ static ir_ref jit_TLS(zend_jit_ctx *jit)
521498{
522- ir_ref ref = jit->ctx.control;
499+ ZEND_ASSERT(jit->ctx.control);
500+ if (jit->tls) {
501+ /* Emit "TLS" once for basic block */
502+ ir_insn *insn;
503+ ir_ref ref = jit->ctx.control;
523504
524- while (cached) {
525- if (ref == cached) {
526- return cached;
527- }
528- ir_insn *insn = &jit->ctx.ir_base[ref];
529- if (insn->op >= IR_START || insn->op == IR_CALL) {
530- break;
505+ while (1) {
506+ if (ref == jit->tls) {
507+ return jit->tls;
508+ }
509+ insn = &jit->ctx.ir_base[ref];
510+ if (insn->op >= IR_START || insn->op == IR_CALL) {
511+ break;
512+ }
513+ ref = insn->op1;
531514 }
532- ref = insn->op1;
533515 }
534- return IR_UNUSED;
535- }
536516
537- /* Thread pointer, cached per basic block, used to form &EG/&CG with an add. */
538- static ir_ref jit_TP(zend_jit_ctx *jit)
539- {
540- ZEND_ASSERT( jit->ctx.control );
541- if (!jit_tls_reuse(jit, jit->tp)) {
542- jit->tp = ir_TLS(0, IR_NULL );
517+ if (tsrm_ls_cache_tcb_offset == 0 && tsrm_tls_index == -1) {
518+ jit->tls = ir_CALL(IR_ADDR, ir_CONST_FC_FUNC(zend_jit_get_tsrm_ls_cache));
519+ } else if (tsrm_ls_cache_tcb_offset) {
520+ jit->tls = ir_TLS(0, IR_NULL );
521+ } else {
522+ jit->tls = ir_TLS(tsrm_tls_index, tsrm_tls_offset + offsetof(zend_tsrm_ls_cache, self) );
543523 }
544- return jit->tp;
545- }
546524
547- /* Used where the TCB offset is unknown: resolve the base via a cached call. */
548- static ir_ref jit_GLOBALS_TLS_call(zend_jit_ctx *jit, ir_ref *cache, const void *fn)
549- {
550- ZEND_ASSERT(jit->ctx.control);
551- if (!jit_tls_reuse(jit, *cache)) {
552- *cache = ir_CALL(IR_ADDR, ir_CONST_FC_FUNC(fn));
553- }
554- return *cache;
525+ return jit->tls;
555526}
556- # define jit_EG_base(jit) (eg_tls_tcb_offset \
557- ? ir_ADD_OFFSET(jit_TP(jit), eg_tls_tcb_offset) \
558- : jit_GLOBALS_TLS_call((jit), &(jit)->eg_tls, zend_jit_get_eg_tls))
559- # define jit_CG_base(jit) (cg_tls_tcb_offset \
560- ? ir_ADD_OFFSET(jit_TP(jit), cg_tls_tcb_offset) \
561- : jit_GLOBALS_TLS_call((jit), &(jit)->cg_tls, zend_jit_get_cg_tls))
562527#endif
563528
564529static ir_ref jit_CONST_ADDR(zend_jit_ctx *jit, uintptr_t addr)
@@ -2855,9 +2820,7 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags)
28552820 delayed_call_chain = false;
28562821 jit->b = -1;
28572822#ifdef ZTS
2858- jit->tp = IR_UNUSED;
2859- jit->eg_tls = IR_UNUSED;
2860- jit->cg_tls = IR_UNUSED;
2823+ jit->tls = IR_UNUSED;
28612824#endif
28622825 jit->fp = IR_UNUSED;
28632826 jit->poly_func_ref = IR_UNUSED;
@@ -3251,8 +3214,7 @@ static void zend_jit_setup_disasm(void)
32513214
32523215 REGISTER_DATA(CG(map_ptr_base));
32533216#else /* ZTS */
3254- REGISTER_HELPER(zend_jit_get_eg_tls);
3255- REGISTER_HELPER(zend_jit_get_cg_tls);
3217+ REGISTER_HELPER(zend_jit_get_tsrm_ls_cache);
32563218#endif
32573219#endif
32583220}
@@ -3463,8 +3425,15 @@ static void zend_jit_setup(bool reattached)
34633425#endif
34643426
34653427#ifdef ZTS
3466- eg_tls_tcb_offset = ZEND_JIT_TLS_TCB_OFFSET(executor_globals_tls);
3467- cg_tls_tcb_offset = ZEND_JIT_TLS_TCB_OFFSET(compiler_globals_tls);
3428+ zend_result result = zend_jit_resolve_tsrm_ls_cache_offsets(
3429+ &tsrm_ls_cache_tcb_offset,
3430+ &tsrm_tls_index,
3431+ &tsrm_tls_offset
3432+ );
3433+ if (result == FAILURE) {
3434+ zend_accel_error(ACCEL_LOG_INFO,
3435+ "Could not get _tsrm_ls_cache offsets, will fallback to runtime resolution");
3436+ }
34683437#endif
34693438
34703439#if !defined(ZEND_WIN32) && !defined(IR_TARGET_AARCH64)
0 commit comments