Commit 523a75eea92 for php.net
commit 523a75eea9228ddd631eb64b8055456a68cf4c8c
Author: Weilin Du <weilindu@php.net>
Date: Tue Aug 4 00:08:45 2026 +0800
Zend: factor out guarded lazy-proxy forwarding in object handlers (#22983)
Refactor out duplicate logic to make the code looks more sensible.
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 313113d7dc2..754f603100c 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -669,6 +669,23 @@ ZEND_API uint32_t *zend_get_recursion_guard(zend_object *zobj)
return &Z_GUARD_P(zv);
}
+static zend_always_inline zend_object *zend_lazy_proxy_get_guarded_instance(
+ zend_object *zobj, zend_string *name, uint32_t guard_type)
+{
+ if (UNEXPECTED(zend_object_is_lazy_proxy(zobj)
+ && zend_lazy_object_initialized(zobj))) {
+ zend_object *instance = zend_lazy_object_get_instance(zobj);
+ if (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS) {
+ uint32_t *instance_guard = zend_get_property_guard(instance, name);
+ if ((*instance_guard) & guard_type) {
+ return instance;
+ }
+ }
+ }
+
+ return NULL;
+}
+
ZEND_COLD static void zend_typed_property_uninitialized_access(const zend_property_info *prop_info, zend_string *name)
{
zend_throw_error(NULL, "Typed property %s::$%s must not be accessed before initialization",
@@ -896,21 +913,16 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
* guard is already set for this property, we are inside a recursive
* call from the real instance's __get/__isset. Forward directly to
* the real instance to avoid double invocation. (GH-21478) */
- if (UNEXPECTED(zend_object_is_lazy_proxy(zobj)
- && zend_lazy_object_initialized(zobj))) {
- zend_object *instance = zend_lazy_object_get_instance(zobj);
- if (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS) {
- uint32_t *instance_guard = zend_get_property_guard(instance, name);
- uint32_t guard_type = ((type == BP_VAR_IS) && zobj->ce->__isset)
- ? IN_ISSET : IN_GET;
- if ((*instance_guard) & guard_type) {
- retval = zend_std_read_property(instance, name, type, cache_slot, rv);
- if (retval == &EG(uninitialized_zval)) {
- ZVAL_NULL(rv);
- retval = rv;
- }
- return retval;
+ {
+ zend_object *instance = zend_lazy_proxy_get_guarded_instance(zobj, name,
+ ((type == BP_VAR_IS) && zobj->ce->__isset) ? IN_ISSET : IN_GET);
+ if (instance) {
+ retval = zend_std_read_property(instance, name, type, cache_slot, rv);
+ if (retval == &EG(uninitialized_zval)) {
+ ZVAL_NULL(rv);
+ retval = rv;
}
+ return retval;
}
}
@@ -1262,14 +1274,10 @@ found:;
/* For initialized lazy proxies: if the real instance's __set guard
* is already set, we are inside a recursive call from the real
* instance's __set. Forward directly to avoid double invocation. */
- if (UNEXPECTED(zend_object_is_lazy_proxy(zobj)
- && zend_lazy_object_initialized(zobj))) {
- zend_object *instance = zend_lazy_object_get_instance(zobj);
- if (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS) {
- uint32_t *instance_guard = zend_get_property_guard(instance, name);
- if ((*instance_guard) & IN_SET) {
- return zend_std_write_property(instance, name, value, cache_slot);
- }
+ {
+ zend_object *instance = zend_lazy_proxy_get_guarded_instance(zobj, name, IN_SET);
+ if (instance) {
+ return zend_std_write_property(instance, name, value, cache_slot);
}
}
@@ -1670,15 +1678,11 @@ ZEND_API void zend_std_unset_property(zend_object *zobj, zend_string *name, void
/* For initialized lazy proxies: if the real instance's __unset guard
* is already set, we are inside a recursive call from the real
* instance's __unset. Forward directly to avoid double invocation. */
- if (UNEXPECTED(zend_object_is_lazy_proxy(zobj)
- && zend_lazy_object_initialized(zobj))) {
- zend_object *instance = zend_lazy_object_get_instance(zobj);
- if (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS) {
- uint32_t *instance_guard = zend_get_property_guard(instance, name);
- if ((*instance_guard) & IN_UNSET) {
- zend_std_unset_property(instance, name, cache_slot);
- return;
- }
+ {
+ zend_object *instance = zend_lazy_proxy_get_guarded_instance(zobj, name, IN_UNSET);
+ if (instance) {
+ zend_std_unset_property(instance, name, cache_slot);
+ return;
}
}
@@ -2498,14 +2502,10 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has
/* For initialized lazy proxies: if the real instance's __isset guard
* is already set, we are inside a recursive call from the real
* instance's __isset. Forward directly to avoid double invocation. */
- if (UNEXPECTED(zend_object_is_lazy_proxy(zobj)
- && zend_lazy_object_initialized(zobj))) {
- zend_object *instance = zend_lazy_object_get_instance(zobj);
- if (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS) {
- uint32_t *instance_guard = zend_get_property_guard(instance, name);
- if ((*instance_guard) & IN_ISSET) {
- return zend_std_has_property(instance, name, has_set_exists, cache_slot);
- }
+ {
+ zend_object *instance = zend_lazy_proxy_get_guarded_instance(zobj, name, IN_ISSET);
+ if (instance) {
+ return zend_std_has_property(instance, name, has_set_exists, cache_slot);
}
}