Skip to content

Commit b0c7519

Browse files
committed
Move common code into always inlined functions
1 parent 020b586 commit b0c7519

File tree

3 files changed

+126
-220
lines changed

3 files changed

+126
-220
lines changed

Zend/zend_execute.c

Lines changed: 71 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -836,8 +836,39 @@ static zend_class_entry *resolve_single_class_type(zend_string *name, zend_class
836836
}
837837
}
838838

839-
// TODO Handle complex types when added
840-
// TODO Update to handle union and intersection in the same loop
839+
// TODO better name
840+
static zend_always_inline zend_class_entry* zend_resolve_ce(
841+
zend_property_info *info, zend_type *type) {
842+
zend_class_entry *ce;
843+
if (UNEXPECTED(ZEND_TYPE_HAS_NAME(*type))) {
844+
zend_string *name = ZEND_TYPE_NAME(*type);
845+
846+
if (ZSTR_HAS_CE_CACHE(name)) {
847+
ce = ZSTR_GET_CE_CACHE(name);
848+
if (!ce) {
849+
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
850+
if (UNEXPECTED(!ce)) {
851+
/* Cannot resolve */
852+
return NULL;
853+
}
854+
}
855+
} else {
856+
ce = resolve_single_class_type(name, info->ce);
857+
if (!ce) {
858+
/* Cannot resolve */
859+
return NULL;
860+
}
861+
if (!(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
862+
zend_string_release(name);
863+
ZEND_TYPE_SET_CE(*type, ce);
864+
}
865+
}
866+
} else {
867+
ce = ZEND_TYPE_CE(*type);
868+
}
869+
return ce;
870+
}
871+
841872
static bool zend_check_and_resolve_property_class_type(
842873
zend_property_info *info, zend_class_entry *object_ce) {
843874
zend_class_entry *ce;
@@ -846,62 +877,27 @@ static bool zend_check_and_resolve_property_class_type(
846877

847878
if (ZEND_TYPE_IS_INTERSECTION(info->type)) {
848879
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(info->type), list_type) {
849-
if (ZEND_TYPE_HAS_NAME(*list_type)) {
850-
zend_string *name = ZEND_TYPE_NAME(*list_type);
851-
852-
if (ZSTR_HAS_CE_CACHE(name)) {
853-
ce = ZSTR_GET_CE_CACHE(name);
854-
if (!ce) {
855-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
856-
if (UNEXPECTED(!ce)) {
857-
/* Cannot resolve */
858-
return false;
859-
}
860-
}
861-
} else {
862-
ce = resolve_single_class_type(name, info->ce);
863-
if (!ce) {
864-
/* Cannot resolve */
865-
return false;
866-
}
867-
if (!(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
868-
zend_string_release(name);
869-
ZEND_TYPE_SET_CE(*list_type, ce);
870-
}
871-
}
872-
} else {
873-
ce = ZEND_TYPE_CE(*list_type);
880+
ce = zend_resolve_ce(info, list_type);
881+
882+
/* If we cannot resolve the CE we cannot check if it satisfies
883+
* the type constraint, fail. */
884+
if (ce == NULL) {
885+
return false;
874886
}
887+
875888
if (!instanceof_function(object_ce, ce)) {
876889
return false;
877890
}
878891
} ZEND_TYPE_LIST_FOREACH_END();
879892
return true;
880893
} else {
881894
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(info->type), list_type) {
882-
if (ZEND_TYPE_HAS_NAME(*list_type)) {
883-
zend_string *name = ZEND_TYPE_NAME(*list_type);
884-
885-
if (ZSTR_HAS_CE_CACHE(name)) {
886-
ce = ZSTR_GET_CE_CACHE(name);
887-
if (!ce) {
888-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
889-
if (UNEXPECTED(!ce)) {
890-
continue;
891-
}
892-
}
893-
} else {
894-
ce = resolve_single_class_type(name, info->ce);
895-
if (!ce) {
896-
continue;
897-
}
898-
if (!(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
899-
zend_string_release(name);
900-
ZEND_TYPE_SET_CE(*list_type, ce);
901-
}
902-
}
903-
} else {
904-
ce = ZEND_TYPE_CE(*list_type);
895+
ce = zend_resolve_ce(info, list_type);
896+
897+
/* If we cannot resolve the CE we cannot check if it satisfies
898+
* the type constraint, check the next one. */
899+
if (ce == NULL) {
900+
continue;
905901
}
906902
if (instanceof_function(object_ce, ce)) {
907903
return true;
@@ -910,30 +906,14 @@ static bool zend_check_and_resolve_property_class_type(
910906
return false;
911907
}
912908
} else {
913-
if (UNEXPECTED(ZEND_TYPE_HAS_NAME(info->type))) {
914-
zend_string *name = ZEND_TYPE_NAME(info->type);
915-
916-
if (ZSTR_HAS_CE_CACHE(name)) {
917-
ce = ZSTR_GET_CE_CACHE(name);
918-
if (!ce) {
919-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
920-
if (UNEXPECTED(!ce)) {
921-
return 0;
922-
}
923-
}
924-
} else {
925-
ce = resolve_single_class_type(name, info->ce);
926-
if (UNEXPECTED(!ce)) {
927-
return 0;
928-
}
929-
if (!(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
930-
zend_string_release(name);
931-
ZEND_TYPE_SET_CE(info->type, ce);
932-
}
933-
}
934-
} else {
935-
ce = ZEND_TYPE_CE(info->type);
909+
ce = zend_resolve_ce(info, &info->type);
910+
911+
/* If we cannot resolve the CE we cannot check if it satisfies
912+
* the type constraint, fail. */
913+
if (ce == NULL) {
914+
return false;
936915
}
916+
937917
return instanceof_function(object_ce, ce);
938918
}
939919
}
@@ -999,16 +979,6 @@ ZEND_API bool zend_value_instanceof_static(zval *zv) {
999979
return instanceof_function(Z_OBJCE_P(zv), called_scope);
1000980
}
1001981

1002-
/* The cache_slot may only be NULL in debug builds, where arginfo verification of
1003-
* internal functions is enabled. Avoid unnecessary checks in release builds. */
1004-
#if ZEND_DEBUG
1005-
# define HAVE_CACHE_SLOT (cache_slot != NULL)
1006-
#else
1007-
# define HAVE_CACHE_SLOT 1
1008-
#endif
1009-
1010-
// TODO Handle complex types when added
1011-
// TODO Update to handle union and intersection in the same loop
1012982
static zend_always_inline bool zend_check_type_slow(
1013983
zend_type *type, zval *arg, zend_reference *ref, void **cache_slot, zend_class_entry *scope,
1014984
bool is_return_type, bool is_internal)
@@ -1020,28 +990,11 @@ static zend_always_inline bool zend_check_type_slow(
1020990
zend_type *list_type;
1021991
if (ZEND_TYPE_IS_INTERSECTION(*type)) {
1022992
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) {
1023-
if (HAVE_CACHE_SLOT && *cache_slot) {
1024-
ce = *cache_slot;
1025-
} else {
1026-
zend_string *name = ZEND_TYPE_NAME(*list_type);
1027-
1028-
if (ZSTR_HAS_CE_CACHE(name)) {
1029-
ce = ZSTR_GET_CE_CACHE(name);
1030-
if (!ce) {
1031-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
1032-
if (!ce) {
1033-
/* Cannot resolve */
1034-
return false;
1035-
}
1036-
}
1037-
} else {
1038-
ce = zend_fetch_class(name,
1039-
ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT);
1040-
if (!ce) {
1041-
/* Cannot resolve */
1042-
return false;
1043-
}
1044-
}
993+
ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type);
994+
/* If we cannot resolve the CE we cannot check if it satisfies
995+
* the type constraint, fail. */
996+
if (ce == NULL) {
997+
return false;
1045998
}
1046999

10471000
/* Perform actual type check */
@@ -1057,32 +1010,14 @@ static zend_always_inline bool zend_check_type_slow(
10571010
return true;
10581011
} else {
10591012
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) {
1060-
if (HAVE_CACHE_SLOT && *cache_slot) {
1061-
ce = *cache_slot;
1062-
} else {
1063-
zend_string *name = ZEND_TYPE_NAME(*list_type);
1064-
1065-
if (ZSTR_HAS_CE_CACHE(name)) {
1066-
ce = ZSTR_GET_CE_CACHE(name);
1067-
if (!ce) {
1068-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
1069-
if (!ce) {
1070-
if (HAVE_CACHE_SLOT) {
1071-
cache_slot++;
1072-
}
1073-
continue;
1074-
}
1075-
}
1076-
} else {
1077-
ce = zend_fetch_class(name,
1078-
ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT);
1079-
if (!ce) {
1080-
if (HAVE_CACHE_SLOT) {
1081-
cache_slot++;
1082-
}
1083-
continue;
1084-
}
1013+
ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type);
1014+
/* If we cannot resolve the CE we cannot check if it satisfies
1015+
* the type constraint, check the next one. */
1016+
if (ce == NULL) {
1017+
if (HAVE_CACHE_SLOT) {
1018+
cache_slot++;
10851019
}
1020+
continue;
10861021
}
10871022

10881023
/* Perform actual type check */
@@ -1096,30 +1031,13 @@ static zend_always_inline bool zend_check_type_slow(
10961031
} ZEND_TYPE_LIST_FOREACH_END();
10971032
}
10981033
} else {
1099-
if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) {
1100-
ce = (zend_class_entry *) *cache_slot;
1101-
} else {
1102-
zend_string *name = ZEND_TYPE_NAME(*type);
1103-
1104-
if (ZSTR_HAS_CE_CACHE(name)) {
1105-
ce = ZSTR_GET_CE_CACHE(name);
1106-
if (!ce) {
1107-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
1108-
if (UNEXPECTED(!ce)) {
1109-
goto builtin_types;
1110-
}
1111-
}
1112-
} else {
1113-
ce = zend_fetch_class(name,
1114-
ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT);
1115-
if (UNEXPECTED(!ce)) {
1116-
goto builtin_types;
1117-
}
1118-
}
1119-
if (HAVE_CACHE_SLOT) {
1120-
*cache_slot = (void *) ce;
1121-
}
1034+
ce = zend_fetch_ce_from_cache_slot(cache_slot, type);
1035+
/* If we cannot resolve the CE we cannot check if it satisfies
1036+
* the type constraint, check if a standard type satisfies it. */
1037+
if (ce == NULL) {
1038+
goto builtin_types;
11221039
}
1040+
11231041
if (instanceof_function(Z_OBJCE_P(arg), ce)) {
11241042
return 1;
11251043
}

Zend/zend_execute.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,45 @@ ZEND_COLD void zend_verify_property_type_error(zend_property_info *info, zval *p
459459
} \
460460
} while (0)
461461

462+
/* The cache_slot may only be NULL in debug builds, where arginfo verification of
463+
* internal functions is enabled. Avoid unnecessary checks in release builds. */
464+
#if ZEND_DEBUG
465+
# define HAVE_CACHE_SLOT (cache_slot != NULL)
466+
#else
467+
# define HAVE_CACHE_SLOT 1
468+
#endif
469+
470+
static zend_always_inline zend_class_entry* zend_fetch_ce_from_cache_slot(void **cache_slot, zend_type *type)
471+
{
472+
zend_class_entry *ce;
473+
474+
if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) {
475+
ce = (zend_class_entry *) *cache_slot;
476+
} else {
477+
zend_string *name = ZEND_TYPE_NAME(*type);
478+
479+
if (ZSTR_HAS_CE_CACHE(name)) {
480+
ce = ZSTR_GET_CE_CACHE(name);
481+
if (!ce) {
482+
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
483+
if (UNEXPECTED(!ce)) {
484+
/* Cannot resolve */
485+
return NULL;
486+
}
487+
}
488+
} else {
489+
ce = zend_fetch_class(name,
490+
ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT);
491+
if (UNEXPECTED(!ce)) {
492+
return NULL;
493+
}
494+
}
495+
if (HAVE_CACHE_SLOT) {
496+
*cache_slot = (void *) ce;
497+
}
498+
}
499+
return ce;
500+
}
462501

463502
END_EXTERN_C()
464503

0 commit comments

Comments
 (0)