Skip to content

Commit 9332d08

Browse files
committed
Zend: add object_init_instantiable_class() API
To remove the need to check (and throw an exception) if a class is instantiable if we know it is.
1 parent 72244e6 commit 9332d08

2 files changed

Lines changed: 32 additions & 18 deletions

File tree

Zend/zend_API.c

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1785,26 +1785,34 @@ ZEND_API void object_properties_load(zend_object *object, const HashTable *prope
17851785
}
17861786
/* }}} */
17871787

1788+
static ZEND_COLD zend_never_inline void zend_cannot_instantiate_class(zend_class_entry *class_type) {
1789+
if (class_type->ce_flags & ZEND_ACC_INTERFACE) {
1790+
zend_throw_error(NULL, "Cannot instantiate interface %s", ZSTR_VAL(class_type->name));
1791+
} else if (class_type->ce_flags & ZEND_ACC_TRAIT) {
1792+
zend_throw_error(NULL, "Cannot instantiate trait %s", ZSTR_VAL(class_type->name));
1793+
} else if (class_type->ce_flags & ZEND_ACC_ENUM) {
1794+
zend_throw_error(NULL, "Cannot instantiate enum %s", ZSTR_VAL(class_type->name));
1795+
} else {
1796+
ZEND_ASSERT(class_type->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS));
1797+
zend_throw_error(NULL, "Cannot instantiate abstract class %s", ZSTR_VAL(class_type->name));
1798+
}
1799+
}
1800+
17881801
/* This function requires 'properties' to contain all props declared in the
17891802
* class and all props being public. If only a subset is given or the class
17901803
* has protected members then you need to merge the properties separately by
17911804
* calling zend_merge_properties(). */
1792-
static zend_always_inline zend_result _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
1793-
{
1794-
if (UNEXPECTED(class_type->ce_flags & ZEND_ACC_UNINSTANTIABLE)) {
1795-
if (class_type->ce_flags & ZEND_ACC_INTERFACE) {
1796-
zend_throw_error(NULL, "Cannot instantiate interface %s", ZSTR_VAL(class_type->name));
1797-
} else if (class_type->ce_flags & ZEND_ACC_TRAIT) {
1798-
zend_throw_error(NULL, "Cannot instantiate trait %s", ZSTR_VAL(class_type->name));
1799-
} else if (class_type->ce_flags & ZEND_ACC_ENUM) {
1800-
zend_throw_error(NULL, "Cannot instantiate enum %s", ZSTR_VAL(class_type->name));
1801-
} else {
1802-
ZEND_ASSERT(class_type->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS));
1803-
zend_throw_error(NULL, "Cannot instantiate abstract class %s", ZSTR_VAL(class_type->name));
1805+
static zend_always_inline zend_result _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties, bool known_instantiable) /* {{{ */
1806+
{
1807+
if (!known_instantiable) {
1808+
if (UNEXPECTED(class_type->ce_flags & ZEND_ACC_UNINSTANTIABLE)) {
1809+
zend_cannot_instantiate_class(class_type);
1810+
ZVAL_NULL(arg);
1811+
Z_OBJ_P(arg) = NULL;
1812+
return FAILURE;
18041813
}
1805-
ZVAL_NULL(arg);
1806-
Z_OBJ_P(arg) = NULL;
1807-
return FAILURE;
1814+
} else {
1815+
ZEND_ASSERT((class_type->ce_flags & ZEND_ACC_UNINSTANTIABLE) == 0);
18081816
}
18091817

18101818
if (UNEXPECTED(!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
@@ -1833,19 +1841,24 @@ static zend_always_inline zend_result _object_and_properties_init(zval *arg, zen
18331841

18341842
ZEND_API zend_result object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
18351843
{
1836-
return _object_and_properties_init(arg, class_type, properties);
1844+
return _object_and_properties_init(arg, class_type, properties, false);
18371845
}
18381846
/* }}} */
18391847

18401848
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type) /* {{{ */
18411849
{
1842-
return _object_and_properties_init(arg, class_type, NULL);
1850+
return _object_and_properties_init(arg, class_type, NULL, false);
18431851
}
18441852
/* }}} */
18451853

1854+
ZEND_API zend_result object_init_instantiable_class(zval *arg, zend_class_entry *class_type) /* {{{ */
1855+
{
1856+
return _object_and_properties_init(arg, class_type, NULL, true);
1857+
}
1858+
18461859
ZEND_API zend_result object_init_with_constructor(zval *arg, zend_class_entry *class_type, uint32_t param_count, zval *params, HashTable *named_params) /* {{{ */
18471860
{
1848-
zend_result status = _object_and_properties_init(arg, class_type, NULL);
1861+
zend_result status = _object_and_properties_init(arg, class_type, NULL, false);
18491862
if (UNEXPECTED(status == FAILURE)) {
18501863
ZVAL_UNDEF(arg);
18511864
return FAILURE;

Zend/zend_API.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ static zend_always_inline void array_init(zval *arg)
544544

545545
ZEND_API void object_init(zval *arg);
546546
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *ce);
547+
ZEND_API zend_result object_init_instantiable_class(zval *arg, zend_class_entry *class_type);
547548
ZEND_API zend_result object_init_with_constructor(zval *arg, zend_class_entry *class_type, uint32_t param_count, zval *params, HashTable *named_params);
548549
ZEND_API zend_result object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties);
549550
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type);

0 commit comments

Comments
 (0)