@@ -1141,10 +1141,13 @@ static bool zend_check_intersection_type_from_list(
11411141}
11421142
11431143static zend_always_inline bool zend_check_type_slow (
1144- const zend_type * type , zval * arg , const zend_reference * ref ,
1144+ const zend_type * type , zval * arg , const zend_reference * ref , void * * cache_slot ,
11451145 bool is_return_type , bool is_internal )
11461146{
11471147 if (ZEND_TYPE_IS_COMPLEX (* type ) && EXPECTED (Z_TYPE_P (arg ) == IS_OBJECT )) {
1148+ if (* cache_slot == Z_OBJCE_P (arg )) {
1149+ return true;
1150+ }
11481151 zend_class_entry * ce ;
11491152 if (UNEXPECTED (ZEND_TYPE_HAS_LIST (* type ))) {
11501153 if (ZEND_TYPE_IS_INTERSECTION (* type )) {
@@ -1154,13 +1157,15 @@ static zend_always_inline bool zend_check_type_slow(
11541157 ZEND_TYPE_LIST_FOREACH (ZEND_TYPE_LIST (* type ), list_type ) {
11551158 if (ZEND_TYPE_IS_INTERSECTION (* list_type )) {
11561159 if (zend_check_intersection_type_from_list (ZEND_TYPE_LIST (* list_type ), Z_OBJCE_P (arg ))) {
1160+ * cache_slot = (void * ) Z_OBJCE_P (arg );
11571161 return true;
11581162 }
11591163 } else {
11601164 ZEND_ASSERT (!ZEND_TYPE_HAS_LIST (* list_type ));
11611165 ce = zend_fetch_ce_from_type (list_type );
11621166 /* Instance of a single type part of a union is sufficient to pass the type check */
11631167 if (ce && instanceof_function (Z_OBJCE_P (arg ), ce )) {
1168+ * cache_slot = (void * ) Z_OBJCE_P (arg );
11641169 return true;
11651170 }
11661171 }
@@ -1171,9 +1176,10 @@ static zend_always_inline bool zend_check_type_slow(
11711176 /* If we have a CE we check if it satisfies the type constraint,
11721177 * otherwise it will check if a standard type satisfies it. */
11731178 if (ce && instanceof_function (Z_OBJCE_P (arg ), ce )) {
1179+ * cache_slot = (void * ) Z_OBJCE_P (arg );
11741180 return true;
11751181 }
1176- }
1182+ };
11771183 }
11781184
11791185 const uint32_t type_mask = ZEND_TYPE_FULL_MASK (* type );
@@ -1204,7 +1210,7 @@ static zend_always_inline bool zend_check_type_slow(
12041210}
12051211
12061212static zend_always_inline bool zend_check_type (
1207- const zend_type * type , zval * arg , zend_class_entry * scope ,
1213+ const zend_type * type , zval * arg , void * * cache_slot , zend_class_entry * scope ,
12081214 bool is_return_type , bool is_internal )
12091215{
12101216 const zend_reference * ref = NULL ;
@@ -1219,25 +1225,25 @@ static zend_always_inline bool zend_check_type(
12191225 return 1 ;
12201226 }
12211227
1222- return zend_check_type_slow (type , arg , ref , is_return_type , is_internal );
1228+ return zend_check_type_slow (type , arg , ref , cache_slot , is_return_type , is_internal );
12231229}
12241230
12251231ZEND_API bool zend_check_user_type_slow (
1226- const zend_type * type , zval * arg , const zend_reference * ref , bool is_return_type )
1232+ const zend_type * type , zval * arg , const zend_reference * ref , void * * cache_slot , bool is_return_type )
12271233{
12281234 return zend_check_type_slow (
1229- type , arg , ref , is_return_type , /* is_internal */ false);
1235+ type , arg , ref , cache_slot , is_return_type , /* is_internal */ false);
12301236}
12311237
1232- static zend_always_inline bool zend_verify_recv_arg_type (const zend_function * zf , uint32_t arg_num , zval * arg )
1238+ static zend_always_inline bool zend_verify_recv_arg_type (const zend_function * zf , uint32_t arg_num , zval * arg , void * * cache_slot )
12331239{
12341240 const zend_arg_info * cur_arg_info ;
12351241
12361242 ZEND_ASSERT (arg_num <= zf -> common .num_args );
12371243 cur_arg_info = & zf -> common .arg_info [arg_num - 1 ];
12381244
12391245 if (ZEND_TYPE_IS_SET (cur_arg_info -> type )
1240- && UNEXPECTED (!zend_check_type (& cur_arg_info -> type , arg , zf -> common .scope , 0 , 0 ))) {
1246+ && UNEXPECTED (!zend_check_type (& cur_arg_info -> type , arg , cache_slot , zf -> common .scope , 0 , 0 ))) {
12411247 zend_verify_arg_error (zf , cur_arg_info , arg_num , arg );
12421248 return 0 ;
12431249 }
@@ -1246,10 +1252,10 @@ static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf
12461252}
12471253
12481254static zend_always_inline bool zend_verify_variadic_arg_type (
1249- const zend_function * zf , const zend_arg_info * arg_info , uint32_t arg_num , zval * arg )
1255+ const zend_function * zf , const zend_arg_info * arg_info , uint32_t arg_num , zval * arg , void * * cache_slot )
12501256{
12511257 ZEND_ASSERT (ZEND_TYPE_IS_SET (arg_info -> type ));
1252- if (UNEXPECTED (!zend_check_type (& arg_info -> type , arg , zf -> common .scope , 0 , 0 ))) {
1258+ if (UNEXPECTED (!zend_check_type (& arg_info -> type , arg , cache_slot , zf -> common .scope , 0 , 0 ))) {
12531259 zend_verify_arg_error (zf , arg_info , arg_num , arg );
12541260 return 0 ;
12551261 }
@@ -1273,8 +1279,9 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ
12731279 break ;
12741280 }
12751281
1282+ void * cache_slot = NULL ;
12761283 if (ZEND_TYPE_IS_SET (cur_arg_info -> type )
1277- && UNEXPECTED (!zend_check_type (& cur_arg_info -> type , arg , fbc -> common .scope , 0 , /* is_internal */ 1 ))) {
1284+ && UNEXPECTED (!zend_check_type (& cur_arg_info -> type , arg , & cache_slot , fbc -> common .scope , 0 , /* is_internal */ 1 ))) {
12781285 return 0 ;
12791286 }
12801287 arg ++ ;
@@ -1480,7 +1487,8 @@ ZEND_API bool zend_verify_internal_return_type(const zend_function *zf, zval *re
14801487 return 1 ;
14811488 }
14821489
1483- if (UNEXPECTED (!zend_check_type (& ret_info -> type , ret , NULL , 1 , /* is_internal */ 1 ))) {
1490+ void * cache_slot = NULL ;
1491+ if (UNEXPECTED (!zend_check_type (& ret_info -> type , ret , & cache_slot , NULL , 1 , /* is_internal */ 1 ))) {
14841492 zend_verify_internal_return_error (zf , ret );
14851493 return 0 ;
14861494 }
0 commit comments