Skip to content

Commit d2eafd9

Browse files
Girgiasnikic
authored andcommitted
Move common code into always inlined functions
1 parent f79148f commit d2eafd9

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
@@ -838,8 +838,39 @@ static zend_class_entry *resolve_single_class_type(zend_string *name, zend_class
838838
}
839839
}
840840

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

849880
if (ZEND_TYPE_IS_INTERSECTION(info->type)) {
850881
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(info->type), list_type) {
851-
if (ZEND_TYPE_HAS_NAME(*list_type)) {
852-
zend_string *name = ZEND_TYPE_NAME(*list_type);
853-
854-
if (ZSTR_HAS_CE_CACHE(name)) {
855-
ce = ZSTR_GET_CE_CACHE(name);
856-
if (!ce) {
857-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
858-
if (UNEXPECTED(!ce)) {
859-
/* Cannot resolve */
860-
return false;
861-
}
862-
}
863-
} else {
864-
ce = resolve_single_class_type(name, info->ce);
865-
if (!ce) {
866-
/* Cannot resolve */
867-
return false;
868-
}
869-
if (!(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
870-
zend_string_release(name);
871-
ZEND_TYPE_SET_CE(*list_type, ce);
872-
}
873-
}
874-
} else {
875-
ce = ZEND_TYPE_CE(*list_type);
882+
ce = zend_resolve_ce(info, list_type);
883+
884+
/* If we cannot resolve the CE we cannot check if it satisfies
885+
* the type constraint, fail. */
886+
if (ce == NULL) {
887+
return false;
876888
}
889+
877890
if (!instanceof_function(object_ce, ce)) {
878891
return false;
879892
}
880893
} ZEND_TYPE_LIST_FOREACH_END();
881894
return true;
882895
} else {
883896
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(info->type), list_type) {
884-
if (ZEND_TYPE_HAS_NAME(*list_type)) {
885-
zend_string *name = ZEND_TYPE_NAME(*list_type);
886-
887-
if (ZSTR_HAS_CE_CACHE(name)) {
888-
ce = ZSTR_GET_CE_CACHE(name);
889-
if (!ce) {
890-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
891-
if (UNEXPECTED(!ce)) {
892-
continue;
893-
}
894-
}
895-
} else {
896-
ce = resolve_single_class_type(name, info->ce);
897-
if (!ce) {
898-
continue;
899-
}
900-
if (!(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
901-
zend_string_release(name);
902-
ZEND_TYPE_SET_CE(*list_type, ce);
903-
}
904-
}
905-
} else {
906-
ce = ZEND_TYPE_CE(*list_type);
897+
ce = zend_resolve_ce(info, list_type);
898+
899+
/* If we cannot resolve the CE we cannot check if it satisfies
900+
* the type constraint, check the next one. */
901+
if (ce == NULL) {
902+
continue;
907903
}
908904
if (instanceof_function(object_ce, ce)) {
909905
return true;
@@ -912,30 +908,14 @@ static bool zend_check_and_resolve_property_class_type(
912908
return false;
913909
}
914910
} else {
915-
if (UNEXPECTED(ZEND_TYPE_HAS_NAME(info->type))) {
916-
zend_string *name = ZEND_TYPE_NAME(info->type);
917-
918-
if (ZSTR_HAS_CE_CACHE(name)) {
919-
ce = ZSTR_GET_CE_CACHE(name);
920-
if (!ce) {
921-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
922-
if (UNEXPECTED(!ce)) {
923-
return 0;
924-
}
925-
}
926-
} else {
927-
ce = resolve_single_class_type(name, info->ce);
928-
if (UNEXPECTED(!ce)) {
929-
return 0;
930-
}
931-
if (!(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
932-
zend_string_release(name);
933-
ZEND_TYPE_SET_CE(info->type, ce);
934-
}
935-
}
936-
} else {
937-
ce = ZEND_TYPE_CE(info->type);
911+
ce = zend_resolve_ce(info, &info->type);
912+
913+
/* If we cannot resolve the CE we cannot check if it satisfies
914+
* the type constraint, fail. */
915+
if (ce == NULL) {
916+
return false;
938917
}
918+
939919
return instanceof_function(object_ce, ce);
940920
}
941921
}
@@ -1001,16 +981,6 @@ ZEND_API bool zend_value_instanceof_static(zval *zv) {
1001981
return instanceof_function(Z_OBJCE_P(zv), called_scope);
1002982
}
1003983

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

10491002
/* Perform actual type check */
@@ -1059,32 +1012,14 @@ static zend_always_inline bool zend_check_type_slow(
10591012
return true;
10601013
} else {
10611014
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) {
1062-
if (HAVE_CACHE_SLOT && *cache_slot) {
1063-
ce = *cache_slot;
1064-
} else {
1065-
zend_string *name = ZEND_TYPE_NAME(*list_type);
1066-
1067-
if (ZSTR_HAS_CE_CACHE(name)) {
1068-
ce = ZSTR_GET_CE_CACHE(name);
1069-
if (!ce) {
1070-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
1071-
if (!ce) {
1072-
if (HAVE_CACHE_SLOT) {
1073-
cache_slot++;
1074-
}
1075-
continue;
1076-
}
1077-
}
1078-
} else {
1079-
ce = zend_fetch_class(name,
1080-
ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT);
1081-
if (!ce) {
1082-
if (HAVE_CACHE_SLOT) {
1083-
cache_slot++;
1084-
}
1085-
continue;
1086-
}
1015+
ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type);
1016+
/* If we cannot resolve the CE we cannot check if it satisfies
1017+
* the type constraint, check the next one. */
1018+
if (ce == NULL) {
1019+
if (HAVE_CACHE_SLOT) {
1020+
cache_slot++;
10871021
}
1022+
continue;
10881023
}
10891024

10901025
/* Perform actual type check */
@@ -1098,30 +1033,13 @@ static zend_always_inline bool zend_check_type_slow(
10981033
} ZEND_TYPE_LIST_FOREACH_END();
10991034
}
11001035
} else {
1101-
if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) {
1102-
ce = (zend_class_entry *) *cache_slot;
1103-
} else {
1104-
zend_string *name = ZEND_TYPE_NAME(*type);
1105-
1106-
if (ZSTR_HAS_CE_CACHE(name)) {
1107-
ce = ZSTR_GET_CE_CACHE(name);
1108-
if (!ce) {
1109-
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
1110-
if (UNEXPECTED(!ce)) {
1111-
goto builtin_types;
1112-
}
1113-
}
1114-
} else {
1115-
ce = zend_fetch_class(name,
1116-
ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT);
1117-
if (UNEXPECTED(!ce)) {
1118-
goto builtin_types;
1119-
}
1120-
}
1121-
if (HAVE_CACHE_SLOT) {
1122-
*cache_slot = (void *) ce;
1123-
}
1036+
ce = zend_fetch_ce_from_cache_slot(cache_slot, type);
1037+
/* If we cannot resolve the CE we cannot check if it satisfies
1038+
* the type constraint, check if a standard type satisfies it. */
1039+
if (ce == NULL) {
1040+
goto builtin_types;
11241041
}
1042+
11251043
if (instanceof_function(Z_OBJCE_P(arg), ce)) {
11261044
return 1;
11271045
}

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)