Skip to content

Commit ef51648

Browse files
committed
Use zend_type.ce_cache__ptr for caching class resulution during argument/result type checks
1 parent a8f6d44 commit ef51648

File tree

6 files changed

+96
-49
lines changed

6 files changed

+96
-49
lines changed

Zend/zend_compile.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,7 +1197,13 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
11971197
} else {
11981198
if (ZEND_TYPE_HAS_CE_CACHE(*list_type)
11991199
&& ZEND_TYPE_CE_CACHE(*list_type)) {
1200-
str = add_type_string(str, ZEND_TYPE_CE_CACHE(*list_type)->name);
1200+
zend_class_entry *ce = ZEND_TYPE_CE_CACHE(*list_type);
1201+
if (ce->ce_flags & ZEND_ACC_ANON_CLASS) {
1202+
zend_string *tmp = zend_string_init(ZSTR_VAL(ce->name), strlen(ZSTR_VAL(ce->name)), 0);
1203+
str = add_type_string(str, tmp);
1204+
} else {
1205+
str = add_type_string(str, ce->name);
1206+
}
12011207
} else {
12021208
zend_string *resolved = resolve_class_name(ZEND_TYPE_NAME(*list_type), scope);
12031209
str = add_type_string(str, resolved);
@@ -1208,7 +1214,12 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
12081214
} else if (ZEND_TYPE_HAS_NAME(type)) {
12091215
if (ZEND_TYPE_HAS_CE_CACHE(type)
12101216
&& ZEND_TYPE_CE_CACHE(type)) {
1211-
str = zend_string_copy(ZEND_TYPE_CE_CACHE(type)->name);
1217+
zend_class_entry *ce = ZEND_TYPE_CE_CACHE(type);
1218+
if (ce->ce_flags & ZEND_ACC_ANON_CLASS) {
1219+
str = zend_string_init(ZSTR_VAL(ce->name), strlen(ZSTR_VAL(ce->name)), 0);
1220+
} else {
1221+
str = zend_string_copy(ce->name);
1222+
}
12121223
} else {
12131224
str = resolve_class_name(ZEND_TYPE_NAME(type), scope);
12141225
}

Zend/zend_execute.c

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -857,24 +857,26 @@ static bool zend_check_and_resolve_property_class_type(
857857
if (ZEND_TYPE_HAS_LIST(info->type)) {
858858
zend_type *list_type;
859859
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(info->type), list_type) {
860-
if (ZEND_TYPE_HAS_CE_CACHE(*list_type)) {
861-
ce = ZEND_TYPE_CE_CACHE(*list_type);
862-
if (!ce) {
860+
if (ZEND_TYPE_HAS_NAME(*list_type)) {
861+
if (ZEND_TYPE_HAS_CE_CACHE(*list_type)) {
862+
ce = ZEND_TYPE_CE_CACHE(*list_type);
863+
if (!ce) {
864+
zend_string *name = ZEND_TYPE_NAME(*list_type);
865+
ce = resolve_single_class_type(name, info->ce);
866+
if (UNEXPECTED(!ce)) {
867+
continue;
868+
}
869+
ZEND_TYPE_SET_CE_CACHE(*list_type, ce);
870+
}
871+
} else {
863872
zend_string *name = ZEND_TYPE_NAME(*list_type);
864873
ce = resolve_single_class_type(name, info->ce);
865-
if (UNEXPECTED(!ce)) {
874+
if (!ce) {
866875
continue;
867876
}
868-
ZEND_TYPE_SET_CE_CACHE(*list_type, ce);
869-
}
870-
} else if (ZEND_TYPE_HAS_NAME(*list_type)) {
871-
zend_string *name = ZEND_TYPE_NAME(*list_type);
872-
ce = resolve_single_class_type(name, info->ce);
873-
if (!ce) {
874-
continue;
877+
zend_string_release(name);
878+
ZEND_TYPE_SET_CE(*list_type, ce);
875879
}
876-
zend_string_release(name);
877-
ZEND_TYPE_SET_CE(*list_type, ce);
878880
} else {
879881
ce = ZEND_TYPE_CE(*list_type);
880882
}
@@ -884,25 +886,27 @@ static bool zend_check_and_resolve_property_class_type(
884886
} ZEND_TYPE_LIST_FOREACH_END();
885887
return 0;
886888
} else {
887-
if (ZEND_TYPE_HAS_CE_CACHE(info->type)) {
888-
ce = ZEND_TYPE_CE_CACHE(info->type);
889-
if (!ce) {
889+
if (UNEXPECTED(ZEND_TYPE_HAS_NAME(info->type))) {
890+
if (ZEND_TYPE_HAS_CE_CACHE(info->type)) {
891+
ce = ZEND_TYPE_CE_CACHE(info->type);
892+
if (!ce) {
893+
zend_string *name = ZEND_TYPE_NAME(info->type);
894+
ce = resolve_single_class_type(name, info->ce);
895+
if (UNEXPECTED(!ce)) {
896+
return 0;
897+
}
898+
ZEND_TYPE_SET_CE_CACHE(info->type, ce);
899+
}
900+
} else {
890901
zend_string *name = ZEND_TYPE_NAME(info->type);
891902
ce = resolve_single_class_type(name, info->ce);
892903
if (UNEXPECTED(!ce)) {
893904
return 0;
894905
}
895-
ZEND_TYPE_SET_CE_CACHE(info->type, ce);
896-
}
897-
} else if (UNEXPECTED(ZEND_TYPE_HAS_NAME(info->type))) {
898-
zend_string *name = ZEND_TYPE_NAME(info->type);
899-
ce = resolve_single_class_type(name, info->ce);
900-
if (UNEXPECTED(!ce)) {
901-
return 0;
902-
}
903906

904-
zend_string_release(name);
905-
ZEND_TYPE_SET_CE(info->type, ce);
907+
zend_string_release(name);
908+
ZEND_TYPE_SET_CE(info->type, ce);
909+
}
906910
} else {
907911
ce = ZEND_TYPE_CE(info->type);
908912
}
@@ -980,17 +984,22 @@ ZEND_API bool zend_value_instanceof_static(zval *zv) {
980984
#endif
981985

982986
static zend_always_inline bool zend_check_type_slow(
983-
zend_type type, zval *arg, zend_reference *ref, void **cache_slot, zend_class_entry *scope,
987+
zend_type *type, zval *arg, zend_reference *ref, void **cache_slot, zend_class_entry *scope,
984988
bool is_return_type, bool is_internal)
985989
{
986990
uint32_t type_mask;
987-
if (ZEND_TYPE_HAS_CLASS(type) && Z_TYPE_P(arg) == IS_OBJECT) {
991+
if (ZEND_TYPE_HAS_CLASS(*type) && Z_TYPE_P(arg) == IS_OBJECT) {
988992
zend_class_entry *ce;
989-
if (ZEND_TYPE_HAS_LIST(type)) {
993+
if (ZEND_TYPE_HAS_LIST(*type)) {
990994
zend_type *list_type;
991-
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) {
995+
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) {
992996
if (HAVE_CACHE_SLOT && *cache_slot) {
993997
ce = *cache_slot;
998+
} else if (ZEND_TYPE_HAS_CE_CACHE(*list_type) && ZEND_TYPE_CE_CACHE(*list_type)) {
999+
ce = ZEND_TYPE_CE_CACHE(*list_type);
1000+
if (HAVE_CACHE_SLOT) {
1001+
*cache_slot = ce;
1002+
}
9941003
} else {
9951004
ce = zend_fetch_class(ZEND_TYPE_NAME(*list_type),
9961005
(ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
@@ -1003,6 +1012,9 @@ static zend_always_inline bool zend_check_type_slow(
10031012
if (HAVE_CACHE_SLOT) {
10041013
*cache_slot = ce;
10051014
}
1015+
if (ZEND_TYPE_HAS_CE_CACHE(*list_type)) {
1016+
ZEND_TYPE_SET_CE_CACHE(*list_type, ce);
1017+
}
10061018
}
10071019
if (instanceof_function(Z_OBJCE_P(arg), ce)) {
10081020
return 1;
@@ -1014,14 +1026,22 @@ static zend_always_inline bool zend_check_type_slow(
10141026
} else {
10151027
if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) {
10161028
ce = (zend_class_entry *) *cache_slot;
1029+
} else if (ZEND_TYPE_HAS_CE_CACHE(*type) && ZEND_TYPE_CE_CACHE(*type)) {
1030+
ce = ZEND_TYPE_CE_CACHE(*type);
1031+
if (HAVE_CACHE_SLOT) {
1032+
*cache_slot = ce;
1033+
}
10171034
} else {
1018-
ce = zend_fetch_class(ZEND_TYPE_NAME(type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
1035+
ce = zend_fetch_class(ZEND_TYPE_NAME(*type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
10191036
if (UNEXPECTED(!ce)) {
10201037
goto builtin_types;
10211038
}
10221039
if (HAVE_CACHE_SLOT) {
10231040
*cache_slot = (void *) ce;
10241041
}
1042+
if (ZEND_TYPE_HAS_CE_CACHE(*type)) {
1043+
ZEND_TYPE_SET_CE_CACHE(*type, ce);
1044+
}
10251045
}
10261046
if (instanceof_function(Z_OBJCE_P(arg), ce)) {
10271047
return 1;
@@ -1030,7 +1050,7 @@ static zend_always_inline bool zend_check_type_slow(
10301050
}
10311051

10321052
builtin_types:
1033-
type_mask = ZEND_TYPE_FULL_MASK(type);
1053+
type_mask = ZEND_TYPE_FULL_MASK(*type);
10341054
if ((type_mask & MAY_BE_CALLABLE) && zend_is_callable(arg, 0, NULL)) {
10351055
return 1;
10361056
}
@@ -1060,18 +1080,18 @@ static zend_always_inline bool zend_check_type_slow(
10601080
}
10611081

10621082
static zend_always_inline bool zend_check_type(
1063-
zend_type type, zval *arg, void **cache_slot, zend_class_entry *scope,
1083+
zend_type *type, zval *arg, void **cache_slot, zend_class_entry *scope,
10641084
bool is_return_type, bool is_internal)
10651085
{
10661086
zend_reference *ref = NULL;
1067-
ZEND_ASSERT(ZEND_TYPE_IS_SET(type));
1087+
ZEND_ASSERT(ZEND_TYPE_IS_SET(*type));
10681088

10691089
if (UNEXPECTED(Z_ISREF_P(arg))) {
10701090
ref = Z_REF_P(arg);
10711091
arg = Z_REFVAL_P(arg);
10721092
}
10731093

1074-
if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(arg)))) {
1094+
if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(*type, Z_TYPE_P(arg)))) {
10751095
return 1;
10761096
}
10771097

@@ -1086,7 +1106,7 @@ static zend_always_inline bool zend_verify_recv_arg_type(zend_function *zf, uint
10861106
cur_arg_info = &zf->common.arg_info[arg_num-1];
10871107

10881108
if (ZEND_TYPE_IS_SET(cur_arg_info->type)
1089-
&& UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
1109+
&& UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
10901110
zend_verify_arg_error(zf, cur_arg_info, arg_num, arg);
10911111
return 0;
10921112
}
@@ -1098,7 +1118,7 @@ static zend_always_inline bool zend_verify_variadic_arg_type(
10981118
zend_function *zf, zend_arg_info *arg_info, uint32_t arg_num, zval *arg, void **cache_slot)
10991119
{
11001120
ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type));
1101-
if (UNEXPECTED(!zend_check_type(arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
1121+
if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
11021122
zend_verify_arg_error(zf, arg_info, arg_num, arg);
11031123
return 0;
11041124
}
@@ -1123,7 +1143,7 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ
11231143
}
11241144

11251145
if (ZEND_TYPE_IS_SET(cur_arg_info->type)
1126-
&& UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, /* cache_slot */ NULL, fbc->common.scope, 0, /* is_internal */ 1))) {
1146+
&& UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, /* cache_slot */ NULL, fbc->common.scope, 0, /* is_internal */ 1))) {
11271147
return 0;
11281148
}
11291149
arg++;
@@ -1256,7 +1276,7 @@ static bool zend_verify_internal_return_type(zend_function *zf, zval *ret)
12561276
return 1;
12571277
}
12581278

1259-
if (UNEXPECTED(!zend_check_type(ret_info->type, ret, /* cache_slot */ NULL, NULL, 1, /* is_internal */ 1))) {
1279+
if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, /* cache_slot */ NULL, NULL, 1, /* is_internal */ 1))) {
12601280
zend_verify_internal_return_error(zf, ret);
12611281
return 0;
12621282
}

Zend/zend_inheritance.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -712,8 +712,12 @@ static ZEND_COLD zend_string *zend_get_function_declaration(
712712
}
713713

714714
if (fptr->common.scope) {
715-
/* cut off on NULL byte ... class@anonymous */
716-
smart_str_appendl(&str, ZSTR_VAL(fptr->common.scope->name), strlen(ZSTR_VAL(fptr->common.scope->name)));
715+
if (fptr->common.scope->ce_flags & ZEND_ACC_ANON_CLASS) {
716+
/* cut off on NULL byte ... class@anonymous */
717+
smart_str_appends(&str, ZSTR_VAL(fptr->common.scope->name));
718+
} else {
719+
smart_str_appendl(&str, ZSTR_VAL(fptr->common.scope->name), ZSTR_LEN(fptr->common.scope->name));
720+
}
717721
smart_str_appends(&str, "::");
718722
}
719723

Zend/zend_vm_def.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4227,7 +4227,7 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV
42274227
}
42284228

42294229
SAVE_OPLINE();
4230-
if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
4230+
if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
42314231
zend_verify_return_error(EX(func), retval_ptr);
42324232
HANDLE_EXCEPTION();
42334233
}

Zend/zend_vm_execute.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9777,7 +9777,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP
97779777
}
97789778

97799779
SAVE_OPLINE();
9780-
if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
9780+
if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
97819781
zend_verify_return_error(EX(func), retval_ptr);
97829782
HANDLE_EXCEPTION();
97839783
}
@@ -20133,7 +20133,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN
2013320133
}
2013420134

2013520135
SAVE_OPLINE();
20136-
if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
20136+
if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
2013720137
zend_verify_return_error(EX(func), retval_ptr);
2013820138
HANDLE_EXCEPTION();
2013920139
}
@@ -27730,7 +27730,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN
2773027730
}
2773127731

2773227732
SAVE_OPLINE();
27733-
if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
27733+
if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
2773427734
zend_verify_return_error(EX(func), retval_ptr);
2773527735
HANDLE_EXCEPTION();
2773627736
}
@@ -34914,7 +34914,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED
3491434914
}
3491534915

3491634916
SAVE_OPLINE();
34917-
if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
34917+
if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
3491834918
zend_verify_return_error(EX(func), retval_ptr);
3491934919
HANDLE_EXCEPTION();
3492034920
}
@@ -46624,7 +46624,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU
4662446624
}
4662546625

4662646626
SAVE_OPLINE();
46627-
if (UNEXPECTED(!zend_check_type_slow(ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
46627+
if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, NULL, 1, 0))) {
4662846628
zend_verify_return_error(EX(func), retval_ptr);
4662946629
HANDLE_EXCEPTION();
4663046630
}

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,9 @@ static zend_always_inline bool zend_jit_verify_type_common(zval *arg, zend_arg_i
13841384
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(arg_info->type), list_type) {
13851385
if (*cache_slot) {
13861386
ce = *cache_slot;
1387+
} else if (ZEND_TYPE_HAS_CE_CACHE(*list_type) && ZEND_TYPE_CE_CACHE(*list_type)) {
1388+
ce = ZEND_TYPE_CE_CACHE(*list_type);
1389+
*cache_slot = ce;
13871390
} else {
13881391
ce = zend_fetch_class(ZEND_TYPE_NAME(*list_type),
13891392
(ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
@@ -1392,6 +1395,9 @@ static zend_always_inline bool zend_jit_verify_type_common(zval *arg, zend_arg_i
13921395
continue;
13931396
}
13941397
*cache_slot = ce;
1398+
if (ZEND_TYPE_HAS_CE_CACHE(*list_type)) {
1399+
ZEND_TYPE_SET_CE_CACHE(*list_type, ce);
1400+
}
13951401
}
13961402
if (instanceof_function(Z_OBJCE_P(arg), ce)) {
13971403
return 1;
@@ -1401,12 +1407,18 @@ static zend_always_inline bool zend_jit_verify_type_common(zval *arg, zend_arg_i
14011407
} else {
14021408
if (EXPECTED(*cache_slot)) {
14031409
ce = (zend_class_entry *) *cache_slot;
1410+
} else if (ZEND_TYPE_HAS_CE_CACHE(arg_info->type) && ZEND_TYPE_CE_CACHE(arg_info->type)) {
1411+
ce = ZEND_TYPE_CE_CACHE(arg_info->type);
1412+
*cache_slot = ce;
14041413
} else {
14051414
ce = zend_fetch_class(ZEND_TYPE_NAME(arg_info->type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
14061415
if (UNEXPECTED(!ce)) {
14071416
goto builtin_types;
14081417
}
14091418
*cache_slot = (void *) ce;
1419+
if (ZEND_TYPE_HAS_CE_CACHE(arg_info->type)) {
1420+
ZEND_TYPE_SET_CE_CACHE(arg_info->type, ce);
1421+
}
14101422
}
14111423
if (instanceof_function(Z_OBJCE_P(arg), ce)) {
14121424
return 1;

0 commit comments

Comments
 (0)