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:
+4
-1
@@ -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
@@ -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));
|
||||
|
||||
@@ -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 | | | */
|
||||
/* | | | */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user