Skip to content

Instantly share code, notes, and snippets.

@dstogov
Created November 17, 2021 15:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dstogov/22404cf96ac1067899488edb3601954d to your computer and use it in GitHub Desktop.
Save dstogov/22404cf96ac1067899488edb3601954d to your computer and use it in GitHub Desktop.
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index 6f7fef32a0..151afadec2 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -726,10 +726,25 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) {
/* Fast class cache */
#define ZSTR_HAS_CE_CACHE(s) (GC_FLAGS(s) & IS_STR_CLASS_NAME_MAP_PTR)
-#define ZSTR_GET_CE_CACHE(s) \
- (*(zend_class_entry **)ZEND_MAP_PTR_OFFSET2PTR(GC_REFCOUNT(s)))
-#define ZSTR_SET_CE_CACHE(s, ce) do { \
- *((zend_class_entry **)ZEND_MAP_PTR_OFFSET2PTR(GC_REFCOUNT(s))) = ce; \
+#define ZSTR_GET_CE_CACHE(s) ZSTR_GET_CE_CACHE_EX(s, 1)
+#define ZSTR_SET_CE_CACHE(s, ce) ZSTR_SET_CE_CACHE_EX(s, ce, 1)
+
+#define ZSTR_VALID_CE_CACHE(s) EXPECTED((GC_REFCOUNT(s)-1)/sizeof(void *) < CG(map_ptr_last))
+
+#define ZSTR_GET_CE_CACHE_EX(s, validate) \
+ ((!(validate) || ZSTR_VALID_CE_CACHE(s)) ? GET_CE_CACHE(GC_REFCOUNT(s)) : NULL)
+
+#define ZSTR_SET_CE_CACHE_EX(s, ce, validate) do { \
+ if (!(validate) || ZSTR_VALID_CE_CACHE(s)) { \
+ SET_CE_CACHE(GC_REFCOUNT(s), ce); \
+ } \
+ } while (0)
+
+#define GET_CE_CACHE(ce_cache) \
+ (*(zend_class_entry **)ZEND_MAP_PTR_OFFSET2PTR(ce_cache))
+
+#define SET_CE_CACHE(ce_cache, ce) do { \
+ *((zend_class_entry **)ZEND_MAP_PTR_OFFSET2PTR(ce_cache)) = ce; \
} while (0)
/* Recursion protection macros must be used only for arrays and objects */
diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c
index 002ea3e5d2..28b458235c 100644
--- a/ext/opcache/zend_accelerator_util_funcs.c
+++ b/ext/opcache/zend_accelerator_util_funcs.c
@@ -220,7 +220,7 @@ static void zend_accel_class_hash_copy(HashTable *target, HashTable *source)
if ((ce->ce_flags & ZEND_ACC_LINKED)
&& ZSTR_HAS_CE_CACHE(ce->name)
&& ZSTR_VAL(p->key)[0]) {
- ZSTR_SET_CE_CACHE(ce->name, ce);
+ ZSTR_SET_CE_CACHE_EX(ce->name, ce, 0);
}
}
}
diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c
index 0523f052eb..c438e6b38b 100644
--- a/ext/opcache/zend_persist.c
+++ b/ext/opcache/zend_persist.c
@@ -889,7 +889,7 @@ zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce)
if (!(ce->ce_flags & ZEND_ACC_CACHED)) {
if (ZSTR_HAS_CE_CACHE(ce->name)) {
- ZSTR_SET_CE_CACHE(ce->name, NULL);
+ ZSTR_SET_CE_CACHE_EX(ce->name, NULL, 0);
}
zend_accel_store_interned_string(ce->name);
if (!(ce->ce_flags & ZEND_ACC_ANON_CLASS)
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index e06d3ca672..4132a7e8aa 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -2286,11 +2286,14 @@ static zend_class_entry* zend_accel_inheritance_cache_get(zend_class_entry *ce,
entry = zend_accel_inheritance_cache_find(entry, ce, parent, traits_and_interfaces, &needs_autoload);
if (entry) {
if (!needs_autoload) {
+ replay_warnings(entry->num_warnings, entry->warnings);
if (ZCSG(map_ptr_last) > CG(map_ptr_last)) {
zend_map_ptr_extend(ZCSG(map_ptr_last));
}
- replay_warnings(entry->num_warnings, entry->warnings);
- return entry->ce;
+ ce = entry->ce;
+ ZEND_ASSERT(ZSTR_HAS_CE_CACHE(ce->name));
+ ZSTR_SET_CE_CACHE_EX(ce->name, ce, 0);
+ return ce;
}
for (i = 0; i < entry->dependencies_count; i++) {
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index 3a4aaba0a3..55d67a5914 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -2768,9 +2768,6 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
}
zv = zend_hash_find_known_hash(CG(class_table), key);
Z_CE_P(zv) = ret;
- if (ZSTR_HAS_CE_CACHE(ret->name)) {
- ZSTR_SET_CE_CACHE(ret->name, ret);
- }
return ret;
}
@@ -2995,9 +2992,6 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_
if (UNEXPECTED(!register_early_bound_ce(delayed_early_binding, lcname, ret))) {
return NULL;
}
- if (ZSTR_HAS_CE_CACHE(ret->name)) {
- ZSTR_SET_CE_CACHE(ret->name, ret);
- }
return ret;
}
} else {
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 3a107427f6..fed3ae1d29 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -1062,10 +1062,12 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *
zval *zv;
zend_string *lc_name;
zend_string *autoload_name;
+ uint32_t ce_cache = 0;
- if (ZSTR_HAS_CE_CACHE(name)) {
- ce = ZSTR_GET_CE_CACHE(name);
- if (ce) {
+ if (ZSTR_HAS_CE_CACHE(name) && ZSTR_VALID_CE_CACHE(name)) {
+ ce_cache = GC_REFCOUNT(name);
+ ce = GET_CE_CACHE(ce_cache);
+ if (EXPECTED(ce)) {
return ce;
}
}
@@ -1106,9 +1108,9 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *
}
/* Don't populate CE_CACHE for mutable classes during compilation.
* The class may be freed while persisting. */
- if (ZSTR_HAS_CE_CACHE(name) &&
+ if (ce_cache &&
(!CG(in_compilation) || (ce->ce_flags & ZEND_ACC_IMMUTABLE))) {
- ZSTR_SET_CE_CACHE(name, ce);
+ SET_CE_CACHE(ce_cache, ce);
}
return ce;
}
@@ -1164,8 +1166,8 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *
}
if (ce) {
ZEND_ASSERT(!CG(in_compilation));
- if (ZSTR_HAS_CE_CACHE(name)) {
- ZSTR_SET_CE_CACHE(name, ce);
+ if (ce_cache) {
+ SET_CE_CACHE(ce_cache, ce);
}
}
return ce;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment