@@ -954,6 +954,50 @@ static bool zend_get_inheritance_binding_full(
954954 return false;
955955}
956956
957+ static bool zend_get_inheritance_binding_full_cached (
958+ const zend_class_entry * ce ,
959+ const zend_class_entry * target ,
960+ zend_type * out_args ,
961+ uint32_t out_capacity ,
962+ uint32_t * out_arity )
963+ {
964+ zend_inheritance_binding_cache * cache = CG (inheritance_binding_cache );
965+ if (cache && cache -> present && cache -> ce == ce && cache -> target == target ) {
966+ if (!cache -> valid ) {
967+ return false;
968+ }
969+
970+ if (cache -> arity > out_capacity ) {
971+ return false;
972+ }
973+
974+ for (uint32_t i = 0 ; i < cache -> arity ; i ++ ) {
975+ out_args [i ] = cache -> args [i ];
976+ }
977+
978+ * out_arity = cache -> arity ;
979+ return true;
980+ }
981+
982+ bool result = zend_get_inheritance_binding_full (
983+ ce , target , out_args , out_capacity , out_arity );
984+
985+ if (cache ) {
986+ cache -> ce = ce ;
987+ cache -> target = target ;
988+ cache -> present = true;
989+ cache -> valid = result ;
990+ if (result && * out_arity <= ZEND_GENERIC_MAX_PARAMS ) {
991+ cache -> arity = * out_arity ;
992+ for (uint32_t i = 0 ; i < * out_arity ; i ++ ) {
993+ cache -> args [i ] = out_args [i ];
994+ }
995+ }
996+ }
997+
998+ return result ;
999+ }
1000+
9571001/* Fills out_args with target_ce's parameter defaults if every parameter
9581002 * has one. */
9591003static bool zend_get_target_default_args (
@@ -997,7 +1041,7 @@ static zend_type zend_substitute_proto_type(
9971041
9981042 zend_type args [ZEND_GENERIC_MAX_PARAMS ];
9991043 uint32_t arity ;
1000- if (!zend_get_inheritance_binding_full (ce , proto_scope , args , ZEND_GENERIC_MAX_PARAMS , & arity )
1044+ if (!zend_get_inheritance_binding_full_cached (ce , proto_scope , args , ZEND_GENERIC_MAX_PARAMS , & arity )
10011045 && !zend_get_target_default_args (proto_scope , args , ZEND_GENERIC_MAX_PARAMS , & arity )) {
10021046 return fallback ;
10031047 }
@@ -1547,7 +1591,7 @@ static zend_function *zend_maybe_substitute_inherited_method(
15471591 zend_class_entry * defining_ce = parent_fn -> common .scope ;
15481592 zend_type bound_args [ZEND_GENERIC_MAX_PARAMS ];
15491593 uint32_t bound_arity = 0 ;
1550- bool have = zend_get_inheritance_binding_full (
1594+ bool have = zend_get_inheritance_binding_full_cached (
15511595 ce , defining_ce , bound_args , ZEND_GENERIC_MAX_PARAMS , & bound_arity );
15521596
15531597 if (!have ) {
@@ -1907,7 +1951,7 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke
19071951 const zend_type * pre_erasure = (const zend_type * ) Z_PTR_P (zv );
19081952 zend_type bound_args [ZEND_GENERIC_MAX_PARAMS ];
19091953 uint32_t bound_arity = 0 ;
1910- bool have_args = zend_get_inheritance_binding_full (
1954+ bool have_args = zend_get_inheritance_binding_full_cached (
19111955 ce , parent_info -> ce , bound_args , ZEND_GENERIC_MAX_PARAMS , & bound_arity );
19121956
19131957 if (!have_args ) {
@@ -2237,6 +2281,11 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par
22372281 zend_property_info * property_info ;
22382282 zend_string * key ;
22392283
2284+ zend_inheritance_binding_cache binding_cache ;
2285+ binding_cache .present = false;
2286+ zend_inheritance_binding_cache * prev_binding_cache = CG (inheritance_binding_cache );
2287+ CG (inheritance_binding_cache ) = & binding_cache ;
2288+
22402289 if (parent_ce && !(ce -> ce_flags & ZEND_ACC_INTERFACE )) {
22412290 const zend_type * extends_args = NULL ;
22422291 uint32_t arity = 0 ;
@@ -2460,6 +2509,8 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par
24602509 }
24612510 }
24622511 ce -> ce_flags |= parent_ce -> ce_flags & (ZEND_HAS_STATIC_IN_METHODS | ZEND_ACC_HAS_TYPE_HINTS | ZEND_ACC_HAS_READONLY_PROPS | ZEND_ACC_USE_GUARDS | ZEND_ACC_NOT_SERIALIZABLE | ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES );
2512+
2513+ CG (inheritance_binding_cache ) = prev_binding_cache ;
24632514}
24642515/* }}} */
24652516
@@ -4339,7 +4390,7 @@ static void zend_diamond_collect_via_provider(
43394390
43404391 zend_type via [ZEND_GENERIC_MAX_PARAMS ];
43414392 uint32_t via_arity ;
4342- if (!zend_get_inheritance_binding_full (provider , target , via , ZEND_GENERIC_MAX_PARAMS , & via_arity )) continue ;
4393+ if (!zend_get_inheritance_binding_full_cached (provider , target , via , ZEND_GENERIC_MAX_PARAMS , & via_arity )) continue ;
43434394
43444395 if (ce_to_provider ) {
43454396 for (uint32_t j = 0 ; j < via_arity ; j ++ ) {
0 commit comments