Skip to content

Commit 10c252b

Browse files
committed
Move common code into always inlined functions
1 parent 52c0799 commit 10c252b

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
@@ -847,8 +847,39 @@ static zend_class_entry *resolve_single_class_type(zend_string *name, zend_class
847847
}
848848
}
849849

850-
// TODO Handle complex types when added
851-
// TODO Update to handle union and intersection in the same loop
850+
// TODO better name
851+
static zend_always_inline zend_class_entry* zend_resolve_ce(
852+
zend_property_info *info, zend_type *type) {
853+
zend_class_entry *ce;
854+
if (UNEXPECTED(ZEND_TYPE_HAS_NAME(*type))) {
855+
zend_string *name = ZEND_TYPE_NAME(*type);
856+
857+
if (ZSTR_HAS_CE_CACHE(name)) {
858+
ce = ZSTR_GET_CE_CACHE(name);
859+
if (!ce) {
860+
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
861+
if (UNEXPECTED(!ce)) {
862+
/* Cannot resolve */
863+
return NULL;
864+
}
865+
}
866+
} else {
867+
ce = resolve_single_class_type(name, info->ce);
868+
if (!ce) {
869+
/* Cannot resolve */
870+
return NULL;
871+
}
872+
if (!(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
873+
zend_string_release(name);
874+
ZEND_TYPE_SET_CE(*type, ce);
875+
}
876+
}
877+
} else {
878+
ce = ZEND_TYPE_CE(*type);
879+
}
880+
return ce;
881+
}
882+
852883
static bool zend_check_and_resolve_property_class_type(
853884
zend_property_info *info, zend_class_entry *object_ce) {
854885
zend_class_entry *ce;
@@ -857,62 +888,27 @@ static bool zend_check_and_resolve_property_class_type(
857888

858889
if (ZEND_TYPE_IS_INTERSECTION(info->type)) {
859890
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(info->type), list_type) {
860-
if (ZEND_TYPE_HAS_NAME(*list_type)) {
861-
zend_string *name = ZEND_TYPE_NAME(*list_type);
862-
863-
if (ZSTR_HAS_CE_CACHE(name)) {
864-
ce = ZSTR_GET_CE_CACHE(name);
865-
if (!ce) {
866-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
867-
if (UNEXPECTED(!ce)) {
868-
/* Cannot resolve */
869-
return false;
870-
}
871-
}
872-
} else {
873-
ce = resolve_single_class_type(name, info->ce);
874-
if (!ce) {
875-
/* Cannot resolve */
876-
return false;
877-
}
878-
if (!(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
879-
zend_string_release(name);
880-
ZEND_TYPE_SET_CE(*list_type, ce);
881-
}
882-
}
883-
} else {
884-
ce = ZEND_TYPE_CE(*list_type);
891+
ce = zend_resolve_ce(info, list_type);
892+
893+
/* If we cannot resolve the CE we cannot check if it satisfies
894+
* the type constraint, fail. */
895+
if (ce == NULL) {
896+
return false;
885897
}
898+
886899
if (!instanceof_function(object_ce, ce)) {
887900
return false;
888901
}
889902
} ZEND_TYPE_LIST_FOREACH_END();
890903
return true;
891904
} else {
892905
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(info->type), list_type) {
893-
if (ZEND_TYPE_HAS_NAME(*list_type)) {
894-
zend_string *name = ZEND_TYPE_NAME(*list_type);
895-
896-
if (ZSTR_HAS_CE_CACHE(name)) {
897-
ce = ZSTR_GET_CE_CACHE(name);
898-
if (!ce) {
899-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
900-
if (UNEXPECTED(!ce)) {
901-
continue;
902-
}
903-
}
904-
} else {
905-
ce = resolve_single_class_type(name, info->ce);
906-
if (!ce) {
907-
continue;
908-
}
909-
if (!(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
910-
zend_string_release(name);
911-
ZEND_TYPE_SET_CE(*list_type, ce);
912-
}
913-
}
914-
} else {
915-
ce = ZEND_TYPE_CE(*list_type);
906+
ce = zend_resolve_ce(info, list_type);
907+
908+
/* If we cannot resolve the CE we cannot check if it satisfies
909+
* the type constraint, check the next one. */
910+
if (ce == NULL) {
911+
continue;
916912
}
917913
if (instanceof_function(object_ce, ce)) {
918914
return true;
@@ -921,30 +917,14 @@ static bool zend_check_and_resolve_property_class_type(
921917
return false;
922918
}
923919
} else {
924-
if (UNEXPECTED(ZEND_TYPE_HAS_NAME(info->type))) {
925-
zend_string *name = ZEND_TYPE_NAME(info->type);
926-
927-
if (ZSTR_HAS_CE_CACHE(name)) {
928-
ce = ZSTR_GET_CE_CACHE(name);
929-
if (!ce) {
930-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
931-
if (UNEXPECTED(!ce)) {
932-
return 0;
933-
}
934-
}
935-
} else {
936-
ce = resolve_single_class_type(name, info->ce);
937-
if (UNEXPECTED(!ce)) {
938-
return 0;
939-
}
940-
if (!(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
941-
zend_string_release(name);
942-
ZEND_TYPE_SET_CE(info->type, ce);
943-
}
944-
}
945-
} else {
946-
ce = ZEND_TYPE_CE(info->type);
920+
ce = zend_resolve_ce(info, &info->type);
921+
922+
/* If we cannot resolve the CE we cannot check if it satisfies
923+
* the type constraint, fail. */
924+
if (ce == NULL) {
925+
return false;
947926
}
927+
948928
return instanceof_function(object_ce, ce);
949929
}
950930
}
@@ -1010,16 +990,6 @@ ZEND_API bool zend_value_instanceof_static(zval *zv) {
1010990
return instanceof_function(Z_OBJCE_P(zv), called_scope);
1011991
}
1012992

1013-
/* The cache_slot may only be NULL in debug builds, where arginfo verification of
1014-
* internal functions is enabled. Avoid unnecessary checks in release builds. */
1015-
#if ZEND_DEBUG
1016-
# define HAVE_CACHE_SLOT (cache_slot != NULL)
1017-
#else
1018-
# define HAVE_CACHE_SLOT 1
1019-
#endif
1020-
1021-
// TODO Handle complex types when added
1022-
// TODO Update to handle union and intersection in the same loop
1023993
static zend_always_inline bool zend_check_type_slow(
1024994
zend_type *type, zval *arg, zend_reference *ref, void **cache_slot, zend_class_entry *scope,
1025995
bool is_return_type, bool is_internal)
@@ -1031,28 +1001,11 @@ static zend_always_inline bool zend_check_type_slow(
10311001
zend_type *list_type;
10321002
if (ZEND_TYPE_IS_INTERSECTION(*type)) {
10331003
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) {
1034-
if (HAVE_CACHE_SLOT && *cache_slot) {
1035-
ce = *cache_slot;
1036-
} else {
1037-
zend_string *name = ZEND_TYPE_NAME(*list_type);
1038-
1039-
if (ZSTR_HAS_CE_CACHE(name)) {
1040-
ce = ZSTR_GET_CE_CACHE(name);
1041-
if (!ce) {
1042-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
1043-
if (!ce) {
1044-
/* Cannot resolve */
1045-
return false;
1046-
}
1047-
}
1048-
} else {
1049-
ce = zend_fetch_class(name,
1050-
ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT);
1051-
if (!ce) {
1052-
/* Cannot resolve */
1053-
return false;
1054-
}
1055-
}
1004+
ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type);
1005+
/* If we cannot resolve the CE we cannot check if it satisfies
1006+
* the type constraint, fail. */
1007+
if (ce == NULL) {
1008+
return false;
10561009
}
10571010

10581011
/* Perform actual type check */
@@ -1068,32 +1021,14 @@ static zend_always_inline bool zend_check_type_slow(
10681021
return true;
10691022
} else {
10701023
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) {
1071-
if (HAVE_CACHE_SLOT && *cache_slot) {
1072-
ce = *cache_slot;
1073-
} else {
1074-
zend_string *name = ZEND_TYPE_NAME(*list_type);
1075-
1076-
if (ZSTR_HAS_CE_CACHE(name)) {
1077-
ce = ZSTR_GET_CE_CACHE(name);
1078-
if (!ce) {
1079-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
1080-
if (!ce) {
1081-
if (HAVE_CACHE_SLOT) {
1082-
cache_slot++;
1083-
}
1084-
continue;
1085-
}
1086-
}
1087-
} else {
1088-
ce = zend_fetch_class(name,
1089-
ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT);
1090-
if (!ce) {
1091-
if (HAVE_CACHE_SLOT) {
1092-
cache_slot++;
1093-
}
1094-
continue;
1095-
}
1024+
ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type);
1025+
/* If we cannot resolve the CE we cannot check if it satisfies
1026+
* the type constraint, check the next one. */
1027+
if (ce == NULL) {
1028+
if (HAVE_CACHE_SLOT) {
1029+
cache_slot++;
10961030
}
1031+
continue;
10971032
}
10981033

10991034
/* Perform actual type check */
@@ -1107,30 +1042,13 @@ static zend_always_inline bool zend_check_type_slow(
11071042
} ZEND_TYPE_LIST_FOREACH_END();
11081043
}
11091044
} else {
1110-
if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) {
1111-
ce = (zend_class_entry *) *cache_slot;
1112-
} else {
1113-
zend_string *name = ZEND_TYPE_NAME(*type);
1114-
1115-
if (ZSTR_HAS_CE_CACHE(name)) {
1116-
ce = ZSTR_GET_CE_CACHE(name);
1117-
if (!ce) {
1118-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
1119-
if (UNEXPECTED(!ce)) {
1120-
goto builtin_types;
1121-
}
1122-
}
1123-
} else {
1124-
ce = zend_fetch_class(name,
1125-
ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT);
1126-
if (UNEXPECTED(!ce)) {
1127-
goto builtin_types;
1128-
}
1129-
}
1130-
if (HAVE_CACHE_SLOT) {
1131-
*cache_slot = (void *) ce;
1132-
}
1045+
ce = zend_fetch_ce_from_cache_slot(cache_slot, type);
1046+
/* If we cannot resolve the CE we cannot check if it satisfies
1047+
* the type constraint, check if a standard type satisfies it. */
1048+
if (ce == NULL) {
1049+
goto builtin_types;
11331050
}
1051+
11341052
if (instanceof_function(Z_OBJCE_P(arg), ce)) {
11351053
return 1;
11361054
}

Zend/zend_execute.h

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

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

454493
END_EXTERN_C()
455494

0 commit comments

Comments
 (0)