Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9a691fe

Browse files
committed
Remove cache slot from ZEND_VERIFY_TYPE and arg RECV opcodes
1 parent bd43334 commit 9a691fe

File tree

10 files changed

+57
-163
lines changed

10 files changed

+57
-163
lines changed

‎UPGRADING.INTERNALS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ PHP 8.5 INTERNALS UPGRADE NOTES
2525
char* instead of zend_string*-based smart strings.
2626
. Added php_build_provider() to retrieve the value of PHP_BUILD_PROVIDER at
2727
runtime.
28+
. Removed the cache_slot argument of zend_check_user_type_slow() because
29+
now it only relies on the CE cache.
2830

2931
========================
3032
2. Build system changes

‎Zend/Optimizer/compact_literals.c

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -43,50 +43,6 @@ typedef struct _literal_info {
4343
info[n].num_related = (related); \
4444
} while (0)
4545

46-
static size_t type_num_classes(const zend_op_array *op_array, uint32_t arg_num)
47-
{
48-
zend_arg_info *arg_info;
49-
if (arg_num > 0) {
50-
if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
51-
return 0;
52-
}
53-
if (EXPECTED(arg_num <= op_array->num_args)) {
54-
arg_info = &op_array->arg_info[arg_num-1];
55-
} else if (UNEXPECTED(op_array->fn_flags & ZEND_ACC_VARIADIC)) {
56-
arg_info = &op_array->arg_info[op_array->num_args];
57-
} else {
58-
return 0;
59-
}
60-
} else {
61-
arg_info = op_array->arg_info - 1;
62-
}
63-
64-
if (ZEND_TYPE_IS_COMPLEX(arg_info->type)) {
65-
if (ZEND_TYPE_HAS_LIST(arg_info->type)) {
66-
/* Intersection types cannot have nested list types */
67-
if (ZEND_TYPE_IS_INTERSECTION(arg_info->type)) {
68-
return ZEND_TYPE_LIST(arg_info->type)->num_types;
69-
}
70-
ZEND_ASSERT(ZEND_TYPE_IS_UNION(arg_info->type));
71-
size_t count = 0;
72-
const zend_type *list_type;
73-
74-
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(arg_info->type), list_type) {
75-
if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
76-
count += ZEND_TYPE_LIST(*list_type)->num_types;
77-
} else {
78-
ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
79-
count += 1;
80-
}
81-
} ZEND_TYPE_LIST_FOREACH_END();
82-
return count;
83-
}
84-
return 1;
85-
}
86-
87-
return 0;
88-
}
89-
9046
static uint32_t add_static_slot(HashTable *hash,
9147
zend_op_array *op_array,
9248
uint32_t op1,
@@ -504,26 +460,6 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
504460
opline->op2.constant = map[opline->op2.constant];
505461
}
506462
switch (opline->opcode) {
507-
case ZEND_RECV_INIT:
508-
case ZEND_RECV:
509-
case ZEND_RECV_VARIADIC:
510-
{
511-
size_t num_classes = type_num_classes(op_array, opline->op1.num);
512-
if (num_classes) {
513-
opline->extended_value = cache_size;
514-
cache_size += num_classes * sizeof(void *);
515-
}
516-
break;
517-
}
518-
case ZEND_VERIFY_RETURN_TYPE:
519-
{
520-
size_t num_classes = type_num_classes(op_array, 0);
521-
if (num_classes) {
522-
opline->op2.num = cache_size;
523-
cache_size += num_classes * sizeof(void *);
524-
}
525-
break;
526-
}
527463
case ZEND_ASSIGN_STATIC_PROP_OP:
528464
if (opline->op1_type == IS_CONST) {
529465
// op1 static property

‎Zend/zend_compile.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2708,8 +2708,6 @@ static void zend_emit_return_type_check(
27082708
opline->result_type = expr->op_type = IS_TMP_VAR;
27092709
opline->result.var = expr->u.op.var = get_temporary_variable();
27102710
}
2711-
2712-
opline->op2.num = zend_alloc_cache_slots(zend_type_get_num_classes(return_info->type));
27132711
}
27142712
}
27152713
/* }}} */
@@ -7754,12 +7752,6 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
77547752
SET_NODE(opline->result, &var_node);
77557753
opline->op1.num = i + 1;
77567754

7757-
if (type_ast) {
7758-
/* Allocate cache slot to speed-up run-time class resolution */
7759-
opline->extended_value =
7760-
zend_alloc_cache_slots(zend_type_get_num_classes(arg_info->type));
7761-
}
7762-
77637755
uint32_t arg_info_flags = _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic, /* is_tentative */ 0)
77647756
| (is_promoted ? _ZEND_IS_PROMOTED_BIT : 0);
77657757
ZEND_TYPE_FULL_MASK(arg_info->type) |= arg_info_flags;

‎Zend/zend_execute.c

Lines changed: 26 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,23 +1099,9 @@ static zend_always_inline bool zend_value_instanceof_static(const zval *zv) {
10991099
return instanceof_function(Z_OBJCE_P(zv), called_scope);
11001100
}
11011101

1102-
/* The cache_slot may only be NULL in debug builds, where arginfo verification of
1103-
* internal functions is enabled. Avoid unnecessary checks in release builds. */
1104-
#if ZEND_DEBUG
1105-
# define HAVE_CACHE_SLOT (cache_slot != NULL)
1106-
#else
1107-
# define HAVE_CACHE_SLOT 1
1108-
#endif
1109-
1110-
#define PROGRESS_CACHE_SLOT() if (HAVE_CACHE_SLOT) {cache_slot++;}
1111-
1112-
static zend_always_inline zend_class_entry *zend_fetch_ce_from_cache_slot(
1113-
void **cache_slot, const zend_type *type)
1102+
static zend_always_inline zend_class_entry *zend_fetch_ce_from_type(
1103+
const zend_type *type)
11141104
{
1115-
if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) {
1116-
return (zend_class_entry *) *cache_slot;
1117-
}
1118-
11191105
zend_string *name = ZEND_TYPE_NAME(*type);
11201106
zend_class_entry *ce;
11211107
if (ZSTR_HAS_CE_CACHE(name)) {
@@ -1134,68 +1120,54 @@ static zend_always_inline zend_class_entry *zend_fetch_ce_from_cache_slot(
11341120
return NULL;
11351121
}
11361122
}
1137-
if (HAVE_CACHE_SLOT) {
1138-
*cache_slot = (void *) ce;
1139-
}
11401123
return ce;
11411124
}
11421125

1143-
static bool zend_check_intersection_type_from_cache_slot(
1126+
static bool zend_check_intersection_type_from_list(
11441127
const zend_type_list *intersection_type_list,
1145-
const zend_class_entry *arg_ce,
1146-
void ***cache_slot_ptr)
1128+
zend_class_entry *arg_ce)
11471129
{
1148-
void**cache_slot=*cache_slot_ptr;
1130+
zend_class_entry*ce;
11491131
const zend_type *list_type;
1150-
bool status = true;
11511132
ZEND_TYPE_LIST_FOREACH(intersection_type_list, list_type) {
1152-
/* Only check classes if the type might be valid */
1153-
if (status) {
1154-
zend_class_entry *ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type);
1155-
/* If type is not an instance of one of the types taking part in the
1156-
* intersection it cannot be a valid instance of the whole intersection type. */
1157-
if (!ce || !instanceof_function(arg_ce, ce)) {
1158-
status = false;
1159-
}
1133+
ce = zend_fetch_ce_from_type(list_type);
1134+
/* If type is not an instance of one of the types taking part in the
1135+
* intersection it cannot be a valid instance of the whole intersection type. */
1136+
if (!ce || !instanceof_function(arg_ce, ce)) {
1137+
return false;
11601138
}
1161-
PROGRESS_CACHE_SLOT();
11621139
} ZEND_TYPE_LIST_FOREACH_END();
1163-
if (HAVE_CACHE_SLOT) {
1164-
*cache_slot_ptr = cache_slot;
1165-
}
1166-
return status;
1140+
return true;
11671141
}
11681142

11691143
static zend_always_inline bool zend_check_type_slow(
1170-
const zend_type *type, zval *arg, const zend_reference *ref,void**cache_slot,
1144+
const zend_type *type, zval *arg, const zend_reference *ref,
11711145
bool is_return_type, bool is_internal)
11721146
{
11731147
if (ZEND_TYPE_IS_COMPLEX(*type) && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
11741148
zend_class_entry *ce;
11751149
if (UNEXPECTED(ZEND_TYPE_HAS_LIST(*type))) {
11761150
if (ZEND_TYPE_IS_INTERSECTION(*type)) {
1177-
return zend_check_intersection_type_from_cache_slot(ZEND_TYPE_LIST(*type), Z_OBJCE_P(arg), &cache_slot);
1151+
return zend_check_intersection_type_from_list(ZEND_TYPE_LIST(*type), Z_OBJCE_P(arg));
11781152
} else {
11791153
const zend_type *list_type;
11801154
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(*type), list_type) {
11811155
if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
1182-
if (zend_check_intersection_type_from_cache_slot(ZEND_TYPE_LIST(*list_type), Z_OBJCE_P(arg), &cache_slot)) {
1156+
if (zend_check_intersection_type_from_list(ZEND_TYPE_LIST(*list_type), Z_OBJCE_P(arg))) {
11831157
return true;
11841158
}
1185-
/* The cache_slot is progressed in zend_check_intersection_type_from_cache_slot() */
11861159
} else {
11871160
ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
1188-
ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type);
1161+
ce = zend_fetch_ce_from_type(list_type);
11891162
/* Instance of a single type part of a union is sufficient to pass the type check */
11901163
if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) {
11911164
return true;
11921165
}
1193-
PROGRESS_CACHE_SLOT();
11941166
}
11951167
} ZEND_TYPE_LIST_FOREACH_END();
11961168
}
11971169
} else {
1198-
ce = zend_fetch_ce_from_cache_slot(cache_slot, type);
1170+
ce = zend_fetch_ce_from_type(type);
11991171
/* If we have a CE we check if it satisfies the type constraint,
12001172
* otherwise it will check if a standard type satisfies it. */
12011173
if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) {
@@ -1232,7 +1204,7 @@ static zend_always_inline bool zend_check_type_slow(
12321204
}
12331205

12341206
static zend_always_inline bool zend_check_type(
1235-
const zend_type *type, zval *arg, void**cache_slot, zend_class_entry *scope,
1207+
const zend_type *type, zval *arg, zend_class_entry *scope,
12361208
bool is_return_type, bool is_internal)
12371209
{
12381210
const zend_reference *ref = NULL;
@@ -1247,25 +1219,25 @@ static zend_always_inline bool zend_check_type(
12471219
return 1;
12481220
}
12491221

1250-
return zend_check_type_slow(type, arg, ref, cache_slot, is_return_type, is_internal);
1222+
return zend_check_type_slow(type, arg, ref, is_return_type, is_internal);
12511223
}
12521224

12531225
ZEND_API bool zend_check_user_type_slow(
1254-
const zend_type *type, zval *arg, const zend_reference *ref, void**cache_slot, bool is_return_type)
1226+
const zend_type *type, zval *arg, const zend_reference *ref, bool is_return_type)
12551227
{
12561228
return zend_check_type_slow(
1257-
type, arg, ref, cache_slot, is_return_type, /* is_internal */ false);
1229+
type, arg, ref, is_return_type, /* is_internal */ false);
12581230
}
12591231

1260-
static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf, uint32_t arg_num, zval *arg, void**cache_slot)
1232+
static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf, uint32_t arg_num, zval *arg)
12611233
{
12621234
const zend_arg_info *cur_arg_info;
12631235

12641236
ZEND_ASSERT(arg_num <= zf->common.num_args);
12651237
cur_arg_info = &zf->common.arg_info[arg_num-1];
12661238

12671239
if (ZEND_TYPE_IS_SET(cur_arg_info->type)
1268-
&& UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
1240+
&& UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, zf->common.scope, 0, 0))) {
12691241
zend_verify_arg_error(zf, cur_arg_info, arg_num, arg);
12701242
return 0;
12711243
}
@@ -1274,10 +1246,10 @@ static zend_always_inline bool zend_verify_recv_arg_type(const zend_function *zf
12741246
}
12751247

12761248
static zend_always_inline bool zend_verify_variadic_arg_type(
1277-
const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *arg, void**cache_slot)
1249+
const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *arg)
12781250
{
12791251
ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type));
1280-
if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
1252+
if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, zf->common.scope, 0, 0))) {
12811253
zend_verify_arg_error(zf, arg_info, arg_num, arg);
12821254
return 0;
12831255
}
@@ -1302,7 +1274,7 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ
13021274
}
13031275

13041276
if (ZEND_TYPE_IS_SET(cur_arg_info->type)
1305-
&& UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, /* cache_slot */NULL, fbc->common.scope, 0, /* is_internal */ 1))) {
1277+
&& UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, fbc->common.scope, 0, /* is_internal */ 1))) {
13061278
return 0;
13071279
}
13081280
arg++;
@@ -1508,7 +1480,7 @@ ZEND_API bool zend_verify_internal_return_type(const zend_function *zf, zval *re
15081480
return 1;
15091481
}
15101482

1511-
if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, /* cache_slot */NULL, NULL, 1, /* is_internal */ 1))) {
1483+
if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, NULL, 1, /* is_internal */ 1))) {
15121484
zend_verify_internal_return_error(zf, ret);
15131485
return 0;
15141486
}

‎Zend/zend_execute.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ ZEND_API ZEND_COLD void zend_verify_never_error(
106106
const zend_function *zf);
107107
ZEND_API bool zend_verify_ref_array_assignable(zend_reference *ref);
108108
ZEND_API bool zend_check_user_type_slow(
109-
const zend_type *type, zval *arg, const zend_reference *ref, void**cache_slot, bool is_return_type);
109+
const zend_type *type, zval *arg, const zend_reference *ref, bool is_return_type);
110110

111111
#if ZEND_DEBUG
112112
ZEND_API bool zend_internal_call_should_throw(const zend_function *fbc, zend_execute_data *call);

‎Zend/zend_vm_def.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4423,7 +4423,7 @@ ZEND_VM_C_LABEL(fcall_end):
44234423
ZEND_VM_CONTINUE();
44244424
}
44254425

4426-
ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED|CACHE_SLOT)
4426+
ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED)
44274427
{
44284428
if (OP1_TYPE == IS_UNUSED) {
44294429
SAVE_OPLINE();
@@ -4465,7 +4465,6 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV
44654465
}
44664466

44674467
zend_reference *ref = NULL;
4468-
void *cache_slot = CACHE_ADDR(opline->op2.num);
44694468
if (UNEXPECTED(retval_ref != retval_ptr)) {
44704469
if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
44714470
ref = Z_REF_P(retval_ref);
@@ -4482,7 +4481,7 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV
44824481
}
44834482

44844483
SAVE_OPLINE();
4485-
if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) {
4484+
if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) {
44864485
zend_verify_return_error(EX(func), retval_ptr);
44874486
HANDLE_EXCEPTION();
44884487
}
@@ -5671,14 +5670,14 @@ ZEND_VM_HELPER(zend_verify_recv_arg_type_helper, ANY, ANY, zval *op_1)
56715670
USE_OPLINE
56725671

56735672
SAVE_OPLINE();
5674-
if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1, CACHE_ADDR(opline->extended_value)))) {
5673+
if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1))) {
56755674
HANDLE_EXCEPTION();
56765675
}
56775676

56785677
ZEND_VM_NEXT_OPCODE();
56795678
}
56805679

5681-
ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED, CACHE_SLOT)
5680+
ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED)
56825681
{
56835682
USE_OPLINE
56845683
uint32_t arg_num = opline->op1.num;
@@ -5697,7 +5696,7 @@ ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED, CACHE_SLOT)
56975696
ZEND_VM_NEXT_OPCODE();
56985697
}
56995698

5700-
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_RECV, op->op2.num == MAY_BE_ANY, ZEND_RECV_NOTYPE, NUM, NUM, CACHE_SLOT)
5699+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_RECV, op->op2.num == MAY_BE_ANY, ZEND_RECV_NOTYPE, NUM, NUM)
57015700
{
57025701
USE_OPLINE
57035702
uint32_t arg_num = opline->op1.num;
@@ -5709,7 +5708,7 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_RECV, op->op2.num == MAY_BE_ANY, ZEND_RECV_NO
57095708
ZEND_VM_NEXT_OPCODE();
57105709
}
57115710

5712-
ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT)
5711+
ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST)
57135712
{
57145713
USE_OPLINE
57155714
uint32_t arg_num;
@@ -5749,7 +5748,7 @@ ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT)
57495748
ZEND_VM_C_LABEL(recv_init_check_type):
57505749
if ((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) {
57515750
SAVE_OPLINE();
5752-
if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) {
5751+
if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param))) {
57535752
HANDLE_EXCEPTION();
57545753
}
57555754
}
@@ -5759,7 +5758,7 @@ ZEND_VM_C_LABEL(recv_init_check_type):
57595758
ZEND_VM_NEXT_OPCODE();
57605759
}
57615760

5762-
ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT)
5761+
ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED)
57635762
{
57645763
USE_OPLINE
57655764
uint32_t arg_num = opline->op1.num;
@@ -5782,7 +5781,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT)
57825781
if (ZEND_TYPE_IS_SET(arg_info->type)) {
57835782
ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS);
57845783
do {
5785-
if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) {
5784+
if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param))) {
57865785
ZEND_HASH_FILL_FINISH();
57875786
HANDLE_EXCEPTION();
57885787
}
@@ -5810,7 +5809,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT)
58105809
if (ZEND_TYPE_IS_SET(arg_info->type)) {
58115810
SEPARATE_ARRAY(params);
58125811
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) {
5813-
if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) {
5812+
if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param))) {
58145813
HANDLE_EXCEPTION();
58155814
}
58165815
Z_TRY_ADDREF_P(param);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /