diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 4906c2947cc..d39a7c641ce 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -58,6 +58,8 @@ extern "C++" { /* Make the atomic types used by Zend available to C++ extensions. */ using std::atomic_bool; using std::atomic_int; +using std::atomic_thread_fence; +using std::memory_order_acquire; } #else # if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L diff --git a/Zend/zend_types.h b/Zend/zend_types.h index c7a44b19bd8..465798a4e6c 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -963,11 +963,16 @@ static zend_always_inline uint32_t zend_gc_delref_ex(zend_refcounted_h *p, uint3 /* Fast class cache */ static zend_always_inline bool zstr_has_ce_cache(const zend_string *s) { - static_assert(sizeof(_Atomic uint32_t) == sizeof(uint32_t), "atomic size"); - static_assert(alignof(_Atomic uint32_t) == alignof(uint32_t), "atomic align"); - static_assert(ATOMIC_INT_LOCK_FREE == 2, "not always lock-free"); +#if defined(__cplusplus) || !defined(ATOMIC_INT_LOCK_FREE) || ATOMIC_INT_LOCK_FREE != 2 + uint32_t type_info = *(const volatile uint32_t *)&GC_TYPE_INFO(s); + atomic_thread_fence(memory_order_acquire); +#else + static_assert(sizeof(_Atomic(uint32_t)) == sizeof(uint32_t), "atomic size"); + static_assert(alignof(_Atomic(uint32_t)) == alignof(uint32_t), "atomic align"); + + uint32_t type_info = atomic_load_explicit((_Atomic(uint32_t) *)&GC_TYPE_INFO(s), memory_order_acquire); +#endif - uint32_t type_info = atomic_load_explicit((_Atomic uint32_t *)&GC_TYPE_INFO(s), memory_order_acquire); return (type_info & (IS_STR_CLASS_NAME_MAP_PTR << GC_FLAGS_SHIFT)) != 0; }