Skip to content

Commit 7907c91

Browse files
committed
Always use CE_CACHE, remove TYPE_HAS_CE
1 parent 467504c commit 7907c91

15 files changed

+113
-261
lines changed

Diff for: Zend/Optimizer/zend_inference.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -2227,9 +2227,7 @@ static uint32_t zend_convert_type(const zend_script *script, zend_type type, zen
22272227
if (pce) {
22282228
/* As we only have space to store one CE,
22292229
* we use a plain object type for class unions. */
2230-
if (ZEND_TYPE_HAS_CE(type)) {
2231-
*pce = ZEND_TYPE_CE(type);
2232-
} else if (ZEND_TYPE_HAS_NAME(type)) {
2230+
if (ZEND_TYPE_HAS_NAME(type)) {
22332231
zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(type));
22342232
*pce = zend_optimizer_get_class_entry(script, lcname);
22352233
zend_string_release_ex(lcname, 0);

Diff for: Zend/tests/objects_008.phpt

-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
--TEST--
22
method overloading with different method signature
3-
--SKIPIF--
4-
<?php
5-
if (getenv('SKIP_PRELOAD')) die('xfail Difference in class name casing');
6-
?>
73
--FILE--
84
<?php
95

Diff for: Zend/zend.c

+28-35
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "Optimizer/zend_optimizer.h"
3939

4040
static size_t global_map_ptr_last = 0;
41+
static bool startup_done = false;
4142

4243
#ifdef ZTS
4344
ZEND_API int compiler_globals_id;
@@ -1018,40 +1019,6 @@ void zend_register_standard_ini_entries(void) /* {{{ */
10181019
}
10191020
/* }}} */
10201021

1021-
static zend_class_entry *resolve_type_name(zend_string *type_name) {
1022-
zend_string *lc_type_name = zend_string_tolower(type_name);
1023-
zend_class_entry *ce = zend_hash_find_ptr(CG(class_table), lc_type_name);
1024-
1025-
ZEND_ASSERT(ce && ce->type == ZEND_INTERNAL_CLASS);
1026-
zend_string_release(lc_type_name);
1027-
return ce;
1028-
}
1029-
1030-
static void zend_resolve_property_types(void) /* {{{ */
1031-
{
1032-
zend_class_entry *ce;
1033-
zend_property_info *prop_info;
1034-
1035-
ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
1036-
if (ce->type != ZEND_INTERNAL_CLASS) {
1037-
continue;
1038-
}
1039-
1040-
if (UNEXPECTED(ZEND_CLASS_HAS_TYPE_HINTS(ce))) {
1041-
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
1042-
zend_type *single_type;
1043-
ZEND_TYPE_FOREACH(prop_info->type, single_type) {
1044-
if (ZEND_TYPE_HAS_NAME(*single_type)) {
1045-
zend_string *type_name = ZEND_TYPE_NAME(*single_type);
1046-
ZEND_TYPE_SET_CE(*single_type, resolve_type_name(type_name));
1047-
zend_string_release(type_name);
1048-
}
1049-
} ZEND_TYPE_FOREACH_END();
1050-
} ZEND_HASH_FOREACH_END();
1051-
}
1052-
} ZEND_HASH_FOREACH_END();
1053-
}
1054-
/* }}} */
10551022

10561023
/* Unlink the global (r/o) copies of the class, function and constant tables,
10571024
* and use a fresh r/w copy for the startup thread
@@ -1065,7 +1032,7 @@ zend_result zend_post_startup(void) /* {{{ */
10651032
zend_executor_globals *executor_globals = ts_resource(executor_globals_id);
10661033
#endif
10671034

1068-
zend_resolve_property_types();
1035+
startup_done = true;
10691036

10701037
if (zend_post_startup_cb) {
10711038
zend_result (*cb)(void) = zend_post_startup_cb;
@@ -1892,3 +1859,29 @@ ZEND_API void zend_map_ptr_extend(size_t last)
18921859
CG(map_ptr_last) = last;
18931860
}
18941861
}
1862+
1863+
ZEND_API void zend_alloc_ce_cache(zend_string *type_name)
1864+
{
1865+
if (ZSTR_HAS_CE_CACHE(type_name) || !ZSTR_IS_INTERNED(type_name)) {
1866+
return;
1867+
}
1868+
1869+
if ((GC_FLAGS(type_name) & IS_STR_PERMANENT) && startup_done) {
1870+
/* Don't allocate slot on permanent interned string outside module startup.
1871+
* The cache slot would no longer be valid on the next request. */
1872+
return;
1873+
}
1874+
1875+
if (zend_string_equals_literal_ci(type_name, "self")
1876+
|| zend_string_equals_literal_ci(type_name, "parent")) {
1877+
return;
1878+
}
1879+
1880+
/* We use the refcount to keep map_ptr of corresponding type */
1881+
uint32_t ret;
1882+
do {
1883+
ret = (uint32_t)(uintptr_t)zend_map_ptr_new();
1884+
} while (ret <= 2);
1885+
GC_ADD_FLAGS(type_name, IS_STR_CLASS_NAME_MAP_PTR);
1886+
GC_SET_REFCOUNT(type_name, ret);
1887+
}

Diff for: Zend/zend_API.c

+12
Original file line numberDiff line numberDiff line change
@@ -3053,6 +3053,7 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class
30533053

30543054
class_entry->type = ZEND_INTERNAL_CLASS;
30553055
zend_initialize_class_data(class_entry, 0);
3056+
zend_alloc_ce_cache(class_entry->name);
30563057
class_entry->ce_flags = orig_class_entry->ce_flags | ce_flags | ZEND_ACC_CONSTANTS_UPDATED | ZEND_ACC_LINKED | ZEND_ACC_RESOLVED_PARENT | ZEND_ACC_RESOLVED_INTERFACES;
30573058
class_entry->info.internal.module = EG(current_module);
30583059

@@ -4126,6 +4127,17 @@ ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, z
41264127
property_info->ce = ce;
41274128
property_info->type = type;
41284129

4130+
if (is_persistent_class(ce)) {
4131+
zend_type *single_type;
4132+
ZEND_TYPE_FOREACH(property_info->type, single_type) {
4133+
if (ZEND_TYPE_HAS_NAME(*single_type)) {
4134+
zend_string *name = zend_new_interned_string(ZEND_TYPE_NAME(*single_type));
4135+
ZEND_TYPE_SET_PTR(*single_type, name);
4136+
zend_alloc_ce_cache(name);
4137+
}
4138+
} ZEND_TYPE_FOREACH_END();
4139+
}
4140+
41294141
zend_hash_update_ptr(&ce->properties_info, name, property_info);
41304142

41314143
return property_info;

Diff for: Zend/zend_compile.c

+10-35
Original file line numberDiff line numberDiff line change
@@ -1202,43 +1202,13 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
12021202
zend_type *list_type;
12031203
bool is_intersection = ZEND_TYPE_IS_INTERSECTION(type);
12041204
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) {
1205-
if (ZEND_TYPE_HAS_CE(*list_type)) {
1206-
str = add_type_string(str, ZEND_TYPE_CE(*list_type)->name, is_intersection);
1207-
} else {
1208-
zend_string *name = ZEND_TYPE_NAME(*list_type);
1209-
1210-
if (ZSTR_HAS_CE_CACHE(name)
1211-
&& ZSTR_GET_CE_CACHE(name)) {
1212-
zend_class_entry *ce = ZSTR_GET_CE_CACHE(name);
1213-
if (ce->ce_flags & ZEND_ACC_ANON_CLASS) {
1214-
zend_string *tmp = zend_string_init(ZSTR_VAL(ce->name), strlen(ZSTR_VAL(ce->name)), 0);
1215-
str = add_type_string(str, tmp, is_intersection);
1216-
} else {
1217-
str = add_type_string(str, ce->name, is_intersection);
1218-
}
1219-
} else {
1220-
zend_string *resolved = resolve_class_name(name, scope);
1221-
str = add_type_string(str, resolved, is_intersection);
1222-
zend_string_release(resolved);
1223-
}
1224-
}
1205+
zend_string *name = ZEND_TYPE_NAME(*list_type);
1206+
zend_string *resolved = resolve_class_name(name, scope);
1207+
str = add_type_string(str, resolved, is_intersection);
1208+
zend_string_release(resolved);
12251209
} ZEND_TYPE_LIST_FOREACH_END();
12261210
} else if (ZEND_TYPE_HAS_NAME(type)) {
1227-
zend_string *name = ZEND_TYPE_NAME(type);
1228-
1229-
if (ZSTR_HAS_CE_CACHE(name)
1230-
&& ZSTR_GET_CE_CACHE(name)) {
1231-
zend_class_entry *ce = ZSTR_GET_CE_CACHE(name);
1232-
if (ce->ce_flags & ZEND_ACC_ANON_CLASS) {
1233-
str = zend_string_init(ZSTR_VAL(ce->name), strlen(ZSTR_VAL(ce->name)), 0);
1234-
} else {
1235-
str = zend_string_copy(ce->name);
1236-
}
1237-
} else {
1238-
str = resolve_class_name(name, scope);
1239-
}
1240-
} else if (ZEND_TYPE_HAS_CE(type)) {
1241-
str = zend_string_copy(ZEND_TYPE_CE(type)->name);
1211+
str = resolve_class_name(ZEND_TYPE_NAME(type), scope);
12421212
}
12431213

12441214
uint32_t type_mask = ZEND_TYPE_PURE_MASK(type);
@@ -6232,6 +6202,8 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
62326202
}
62336203
}
62346204

6205+
class_name = zend_new_interned_string(class_name);
6206+
zend_alloc_ce_cache(class_name);
62356207
return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, 0, 0);
62366208
}
62376209
}
@@ -7687,6 +7659,9 @@ void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{
76877659
ce->type = ZEND_USER_CLASS;
76887660
ce->name = name;
76897661
zend_initialize_class_data(ce, 1);
7662+
if (!(decl->flags & ZEND_ACC_ANON_CLASS)) {
7663+
zend_alloc_ce_cache(ce->name);
7664+
}
76907665

76917666
if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
76927667
ce->ce_flags |= ZEND_ACC_PRELOADED;

Diff for: Zend/zend_execute.c

+4-19
Original file line numberDiff line numberDiff line change
@@ -851,11 +851,6 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error(
851851

852852
static zend_class_entry *resolve_single_class_type(zend_string *name, zend_class_entry *self_ce) {
853853
if (zend_string_equals_literal_ci(name, "self")) {
854-
/* We need to explicitly check for this here, to avoid updating the type in the trait and
855-
* later using the wrong "self" when the trait is used in a class. */
856-
if (UNEXPECTED((self_ce->ce_flags & ZEND_ACC_TRAIT) != 0)) {
857-
return NULL;
858-
}
859854
return self_ce;
860855
} else if (zend_string_equals_literal_ci(name, "parent")) {
861856
return self_ce->parent;
@@ -866,26 +861,16 @@ static zend_class_entry *resolve_single_class_type(zend_string *name, zend_class
866861

867862
static zend_always_inline zend_class_entry *zend_ce_from_type(
868863
zend_property_info *info, zend_type *type) {
869-
if (UNEXPECTED(!ZEND_TYPE_HAS_NAME(*type))) {
870-
ZEND_ASSERT(ZEND_TYPE_HAS_CE(*type));
871-
return ZEND_TYPE_CE(*type);
872-
}
873-
864+
ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*type));
874865
zend_string *name = ZEND_TYPE_NAME(*type);
875-
zend_class_entry *ce;
876866
if (ZSTR_HAS_CE_CACHE(name)) {
877-
ce = ZSTR_GET_CE_CACHE(name);
867+
zend_class_entry *ce = ZSTR_GET_CE_CACHE(name);
878868
if (!ce) {
879869
ce = zend_lookup_class_ex(name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
880870
}
881-
} else {
882-
ce = resolve_single_class_type(name, info->ce);
883-
if (ce && !(info->ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
884-
zend_string_release(name);
885-
ZEND_TYPE_SET_CE(*type, ce);
886-
}
871+
return ce;
887872
}
888-
return ce;
873+
return resolve_single_class_type(name, info->ce);
889874
}
890875

891876
static bool zend_check_and_resolve_property_class_type(

Diff for: Zend/zend_inheritance.c

-10
Original file line numberDiff line numberDiff line change
@@ -430,9 +430,6 @@ static inheritance_status zend_is_intersection_subtype_of_class(
430430

431431
if (!proto_ce) proto_ce = lookup_class(proto_scope, proto_class_name);
432432
fe_ce = lookup_class(fe_scope, fe_class_name);
433-
} else if (ZEND_TYPE_HAS_CE(*single_type)) {
434-
if (!proto_ce) proto_ce = lookup_class(proto_scope, proto_class_name);
435-
fe_ce = ZEND_TYPE_CE(*single_type);
436433
} else {
437434
/* standard type in an intersection type is impossible,
438435
* because it would be a fatal compile error */
@@ -503,9 +500,6 @@ static inheritance_status zend_is_class_subtype_of_type(
503500

504501
if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name);
505502
proto_ce = lookup_class(proto_scope, proto_class_name);
506-
} else if (ZEND_TYPE_HAS_CE(*single_type)) {
507-
if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name);
508-
proto_ce = ZEND_TYPE_CE(*single_type);
509503
} else {
510504
/* standard type */
511505
ZEND_ASSERT(!is_intersection);
@@ -541,10 +535,6 @@ static zend_string *get_class_from_type(
541535
*ce = NULL;
542536
return resolve_class_name(scope, ZEND_TYPE_NAME(single_type));
543537
}
544-
if (ZEND_TYPE_HAS_CE(single_type)) {
545-
*ce = ZEND_TYPE_CE(single_type);
546-
return (*ce)->name;
547-
}
548538
return NULL;
549539
}
550540

Diff for: Zend/zend_map_ptr.h

+1
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,6 @@
103103
ZEND_API void zend_map_ptr_reset(void);
104104
ZEND_API void *zend_map_ptr_new(void);
105105
ZEND_API void zend_map_ptr_extend(size_t last);
106+
ZEND_API void zend_alloc_ce_cache(zend_string *type_name);
106107

107108
#endif /* ZEND_MAP_PTR_H */

Diff for: Zend/zend_types.h

+3-18
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,11 @@ typedef void (*copy_ctor_func_t)(zval *pElement);
111111
* ZEND_TYPE_IS_SET() - checks if there is a type-hint
112112
* ZEND_TYPE_IS_ONLY_MASK() - checks if type-hint refer to standard type only
113113
* ZEND_TYPE_IS_COMPLEX() - checks if type is a type_list, or contains a class either as a CE or as a name
114-
* ZEND_TYPE_HAS_CE() - checks if type-hint contains some class as zend_class_entry *
115114
* ZEND_TYPE_HAS_NAME() - checks if type-hint contains some class as zend_string *
116115
* ZEND_TYPE_IS_INTERSECTION() - checks if the type_list represents an intersection type list
117116
* ZEND_TYPE_IS_UNION() - checks if the type_list represents a union type list
118117
*
119118
* ZEND_TYPE_NAME() - returns referenced class name
120-
* ZEND_TYPE_CE() - returns referenced class entry
121119
* ZEND_TYPE_PURE_MASK() - returns MAY_BE_* type mask
122120
* ZEND_TYPE_FULL_MASK() - returns MAY_BE_* type mask together with other flags
123121
*
@@ -144,9 +142,8 @@ typedef struct {
144142
#define _ZEND_TYPE_MASK ((1u << 25) - 1)
145143
/* Only one of these bits may be set. */
146144
#define _ZEND_TYPE_NAME_BIT (1u << 24)
147-
#define _ZEND_TYPE_CE_BIT (1u << 23)
148145
#define _ZEND_TYPE_LIST_BIT (1u << 22)
149-
#define _ZEND_TYPE_KIND_MASK (_ZEND_TYPE_LIST_BIT|_ZEND_TYPE_CE_BIT|_ZEND_TYPE_NAME_BIT)
146+
#define _ZEND_TYPE_KIND_MASK (_ZEND_TYPE_LIST_BIT|_ZEND_TYPE_NAME_BIT)
150147
/* TODO: bit 21 is not used */
151148
/* Whether the type list is arena allocated */
152149
#define _ZEND_TYPE_ARENA_BIT (1u << 20)
@@ -163,13 +160,10 @@ typedef struct {
163160
(((t).type_mask & _ZEND_TYPE_MASK) != 0)
164161

165162
/* If a type is complex it means it's either a list with a union or intersection,
166-
* or the void pointer is a CE/Name */
163+
* or the void pointer is a class name */
167164
#define ZEND_TYPE_IS_COMPLEX(t) \
168165
((((t).type_mask) & _ZEND_TYPE_KIND_MASK) != 0)
169166

170-
#define ZEND_TYPE_HAS_CE(t) \
171-
((((t).type_mask) & _ZEND_TYPE_CE_BIT) != 0)
172-
173167
#define ZEND_TYPE_HAS_NAME(t) \
174168
((((t).type_mask) & _ZEND_TYPE_NAME_BIT) != 0)
175169

@@ -194,9 +188,6 @@ typedef struct {
194188
#define ZEND_TYPE_LITERAL_NAME(t) \
195189
((const char *) (t).ptr)
196190

197-
#define ZEND_TYPE_CE(t) \
198-
((zend_class_entry *) (t).ptr)
199-
200191
#define ZEND_TYPE_LIST(t) \
201192
((zend_type_list *) (t).ptr)
202193

@@ -242,13 +233,10 @@ typedef struct {
242233
(t).type_mask |= (kind_bit); \
243234
} while (0)
244235

245-
#define ZEND_TYPE_SET_CE(t, ce) \
246-
ZEND_TYPE_SET_PTR_AND_KIND(t, ce, _ZEND_TYPE_CE_BIT)
247-
248236
#define ZEND_TYPE_SET_LIST(t, list) \
249237
ZEND_TYPE_SET_PTR_AND_KIND(t, list, _ZEND_TYPE_LIST_BIT)
250238

251-
/* FULL_MASK() includes the MAY_BE_* type mask, the CE/NAME bits, as well as extra reserved bits.
239+
/* FULL_MASK() includes the MAY_BE_* type mask, as well as additional metadata bits.
252240
* The PURE_MASK() only includes the MAY_BE_* type mask. */
253241
#define ZEND_TYPE_FULL_MASK(t) \
254242
((t).type_mask)
@@ -285,9 +273,6 @@ typedef struct {
285273
#define ZEND_TYPE_INIT_PTR_MASK(ptr, type_mask) \
286274
{ (void *) (ptr), (type_mask) }
287275

288-
#define ZEND_TYPE_INIT_CE(_ce, allow_null, extra_flags) \
289-
ZEND_TYPE_INIT_PTR(_ce, _ZEND_TYPE_CE_BIT, allow_null, extra_flags)
290-
291276
#define ZEND_TYPE_INIT_CLASS(class_name, allow_null, extra_flags) \
292277
ZEND_TYPE_INIT_PTR(class_name, _ZEND_TYPE_NAME_BIT, allow_null, extra_flags)
293278

0 commit comments

Comments
 (0)