Skip to content

Commit c9bd24d

Browse files
committed
Improved ineritance code
1 parent 5de64a2 commit c9bd24d

File tree

2 files changed

+69
-44
lines changed

2 files changed

+69
-44
lines changed

Zend/zend_hash.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,22 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht,
800800
__fill_ht->nInternalPointer = 0; \
801801
} while (0)
802802

803+
static zend_always_inline void _zend_hash_append(HashTable *ht, zend_string *key, zval *zv)
804+
{
805+
uint32_t idx = ht->nNumUsed++;
806+
uint32_t nIndex;
807+
Bucket *p = ht->arData + idx;
808+
809+
ZVAL_COPY_VALUE(&p->val, zv);
810+
p->key = key;
811+
p->h = key->h;
812+
nIndex = p->h & ht->nTableMask;
813+
Z_NEXT(p->val) = ht->arHash[nIndex];
814+
ht->arHash[nIndex] = idx;
815+
ht->nNumUsed = idx + 1;
816+
ht->nNumOfElements++;
817+
}
818+
803819
static zend_always_inline void _zend_hash_append_ptr(HashTable *ht, zend_string *key, void *ptr)
804820
{
805821
uint32_t idx = ht->nNumUsed++;

Zend/zend_inheritance.c

Lines changed: 53 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -619,34 +619,34 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function *
619619

620620
static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, zend_string *key, zend_class_entry *child_ce) /* {{{ */
621621
{
622-
uint32_t parent_flags = parent->common.fn_flags;
623-
zend_function *child;
622+
zval *child = zend_hash_find(child_function_table, key);
624623

625-
if ((child = zend_hash_find_ptr(child_function_table, key)) == NULL) {
626-
if (parent_flags & (ZEND_ACC_ABSTRACT)) {
624+
if (child == NULL) {
625+
if (parent->common.fn_flags & (ZEND_ACC_ABSTRACT)) {
627626
child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
628627
}
629628
return 1; /* method doesn't exist in child, copy from parent */
630629
}
631630

632-
do_inheritance_check_on_method(child, parent);
631+
do_inheritance_check_on_method((zend_function*)Z_PTR_P(child), parent);
633632

634633
return 0;
635634
}
636635
/* }}} */
637636

638637
static void do_inherit_property(zend_property_info *parent_info, zend_string *key, zend_class_entry *ce) /* {{{ */
639638
{
640-
zend_property_info *child_info = zend_hash_find_ptr(&ce->properties_info, key);
641-
zend_class_entry *parent_ce = ce->parent;
639+
zval *child = zend_hash_find(&ce->properties_info, key);
640+
zend_property_info *child_info;
642641

643-
if (UNEXPECTED(child_info)) {
642+
if (UNEXPECTED(child)) {
643+
child_info = Z_PTR_P(child);
644644
if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
645645
child_info->flags |= ZEND_ACC_CHANGED;
646646
} else {
647647
if ((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC)) {
648648
zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s",
649-
(parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name->val, key->val,
649+
(parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->parent->name->val, key->val,
650650
(child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name->val, key->val);
651651
}
652652

@@ -655,7 +655,7 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke
655655
}
656656

657657
if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
658-
zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name->val, key->val, zend_visibility_string(parent_info->flags), parent_ce->name->val, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
658+
zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name->val, key->val, zend_visibility_string(parent_info->flags), ce->parent->name->val, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
659659
} else if ((child_info->flags & ZEND_ACC_STATIC) == 0) {
660660
int parent_num = OBJ_PROP_TO_NUM(parent_info->offset);
661661
int child_num = OBJ_PROP_TO_NUM(child_info->offset);
@@ -736,28 +736,22 @@ ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_
736736
}
737737
/* }}} */
738738

739-
#ifdef ZTS
740-
# define zval_property_ctor(parent_ce, ce) \
741-
(((parent_ce)->type != (ce)->type) ? ZVAL_COPY_CTOR : zval_add_ref)
742-
#else
743-
# define zval_property_ctor(parent_ce, ce) \
744-
zval_add_ref
745-
#endif
746-
747739
static void do_inherit_class_constant(zend_string *name, zval *zv, zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */
748740
{
749-
if (!Z_ISREF_P(zv)) {
750-
if (parent_ce->type == ZEND_INTERNAL_CLASS) {
751-
ZVAL_NEW_PERSISTENT_REF(zv, zv);
752-
} else {
753-
ZVAL_NEW_REF(zv, zv);
741+
if (!zend_hash_exists(&ce->constants_table, name)) {
742+
if (!Z_ISREF_P(zv)) {
743+
if (parent_ce->type == ZEND_INTERNAL_CLASS) {
744+
ZVAL_NEW_PERSISTENT_REF(zv, zv);
745+
} else {
746+
ZVAL_NEW_REF(zv, zv);
747+
}
748+
}
749+
if (Z_CONSTANT_P(Z_REFVAL_P(zv))) {
750+
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
754751
}
755-
}
756-
if (Z_CONSTANT_P(Z_REFVAL_P(zv))) {
757-
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
758-
}
759-
if (zend_hash_add(&ce->constants_table, name, zv)) {
760752
Z_ADDREF_P(zv);
753+
zend_string_addref(name);
754+
_zend_hash_append(&ce->constants_table, name, zv);
761755
}
762756
}
763757
/* }}} */
@@ -774,7 +768,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
774768
if (!(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
775769
zend_error_noreturn(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name->val, parent_ce->name->val);
776770
}
777-
} else {
771+
} else if (UNEXPECTED(parent_ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_FINAL))) {
778772
/* Class declaration must not extend traits or interfaces */
779773
if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
780774
zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name->val, parent_ce->name->val);
@@ -888,24 +882,39 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
888882
}
889883
} ZEND_HASH_FOREACH_END();
890884

891-
zend_hash_extend(&ce->properties_info,
892-
zend_hash_num_elements(&ce->properties_info) +
893-
zend_hash_num_elements(&parent_ce->properties_info), 0);
885+
if (zend_hash_num_elements(&parent_ce->properties_info)) {
886+
zend_hash_extend(&ce->properties_info,
887+
zend_hash_num_elements(&ce->properties_info) +
888+
zend_hash_num_elements(&parent_ce->properties_info), 0);
894889

895-
ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, property_info) {
896-
do_inherit_property(property_info, key, ce);
897-
} ZEND_HASH_FOREACH_END();
890+
ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, property_info) {
891+
do_inherit_property(property_info, key, ce);
892+
} ZEND_HASH_FOREACH_END();
893+
}
898894

899-
ZEND_HASH_FOREACH_STR_KEY_VAL(&parent_ce->constants_table, key, zv) {
900-
do_inherit_class_constant(key, zv, ce, parent_ce);
901-
} ZEND_HASH_FOREACH_END();
895+
if (zend_hash_num_elements(&parent_ce->constants_table)) {
896+
zend_hash_extend(&ce->constants_table,
897+
zend_hash_num_elements(&ce->constants_table) +
898+
zend_hash_num_elements(&parent_ce->constants_table), 0);
902899

903-
ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) {
904-
if (do_inherit_method_check(&ce->function_table, func, key, ce)) {
905-
zend_function *new_func = do_inherit_method(func, ce);
906-
zend_hash_add_new_ptr(&ce->function_table, key, new_func);
907-
}
908-
} ZEND_HASH_FOREACH_END();
900+
ZEND_HASH_FOREACH_STR_KEY_VAL(&parent_ce->constants_table, key, zv) {
901+
do_inherit_class_constant(key, zv, ce, parent_ce);
902+
} ZEND_HASH_FOREACH_END();
903+
}
904+
905+
if (zend_hash_num_elements(&parent_ce->function_table)) {
906+
zend_hash_extend(&ce->function_table,
907+
zend_hash_num_elements(&ce->function_table) +
908+
zend_hash_num_elements(&parent_ce->function_table), 0);
909+
910+
ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) {
911+
if (do_inherit_method_check(&ce->function_table, func, key, ce)) {
912+
zend_function *new_func = do_inherit_method(func, ce);
913+
zend_string_addref(key);
914+
_zend_hash_append_ptr(&ce->function_table, key, new_func);
915+
}
916+
} ZEND_HASH_FOREACH_END();
917+
}
909918

910919
do_inherit_parent_constructor(ce);
911920

0 commit comments

Comments
 (0)