1
0
mirror of https://github.com/php/php-src.git synced 2026-04-02 21:52:36 +02:00

Reuse part of the class binding logic

This part of DECLARE_CLASS and DECLARE_CLASS_DELAYED is the
same.
This commit is contained in:
Nikita Popov
2021-07-27 16:54:45 +02:00
parent 8834cf013b
commit dcf5e5bbf0
4 changed files with 41 additions and 54 deletions

View File

@@ -1100,6 +1100,32 @@ ZEND_API zend_result do_bind_function(zend_function *func, zval *lcname) /* {{{
}
/* }}} */
ZEND_API zend_class_entry *zend_bind_class_in_slot(
zval *class_table_slot, zval *lcname, zend_string *lc_parent_name)
{
zend_class_entry *ce = Z_PTR_P(class_table_slot);
zval *zv = zend_hash_set_bucket_key(
EG(class_table), (Bucket *) class_table_slot, Z_STR_P(lcname));
if (UNEXPECTED(!zv)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
return NULL;
}
if (ce->ce_flags & ZEND_ACC_LINKED) {
return ce;
}
ce = zend_do_link_class(ce, lc_parent_name, Z_STR_P(lcname));
if (ce) {
return ce;
}
/* Reload bucket pointer, the hash table may have been reallocated */
zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
return NULL;
}
ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */
{
zend_class_entry *ce;
@@ -1131,26 +1157,7 @@ ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name) /*
}
/* Register the derived class */
ce = (zend_class_entry*)Z_PTR_P(zv);
zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
if (UNEXPECTED(!zv)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
return FAILURE;
}
if (ce->ce_flags & ZEND_ACC_LINKED) {
return SUCCESS;
}
ce = zend_do_link_class(ce, lc_parent_name, Z_STR_P(lcname));
if (!ce) {
/* Reload bucket pointer, the hash table may have been reallocated */
zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(rtd_key));
return FAILURE;
}
return SUCCESS;
return zend_bind_class_in_slot(zv, lcname, lc_parent_name) ? SUCCESS : FAILURE;
}
/* }}} */

View File

@@ -797,6 +797,8 @@ bool zend_handle_encoding_declaration(zend_ast *ast);
/* parser-driven code generators */
void zend_do_free(znode *op1);
ZEND_API zend_class_entry *zend_bind_class_in_slot(
zval *class_table_slot, zval *lcname, zend_string *lc_parent_name);
ZEND_API zend_result do_bind_function(zend_function *func, zval *lcname);
ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name);
ZEND_API uint32_t zend_build_delayed_early_binding_list(const zend_op_array *op_array);

View File

@@ -7582,27 +7582,16 @@ ZEND_VM_HANDLER(144, ZEND_DECLARE_CLASS, CONST, ANY)
ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST)
{
USE_OPLINE
zval *lcname, *zv;
zend_class_entry *ce;
ce = CACHED_PTR(opline->extended_value);
zend_class_entry *ce = CACHED_PTR(opline->extended_value);
if (ce == NULL) {
lcname = RT_CONSTANT(opline, opline->op1);
zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1));
zval *lcname = RT_CONSTANT(opline, opline->op1);
zval *zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1));
if (zv) {
SAVE_OPLINE();
ce = Z_CE_P(zv);
zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
if (UNEXPECTED(!zv)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
} else {
ce = zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(lcname));
if (!ce) {
/* Reload bucket pointer, the hash table may have been reallocated */
zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
HANDLE_EXCEPTION();
}
ce = zend_bind_class_in_slot(zv, lcname, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
if (!ce) {
HANDLE_EXCEPTION();
}
}
CACHE_PTR(opline->extended_value, ce);

View File

@@ -7355,27 +7355,16 @@ array_key_exists_array:
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *lcname, *zv;
zend_class_entry *ce;
ce = CACHED_PTR(opline->extended_value);
zend_class_entry *ce = CACHED_PTR(opline->extended_value);
if (ce == NULL) {
lcname = RT_CONSTANT(opline, opline->op1);
zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1));
zval *lcname = RT_CONSTANT(opline, opline->op1);
zval *zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1));
if (zv) {
SAVE_OPLINE();
ce = Z_CE_P(zv);
zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
if (UNEXPECTED(!zv)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
} else {
ce = zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(lcname));
if (!ce) {
/* Reload bucket pointer, the hash table may have been reallocated */
zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
HANDLE_EXCEPTION();
}
ce = zend_bind_class_in_slot(zv, lcname, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
if (!ce) {
HANDLE_EXCEPTION();
}
}
CACHE_PTR(opline->extended_value, ce);