1
0
mirror of https://github.com/php/php-src.git synced 2026-04-29 19:23:22 +02:00

Keep information about unresolved parent class in zend_class_entry->parent_name

This commit is contained in:
Dmitry Stogov
2018-08-24 00:20:57 +03:00
parent 644bdaf9cd
commit 8050f4a334
10 changed files with 56 additions and 22 deletions
+4 -1
View File
@@ -115,7 +115,10 @@ typedef struct _zend_trait_alias {
struct _zend_class_entry {
char type;
zend_string *name;
zend_class_entry *parent;
union {
zend_class_entry *parent;
zend_string *parent_name;
};
int refcount;
uint32_t ce_flags;
+6 -5
View File
@@ -6403,7 +6403,7 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */
if (extends_ast) {
znode extends_node;
zend_string *extends_name;
zend_string *extends_name, *parent_name;
if (!zend_is_const_default_class_ref(extends_ast)) {
extends_name = zend_ast_get_str(extends_ast);
@@ -6416,11 +6416,12 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */
zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
}
extends_name = Z_STR(extends_node.u.constant);
extends_const = zend_add_class_name_literal(CG(active_op_array),
zend_resolve_class_name(extends_name,
extends_ast->kind == ZEND_AST_ZVAL ? extends_ast->attr : ZEND_NAME_FQ));
parent_name = zend_resolve_class_name(extends_name,
extends_ast->kind == ZEND_AST_ZVAL ? extends_ast->attr : ZEND_NAME_FQ);
extends_const = zend_add_class_name_literal(CG(active_op_array), parent_name);
ce->parent_name = zend_string_copy(parent_name);
zend_string_release_ex(extends_name, 0);
ce->ce_flags |= ZEND_ACC_INHERITED;
ce->ce_flags |= ZEND_ACC_INHERITED | ZEND_ACC_UNRESOLVED_PARENT;
}
opline = get_next_op(CG(active_op_array));
+3
View File
@@ -244,6 +244,9 @@ typedef struct _zend_oparray_context {
/* Class extends another class | | | */
#define ZEND_ACC_INHERITED (1 << 10) /* X | | | */
/* | | | */
/* Class extends another class | | | */
#define ZEND_ACC_UNRESOLVED_PARENT (1 << 11) /* X | | | */
/* | | | */
/* Class implements interface(s) | | | */
#define ZEND_ACC_IMPLEMENT_INTERFACES (1 << 19) /* X | | | */
/* | | | */
+4
View File
@@ -816,6 +816,10 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
}
}
if (ce->ce_flags & ZEND_ACC_UNRESOLVED_PARENT) {
zend_string_release_ex(ce->parent_name, 0);
ce->ce_flags &= ~ZEND_ACC_UNRESOLVED_PARENT;
}
ce->parent = parent_ce;
/* Inherit interfaces */
+3
View File
@@ -218,6 +218,9 @@ ZEND_API void destroy_zend_class(zval *zv)
}
switch (ce->type) {
case ZEND_USER_CLASS:
if (ce->ce_flags & ZEND_ACC_UNRESOLVED_PARENT) {
zend_string_release_ex(ce->parent_name, 0);
}
if (ce->default_properties_table) {
zval *p = ce->default_properties_table;
zval *end = p + ce->default_properties_count;
+10 -8
View File
@@ -2981,7 +2981,7 @@ static int zend_update_type_info(const zend_op_array *op_array,
}
break;
case ZEND_FETCH_CLASS_PARENT:
if (op_array->scope && op_array->scope->parent) {
if (op_array->scope && op_array->scope->parent && !(op_array->scope->ce_flags & ZEND_ACC_UNRESOLVED_PARENT)) {
UPDATE_SSA_OBJ_TYPE(op_array->scope->parent, 0, ssa_ops[i].result_def);
} else {
UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
@@ -3464,9 +3464,11 @@ unknown_opcode:
static uint32_t get_class_entry_rank(zend_class_entry *ce) {
uint32_t rank = 0;
while (ce->parent) {
rank++;
ce = ce->parent;
if (!(ce->ce_flags & ZEND_ACC_UNRESOLVED_PARENT)) {
while (ce->parent) {
rank++;
ce = ce->parent;
}
}
return rank;
}
@@ -3487,17 +3489,17 @@ static zend_class_entry *join_class_entries(
while (rank1 != rank2) {
if (rank1 > rank2) {
ce1 = ce1->parent;
ce1 = (ce1->ce_flags & ZEND_ACC_UNRESOLVED_PARENT) ? NULL : ce1->parent;
rank1--;
} else {
ce2 = ce2->parent;
ce2 = (ce2->ce_flags & ZEND_ACC_UNRESOLVED_PARENT) ? NULL : ce2->parent;
rank2--;
}
}
while (ce1 != ce2) {
ce1 = ce1->parent;
ce2 = ce2->parent;
ce1 = (ce1->ce_flags & ZEND_ACC_UNRESOLVED_PARENT) ? NULL : ce1->parent;
ce2 = (ce2->ce_flags & ZEND_ACC_UNRESOLVED_PARENT) ? NULL : ce2->parent;
}
if (ce1) {
+2 -2
View File
@@ -292,7 +292,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
*pce = ce = ARENA_REALLOC(old_ce);
ce->refcount = 1;
if (ce->parent) {
if (ce->parent && !(ce->ce_flags & ZEND_ACC_UNRESOLVED_PARENT)) {
ce->parent = ARENA_REALLOC(ce->parent);
}
@@ -312,7 +312,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
/* static members */
if (old_ce->default_static_members_table) {
int i, end;
zend_class_entry *parent = ce->parent;
zend_class_entry *parent = (ce->ce_flags & ZEND_ACC_UNRESOLVED_PARENT) ? NULL : ce->parent;
ce->default_static_members_table = emalloc(sizeof(zval) * old_ce->default_static_members_count);
i = ce->default_static_members_count - 1;
+16 -4
View File
@@ -604,12 +604,19 @@ static void zend_file_cache_serialize_class(zval *zv,
void *buf)
{
zend_class_entry *ce;
zend_class_entry *parent = NULL;
SERIALIZE_PTR(Z_PTR_P(zv));
ce = Z_PTR_P(zv);
UNSERIALIZE_PTR(ce);
SERIALIZE_STR(ce->name);
if (ce->ce_flags & ZEND_ACC_UNRESOLVED_PARENT) {
SERIALIZE_STR(ce->parent_name);
} else {
parent = ce->parent;
SERIALIZE_PTR(ce->parent);
}
zend_file_cache_serialize_hash(&ce->function_table, script, info, buf, zend_file_cache_serialize_func);
if (ce->default_properties_table) {
zval *p, *end;
@@ -632,7 +639,7 @@ static void zend_file_cache_serialize_class(zval *zv,
/* Serialize only static properties in this class.
* Static properties from parent classes will be handled in class_copy_ctor */
p = table + (ce->parent ? ce->parent->default_static_members_count : 0);
p = table + (parent ? parent->default_static_members_count : 0);
end = table + ce->default_static_members_count;
while (p < end) {
zend_file_cache_serialize_zval(p, script, info, buf);
@@ -727,7 +734,6 @@ static void zend_file_cache_serialize_class(zval *zv,
}
}
SERIALIZE_PTR(ce->parent);
SERIALIZE_PTR(ce->constructor);
SERIALIZE_PTR(ce->destructor);
SERIALIZE_PTR(ce->clone);
@@ -1238,12 +1244,18 @@ static void zend_file_cache_unserialize_class(zval *zv,
void *buf)
{
zend_class_entry *ce;
zend_class_entry *parent = NULL;
UNSERIALIZE_PTR(Z_PTR_P(zv));
ce = Z_PTR_P(zv);
UNSERIALIZE_STR(ce->name);
UNSERIALIZE_PTR(ce->parent);
if (ce->ce_flags & ZEND_ACC_UNRESOLVED_PARENT) {
UNSERIALIZE_STR(ce->parent_name);
} else {
UNSERIALIZE_PTR(ce->parent);
parent = ce->parent;
}
zend_file_cache_unserialize_hash(&ce->function_table,
script, buf, zend_file_cache_unserialize_func, ZEND_FUNCTION_DTOR);
if (ce->default_properties_table) {
@@ -1264,7 +1276,7 @@ static void zend_file_cache_unserialize_class(zval *zv,
* Static properties from parent classes will be handled in class_copy_ctor */
UNSERIALIZE_PTR(ce->default_static_members_table);
table = ce->default_static_members_table;
p = table + (ce->parent ? ce->parent->default_static_members_count : 0);
p = table + (parent ? parent->default_static_members_count : 0);
end = table + ce->default_static_members_count;
while (p < end) {
zend_file_cache_unserialize_zval(p, script, buf);
+5 -2
View File
@@ -722,6 +722,9 @@ static void zend_persist_class_entry(zval *zv)
ce = Z_PTR_P(zv) = ZCG(arena_mem);
ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_class_entry)));
zend_accel_store_interned_string(ce->name);
if (ce->ce_flags & ZEND_ACC_UNRESOLVED_PARENT) {
zend_accel_store_interned_string(ce->parent_name);
}
zend_hash_persist(&ce->function_table, zend_persist_class_method);
if (ce->default_properties_table) {
int i;
@@ -737,7 +740,7 @@ static void zend_persist_class_entry(zval *zv)
/* Persist only static properties in this class.
* Static properties from parent classes will be handled in class_copy_ctor */
i = ce->parent ? ce->parent->default_static_members_count : 0;
i = (ce->parent && !(ce->ce_flags & ZEND_ACC_UNRESOLVED_PARENT)) ? ce->parent->default_static_members_count : 0;
for (; i < ce->default_static_members_count; i++) {
zend_persist_zval(&ce->default_static_members_table[i]);
}
@@ -838,7 +841,7 @@ static int zend_update_parent_ce(zval *zv)
{
zend_class_entry *ce = Z_PTR_P(zv);
if (ce->parent) {
if (ce->parent && !(ce->ce_flags & ZEND_ACC_UNRESOLVED_PARENT)) {
ce->parent = zend_shared_alloc_get_xlat_entry(ce->parent);
}
+3
View File
@@ -312,6 +312,9 @@ static void zend_persist_class_entry_calc(zval *zv)
if (ce->type == ZEND_USER_CLASS) {
ADD_ARENA_SIZE(sizeof(zend_class_entry));
ADD_INTERNED_STRING(ce->name, 0);
if (ce->ce_flags & ZEND_ACC_UNRESOLVED_PARENT) {
ADD_INTERNED_STRING(ce->parent_name, 0);
}
zend_hash_persist_calc(&ce->function_table, zend_persist_class_method_calc);
if (ce->default_properties_table) {
int i;