mirror of
https://github.com/php/php-src.git
synced 2024-11-23 09:54:15 +08:00
Classify object handlers are required/optional
This commit is contained in:
parent
fc0aa264c1
commit
1cfbb21790
@ -7,6 +7,7 @@ PHP 7.4 INTERNALS UPGRADE NOTES
|
||||
d. Removed zend_check_private()
|
||||
e. php_win32_error_to_msg() memory management
|
||||
f. get_properties_for() handler / Z_OBJDEBUG_P
|
||||
g. Required object handlers
|
||||
|
||||
2. Build system changes
|
||||
a. Abstract
|
||||
@ -98,6 +99,28 @@ PHP 7.4 INTERNALS UPGRADE NOTES
|
||||
// ...
|
||||
zend_release_properties(ht);
|
||||
|
||||
g. The following object handlers are now required (must be non-NULL):
|
||||
|
||||
* free_obj
|
||||
* dtor_obj
|
||||
* read_property
|
||||
* write_property
|
||||
* read_dimension
|
||||
* write_dimension
|
||||
* get_property_ptr_ptr
|
||||
* has_property
|
||||
* unset_property
|
||||
* has_dimension
|
||||
* unset_dimension
|
||||
* get_properties
|
||||
* get_method
|
||||
* get_constructor
|
||||
* get_class_name
|
||||
* get_gc
|
||||
|
||||
It is recommended to initialize object handler structures by copying the
|
||||
std object handlers and only overwriting those you want to change.
|
||||
|
||||
========================
|
||||
2. Build system changes
|
||||
========================
|
||||
|
@ -3114,7 +3114,7 @@ get_function_via_handler:
|
||||
fcc->function_handler = zend_get_call_trampoline_func(ce_org, mname, 0);
|
||||
call_via_handler = 1;
|
||||
retval = 1;
|
||||
} else if (fcc->object->handlers->get_method) {
|
||||
} else {
|
||||
fcc->function_handler = fcc->object->handlers->get_method(&fcc->object, mname, NULL);
|
||||
if (fcc->function_handler) {
|
||||
if (strict_class &&
|
||||
@ -3935,9 +3935,6 @@ ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zen
|
||||
|
||||
EG(fake_scope) = scope;
|
||||
|
||||
if (!Z_OBJ_HT_P(object)->write_property) {
|
||||
zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be updated", ZSTR_VAL(name), ZSTR_VAL(Z_OBJCE_P(object)->name));
|
||||
}
|
||||
ZVAL_STR(&property, name);
|
||||
Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL);
|
||||
|
||||
@ -3952,9 +3949,6 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const
|
||||
|
||||
EG(fake_scope) = scope;
|
||||
|
||||
if (!Z_OBJ_HT_P(object)->write_property) {
|
||||
zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, ZSTR_VAL(Z_OBJCE_P(object)->name));
|
||||
}
|
||||
ZVAL_STRINGL(&property, name, name_length);
|
||||
Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL);
|
||||
zval_ptr_dtor(&property);
|
||||
@ -3979,9 +3973,6 @@ ZEND_API void zend_unset_property(zend_class_entry *scope, zval *object, const c
|
||||
|
||||
EG(fake_scope) = scope;
|
||||
|
||||
if (!Z_OBJ_HT_P(object)->unset_property) {
|
||||
zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be unset", name, ZSTR_VAL(Z_OBJCE_P(object)->name));
|
||||
}
|
||||
ZVAL_STRINGL(&property, name, name_length);
|
||||
Z_OBJ_HT_P(object)->unset_property(object, &property, 0);
|
||||
zval_ptr_dtor(&property);
|
||||
@ -4143,10 +4134,6 @@ ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zval *object, zend
|
||||
|
||||
EG(fake_scope) = scope;
|
||||
|
||||
if (!Z_OBJ_HT_P(object)->read_property) {
|
||||
zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be read", ZSTR_VAL(name), ZSTR_VAL(Z_OBJCE_P(object)->name));
|
||||
}
|
||||
|
||||
ZVAL_STR(&property, name);
|
||||
value = Z_OBJ_HT_P(object)->read_property(object, &property, silent?BP_VAR_IS:BP_VAR_R, NULL, rv);
|
||||
|
||||
|
@ -1338,7 +1338,7 @@ ZEND_FUNCTION(method_exists)
|
||||
if (zend_hash_exists(&ce->function_table, lcname)) {
|
||||
zend_string_release_ex(lcname, 0);
|
||||
RETURN_TRUE;
|
||||
} else if (Z_TYPE_P(klass) == IS_OBJECT && Z_OBJ_HT_P(klass)->get_method != NULL) {
|
||||
} else if (Z_TYPE_P(klass) == IS_OBJECT) {
|
||||
zend_object *obj = Z_OBJ_P(klass);
|
||||
zend_function *func = Z_OBJ_HT_P(klass)->get_method(&obj, method_name, NULL);
|
||||
if (func != NULL) {
|
||||
@ -1401,7 +1401,6 @@ ZEND_FUNCTION(property_exists)
|
||||
ZVAL_STR(&property_z, property);
|
||||
|
||||
if (Z_TYPE_P(object) == IS_OBJECT &&
|
||||
Z_OBJ_HANDLER_P(object, has_property) &&
|
||||
Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2, NULL)) {
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
@ -625,17 +625,6 @@ static zend_never_inline ZEND_COLD int zend_wrong_assign_to_variable_reference(z
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_property_assignment(zval *property OPLINE_DC EXECUTE_DATA_DC)
|
||||
{
|
||||
zend_string *tmp_property_name;
|
||||
zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
|
||||
zend_error(E_WARNING, "Attempt to assign property '%s' of non-object", ZSTR_VAL(property_name));
|
||||
zend_tmp_string_release(tmp_property_name);
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
}
|
||||
|
||||
/* this should modify object only if it's empty */
|
||||
static zend_never_inline ZEND_COLD int ZEND_FASTCALL make_real_object(zval *object, zval *property OPLINE_DC EXECUTE_DATA_DC)
|
||||
{
|
||||
@ -1112,14 +1101,6 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_offset(void)
|
||||
|
||||
static zend_never_inline void zend_assign_to_object_dim(zval *object, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC)
|
||||
{
|
||||
if (UNEXPECTED(!Z_OBJ_HT_P(object)->write_dimension)) {
|
||||
zend_use_object_as_array();
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Z_OBJ_HT_P(object)->write_dimension(object, dim, value);
|
||||
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
@ -1132,8 +1113,7 @@ static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *
|
||||
zval *z;
|
||||
zval rv, res;
|
||||
|
||||
if (Z_OBJ_HT_P(object)->read_dimension &&
|
||||
(z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv)) != NULL) {
|
||||
if ((z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv)) != NULL) {
|
||||
|
||||
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
|
||||
zval rv2;
|
||||
@ -1335,22 +1315,6 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_property_read(z
|
||||
zend_tmp_string_release(tmp_property_name);
|
||||
}
|
||||
|
||||
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_property_unset(zval *property)
|
||||
{
|
||||
zend_string *tmp_property_name;
|
||||
zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
|
||||
zend_error(E_NOTICE, "Trying to unset property '%s' of non-object", ZSTR_VAL(property_name));
|
||||
zend_tmp_string_release(tmp_property_name);
|
||||
}
|
||||
|
||||
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_property_check(zval *property)
|
||||
{
|
||||
zend_string *tmp_property_name;
|
||||
zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
|
||||
zend_error(E_NOTICE, "Trying to check property '%s' of non-object", ZSTR_VAL(property_name));
|
||||
zend_tmp_string_release(tmp_property_name);
|
||||
}
|
||||
|
||||
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_function *fbc)
|
||||
{
|
||||
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
|
||||
@ -1425,93 +1389,80 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
|
||||
|
||||
static zend_never_inline void zend_post_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc OPLINE_DC EXECUTE_DATA_DC)
|
||||
{
|
||||
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
||||
zval rv, obj;
|
||||
zval *z;
|
||||
zval z_copy;
|
||||
zval rv, obj;
|
||||
zval *z;
|
||||
zval z_copy;
|
||||
|
||||
ZVAL_OBJ(&obj, Z_OBJ_P(object));
|
||||
Z_ADDREF(obj);
|
||||
z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
OBJ_RELEASE(Z_OBJ(obj));
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
return;
|
||||
}
|
||||
|
||||
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
||||
zval rv2;
|
||||
zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
|
||||
if (z == &rv) {
|
||||
zval_ptr_dtor(&rv);
|
||||
}
|
||||
ZVAL_COPY_VALUE(z, value);
|
||||
}
|
||||
|
||||
ZVAL_COPY_DEREF(&z_copy, z);
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), &z_copy);
|
||||
if (inc) {
|
||||
increment_function(&z_copy);
|
||||
} else {
|
||||
decrement_function(&z_copy);
|
||||
}
|
||||
Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot);
|
||||
ZVAL_OBJ(&obj, Z_OBJ_P(object));
|
||||
Z_ADDREF(obj);
|
||||
z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
OBJ_RELEASE(Z_OBJ(obj));
|
||||
zval_ptr_dtor(&z_copy);
|
||||
zval_ptr_dtor(z);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
return;
|
||||
}
|
||||
|
||||
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
||||
zval rv2;
|
||||
zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
|
||||
if (z == &rv) {
|
||||
zval_ptr_dtor(&rv);
|
||||
}
|
||||
ZVAL_COPY_VALUE(z, value);
|
||||
}
|
||||
|
||||
ZVAL_COPY_DEREF(&z_copy, z);
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), &z_copy);
|
||||
if (inc) {
|
||||
increment_function(&z_copy);
|
||||
} else {
|
||||
decrement_function(&z_copy);
|
||||
}
|
||||
Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot);
|
||||
OBJ_RELEASE(Z_OBJ(obj));
|
||||
zval_ptr_dtor(&z_copy);
|
||||
zval_ptr_dtor(z);
|
||||
}
|
||||
|
||||
static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc OPLINE_DC EXECUTE_DATA_DC)
|
||||
{
|
||||
zval rv;
|
||||
zval *z, obj;
|
||||
zval z_copy;
|
||||
|
||||
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
||||
zval *z, obj;
|
||||
zval z_copy;
|
||||
|
||||
ZVAL_OBJ(&obj, Z_OBJ_P(object));
|
||||
Z_ADDREF(obj);
|
||||
z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
OBJ_RELEASE(Z_OBJ(obj));
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
||||
zval rv2;
|
||||
zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
|
||||
|
||||
if (z == &rv) {
|
||||
zval_ptr_dtor(&rv);
|
||||
}
|
||||
ZVAL_COPY_VALUE(z, value);
|
||||
}
|
||||
ZVAL_COPY_DEREF(&z_copy, z);
|
||||
if (inc) {
|
||||
increment_function(&z_copy);
|
||||
} else {
|
||||
decrement_function(&z_copy);
|
||||
}
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), &z_copy);
|
||||
}
|
||||
Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot);
|
||||
ZVAL_OBJ(&obj, Z_OBJ_P(object));
|
||||
Z_ADDREF(obj);
|
||||
z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
OBJ_RELEASE(Z_OBJ(obj));
|
||||
zval_ptr_dtor(&z_copy);
|
||||
zval_ptr_dtor(z);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
||||
zval rv2;
|
||||
zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
|
||||
|
||||
if (z == &rv) {
|
||||
zval_ptr_dtor(&rv);
|
||||
}
|
||||
ZVAL_COPY_VALUE(z, value);
|
||||
}
|
||||
ZVAL_COPY_DEREF(&z_copy, z);
|
||||
if (inc) {
|
||||
increment_function(&z_copy);
|
||||
} else {
|
||||
decrement_function(&z_copy);
|
||||
}
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), &z_copy);
|
||||
}
|
||||
Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot);
|
||||
OBJ_RELEASE(Z_OBJ(obj));
|
||||
zval_ptr_dtor(&z_copy);
|
||||
zval_ptr_dtor(z);
|
||||
}
|
||||
|
||||
static zend_never_inline void zend_assign_op_overloaded_property(zval *object, zval *property, void **cache_slot, zval *value, binary_op_type binary_op OPLINE_DC EXECUTE_DATA_DC)
|
||||
@ -1521,38 +1472,31 @@ static zend_never_inline void zend_assign_op_overloaded_property(zval *object, z
|
||||
|
||||
ZVAL_OBJ(&obj, Z_OBJ_P(object));
|
||||
Z_ADDREF(obj);
|
||||
if (EXPECTED(Z_OBJ_HT(obj)->read_property)) {
|
||||
z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
OBJ_RELEASE(Z_OBJ(obj));
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
|
||||
zval rv2;
|
||||
zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
|
||||
|
||||
if (z == &rv) {
|
||||
zval_ptr_dtor(&rv);
|
||||
}
|
||||
ZVAL_COPY_VALUE(z, value);
|
||||
}
|
||||
if (binary_op(&res, z, value) == SUCCESS) {
|
||||
Z_OBJ_HT(obj)->write_property(&obj, property, &res, cache_slot);
|
||||
}
|
||||
z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
OBJ_RELEASE(Z_OBJ(obj));
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), &res);
|
||||
}
|
||||
zval_ptr_dtor(z);
|
||||
zval_ptr_dtor(&res);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
|
||||
zval rv2;
|
||||
zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
|
||||
|
||||
if (z == &rv) {
|
||||
zval_ptr_dtor(&rv);
|
||||
}
|
||||
ZVAL_COPY_VALUE(z, value);
|
||||
}
|
||||
if (binary_op(&res, z, value) == SUCCESS) {
|
||||
Z_OBJ_HT(obj)->write_property(&obj, property, &res, cache_slot);
|
||||
}
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), &res);
|
||||
}
|
||||
zval_ptr_dtor(z);
|
||||
zval_ptr_dtor(&res);
|
||||
OBJ_RELEASE(Z_OBJ(obj));
|
||||
}
|
||||
|
||||
@ -1660,16 +1604,6 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_new_element_for_s
|
||||
zend_throw_error(NULL, "[] operator not supported for strings");
|
||||
}
|
||||
|
||||
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_access_undefined_propery_in_overloaded_object(void)
|
||||
{
|
||||
zend_throw_error(NULL, "Cannot access undefined property for object with overloaded property access");
|
||||
}
|
||||
|
||||
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_unsupported_property_reference(void)
|
||||
{
|
||||
zend_error(E_WARNING, "This object doesn't support property references");
|
||||
}
|
||||
|
||||
static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type EXECUTE_DATA_DC)
|
||||
{
|
||||
zval *retval = NULL;
|
||||
@ -1844,39 +1778,34 @@ fetch_from_array:
|
||||
zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
|
||||
dim = &EG(uninitialized_zval);
|
||||
}
|
||||
if (!Z_OBJ_HT_P(container)->read_dimension) {
|
||||
zend_use_object_as_array();
|
||||
ZVAL_ERROR(result);
|
||||
} else {
|
||||
if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
|
||||
dim++;
|
||||
}
|
||||
retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
|
||||
if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
|
||||
dim++;
|
||||
}
|
||||
retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
|
||||
|
||||
if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
|
||||
zend_class_entry *ce = Z_OBJCE_P(container);
|
||||
if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
|
||||
zend_class_entry *ce = Z_OBJCE_P(container);
|
||||
|
||||
ZVAL_NULL(result);
|
||||
zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
|
||||
} else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
|
||||
if (!Z_ISREF_P(retval)) {
|
||||
if (result != retval) {
|
||||
ZVAL_COPY(result, retval);
|
||||
retval = result;
|
||||
}
|
||||
if (Z_TYPE_P(retval) != IS_OBJECT) {
|
||||
zend_class_entry *ce = Z_OBJCE_P(container);
|
||||
zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
|
||||
}
|
||||
} else if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) {
|
||||
ZVAL_UNREF(retval);
|
||||
}
|
||||
ZVAL_NULL(result);
|
||||
zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
|
||||
} else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
|
||||
if (!Z_ISREF_P(retval)) {
|
||||
if (result != retval) {
|
||||
ZVAL_INDIRECT(result, retval);
|
||||
ZVAL_COPY(result, retval);
|
||||
retval = result;
|
||||
}
|
||||
} else {
|
||||
ZVAL_ERROR(result);
|
||||
if (Z_TYPE_P(retval) != IS_OBJECT) {
|
||||
zend_class_entry *ce = Z_OBJCE_P(container);
|
||||
zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
|
||||
}
|
||||
} else if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) {
|
||||
ZVAL_UNREF(retval);
|
||||
}
|
||||
if (result != retval) {
|
||||
ZVAL_INDIRECT(result, retval);
|
||||
}
|
||||
} else {
|
||||
ZVAL_ERROR(result);
|
||||
}
|
||||
} else {
|
||||
if (type != BP_VAR_W && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
|
||||
@ -2004,25 +1933,20 @@ try_string_offset:
|
||||
zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
|
||||
dim = &EG(uninitialized_zval);
|
||||
}
|
||||
if (!Z_OBJ_HT_P(container)->read_dimension) {
|
||||
zend_use_object_as_array();
|
||||
ZVAL_NULL(result);
|
||||
} else {
|
||||
if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
|
||||
dim++;
|
||||
}
|
||||
retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
|
||||
if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
|
||||
dim++;
|
||||
}
|
||||
retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
|
||||
|
||||
ZEND_ASSERT(result != NULL);
|
||||
if (retval) {
|
||||
if (result != retval) {
|
||||
ZVAL_COPY_DEREF(result, retval);
|
||||
} else if (UNEXPECTED(Z_ISREF_P(retval))) {
|
||||
zend_unwrap_reference(result);
|
||||
}
|
||||
} else {
|
||||
ZVAL_NULL(result);
|
||||
ZEND_ASSERT(result != NULL);
|
||||
if (retval) {
|
||||
if (result != retval) {
|
||||
ZVAL_COPY_DEREF(result, retval);
|
||||
} else if (UNEXPECTED(Z_ISREF_P(retval))) {
|
||||
zend_unwrap_reference(result);
|
||||
}
|
||||
} else {
|
||||
ZVAL_NULL(result);
|
||||
}
|
||||
} else {
|
||||
if (type != BP_VAR_IS && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
|
||||
@ -2101,12 +2025,7 @@ static zend_never_inline int ZEND_FASTCALL zend_isset_dim_slow(zval *container,
|
||||
}
|
||||
|
||||
if (/*OP1_TYPE != IS_CONST &&*/ EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
||||
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
||||
return Z_OBJ_HT_P(container)->has_dimension(container, offset, 0);
|
||||
} else {
|
||||
zend_use_object_as_array();
|
||||
return 0;
|
||||
}
|
||||
return Z_OBJ_HT_P(container)->has_dimension(container, offset, 0);
|
||||
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
||||
zend_long lval;
|
||||
|
||||
@ -2146,12 +2065,7 @@ static zend_never_inline int ZEND_FASTCALL zend_isempty_dim_slow(zval *container
|
||||
}
|
||||
|
||||
if (/*OP1_TYPE != IS_CONST &&*/ EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
||||
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
||||
return !Z_OBJ_HT_P(container)->has_dimension(container, offset, 1);
|
||||
} else {
|
||||
zend_use_object_as_array();
|
||||
return 1;
|
||||
}
|
||||
return !Z_OBJ_HT_P(container)->has_dimension(container, offset, 1);
|
||||
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
||||
zend_long lval;
|
||||
|
||||
@ -2185,6 +2099,7 @@ str_offset:
|
||||
|
||||
static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type OPLINE_DC)
|
||||
{
|
||||
zval *ptr;
|
||||
if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
||||
do {
|
||||
if (Z_ISREF_P(container)) {
|
||||
@ -2228,29 +2143,17 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
|
||||
}
|
||||
}
|
||||
}
|
||||
if (EXPECTED(Z_OBJ_HT_P(container)->get_property_ptr_ptr)) {
|
||||
zval *ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot);
|
||||
if (NULL == ptr) {
|
||||
if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
|
||||
use_read_property:
|
||||
ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result);
|
||||
if (ptr != result) {
|
||||
ZVAL_INDIRECT(result, ptr);
|
||||
} else if (UNEXPECTED(Z_ISREF_P(ptr) && Z_REFCOUNT_P(ptr) == 1)) {
|
||||
ZVAL_UNREF(ptr);
|
||||
}
|
||||
} else {
|
||||
zend_access_undefined_propery_in_overloaded_object();
|
||||
ZVAL_ERROR(result);
|
||||
}
|
||||
} else {
|
||||
|
||||
ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot);
|
||||
if (NULL == ptr) {
|
||||
ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result);
|
||||
if (ptr != result) {
|
||||
ZVAL_INDIRECT(result, ptr);
|
||||
} else if (UNEXPECTED(Z_ISREF_P(ptr) && Z_REFCOUNT_P(ptr) == 1)) {
|
||||
ZVAL_UNREF(ptr);
|
||||
}
|
||||
} else if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
|
||||
goto use_read_property;
|
||||
} else {
|
||||
zend_unsupported_property_reference();
|
||||
ZVAL_ERROR(result);
|
||||
ZVAL_INDIRECT(result, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -617,17 +617,15 @@ tail_call:
|
||||
GC_REF_SET_BLACK(ref);
|
||||
|
||||
if (GC_TYPE(ref) == IS_OBJECT) {
|
||||
zend_object_get_gc_t get_gc;
|
||||
zend_object *obj = (zend_object*)ref;
|
||||
|
||||
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED) &&
|
||||
(get_gc = obj->handlers->get_gc) != NULL)) {
|
||||
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) {
|
||||
int n;
|
||||
zval *zv, *end;
|
||||
zval tmp;
|
||||
|
||||
ZVAL_OBJ(&tmp, obj);
|
||||
ht = get_gc(&tmp, &zv, &n);
|
||||
ht = obj->handlers->get_gc(&tmp, &zv, &n);
|
||||
end = zv + n;
|
||||
if (EXPECTED(!ht)) {
|
||||
if (!n) return;
|
||||
@ -727,17 +725,15 @@ tail_call:
|
||||
GC_REF_SET_COLOR(ref, GC_GREY);
|
||||
|
||||
if (GC_TYPE(ref) == IS_OBJECT) {
|
||||
zend_object_get_gc_t get_gc;
|
||||
zend_object *obj = (zend_object*)ref;
|
||||
|
||||
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED) &&
|
||||
(get_gc = obj->handlers->get_gc) != NULL)) {
|
||||
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) {
|
||||
int n;
|
||||
zval *zv, *end;
|
||||
zval tmp;
|
||||
|
||||
ZVAL_OBJ(&tmp, obj);
|
||||
ht = get_gc(&tmp, &zv, &n);
|
||||
ht = obj->handlers->get_gc(&tmp, &zv, &n);
|
||||
end = zv + n;
|
||||
if (EXPECTED(!ht)) {
|
||||
if (!n) return;
|
||||
@ -883,17 +879,15 @@ tail_call:
|
||||
} else {
|
||||
GC_REF_SET_COLOR(ref, GC_WHITE);
|
||||
if (GC_TYPE(ref) == IS_OBJECT) {
|
||||
zend_object_get_gc_t get_gc;
|
||||
zend_object *obj = (zend_object*)ref;
|
||||
|
||||
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED) &&
|
||||
(get_gc = obj->handlers->get_gc) != NULL)) {
|
||||
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) {
|
||||
int n;
|
||||
zval *zv, *end;
|
||||
zval tmp;
|
||||
|
||||
ZVAL_OBJ(&tmp, obj);
|
||||
ht = get_gc(&tmp, &zv, &n);
|
||||
ht = obj->handlers->get_gc(&tmp, &zv, &n);
|
||||
end = zv + n;
|
||||
if (EXPECTED(!ht)) {
|
||||
if (!n) return;
|
||||
@ -1023,11 +1017,9 @@ tail_call:
|
||||
}
|
||||
|
||||
if (GC_TYPE(ref) == IS_OBJECT) {
|
||||
zend_object_get_gc_t get_gc;
|
||||
zend_object *obj = (zend_object*)ref;
|
||||
|
||||
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED) &&
|
||||
(get_gc = obj->handlers->get_gc) != NULL)) {
|
||||
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) {
|
||||
int n;
|
||||
zval *zv, *end;
|
||||
zval tmp;
|
||||
@ -1036,13 +1028,12 @@ tail_call:
|
||||
if (!GC_INFO(ref)) {
|
||||
gc_add_garbage(ref);
|
||||
}
|
||||
if (obj->handlers->dtor_obj &&
|
||||
((obj->handlers->dtor_obj != zend_objects_destroy_object) ||
|
||||
(obj->ce->destructor != NULL))) {
|
||||
if (obj->handlers->dtor_obj != zend_objects_destroy_object ||
|
||||
obj->ce->destructor != NULL) {
|
||||
*flags |= GC_HAS_DESTRUCTORS;
|
||||
}
|
||||
ZVAL_OBJ(&tmp, obj);
|
||||
ht = get_gc(&tmp, &zv, &n);
|
||||
ht = obj->handlers->get_gc(&tmp, &zv, &n);
|
||||
end = zv + n;
|
||||
if (EXPECTED(!ht)) {
|
||||
if (!n) return count;
|
||||
@ -1193,17 +1184,15 @@ tail_call:
|
||||
}
|
||||
|
||||
if (GC_TYPE(ref) == IS_OBJECT) {
|
||||
zend_object_get_gc_t get_gc;
|
||||
zend_object *obj = (zend_object*)ref;
|
||||
|
||||
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED) &&
|
||||
(get_gc = obj->handlers->get_gc) != NULL)) {
|
||||
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) {
|
||||
int n;
|
||||
zval *zv, *end;
|
||||
zval tmp;
|
||||
|
||||
ZVAL_OBJ(&tmp, obj);
|
||||
ht = get_gc(&tmp, &zv, &n);
|
||||
ht = obj->handlers->get_gc(&tmp, &zv, &n);
|
||||
end = zv + n;
|
||||
if (EXPECTED(!ht)) {
|
||||
if (!n) return;
|
||||
@ -1341,9 +1330,8 @@ ZEND_API int zend_gc_collect_cycles(void)
|
||||
|
||||
GC_TRACE_REF(obj, "calling destructor");
|
||||
GC_ADD_FLAGS(obj, IS_OBJ_DESTRUCTOR_CALLED);
|
||||
if (obj->handlers->dtor_obj
|
||||
&& (obj->handlers->dtor_obj != zend_objects_destroy_object
|
||||
|| obj->ce->destructor)) {
|
||||
if (obj->handlers->dtor_obj != zend_objects_destroy_object
|
||||
|| obj->ce->destructor) {
|
||||
GC_ADDREF(obj);
|
||||
obj->handlers->dtor_obj(obj);
|
||||
GC_DELREF(obj);
|
||||
@ -1392,11 +1380,9 @@ ZEND_API int zend_gc_collect_cycles(void)
|
||||
(GC_TYPE_INFO(obj) & ~GC_TYPE_MASK);
|
||||
if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
|
||||
GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED);
|
||||
if (obj->handlers->free_obj) {
|
||||
GC_ADDREF(obj);
|
||||
obj->handlers->free_obj(obj);
|
||||
GC_DELREF(obj);
|
||||
}
|
||||
GC_ADDREF(obj);
|
||||
obj->handlers->free_obj(obj);
|
||||
GC_DELREF(obj);
|
||||
}
|
||||
|
||||
ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(obj->handle);
|
||||
|
@ -153,36 +153,35 @@ typedef int (*zend_object_do_operation_t)(zend_uchar opcode, zval *result, zval
|
||||
struct _zend_object_handlers {
|
||||
/* offset of real object header (usually zero) */
|
||||
int offset;
|
||||
/* general object functions */
|
||||
zend_object_free_obj_t free_obj;
|
||||
zend_object_dtor_obj_t dtor_obj;
|
||||
zend_object_clone_obj_t clone_obj;
|
||||
/* individual object functions */
|
||||
zend_object_read_property_t read_property;
|
||||
zend_object_write_property_t write_property;
|
||||
zend_object_read_dimension_t read_dimension;
|
||||
zend_object_write_dimension_t write_dimension;
|
||||
zend_object_get_property_ptr_ptr_t get_property_ptr_ptr;
|
||||
zend_object_get_t get;
|
||||
zend_object_set_t set;
|
||||
zend_object_has_property_t has_property;
|
||||
zend_object_unset_property_t unset_property;
|
||||
zend_object_has_dimension_t has_dimension;
|
||||
zend_object_unset_dimension_t unset_dimension;
|
||||
zend_object_get_properties_t get_properties; /* required */
|
||||
zend_object_get_method_t get_method;
|
||||
zend_object_call_method_t call_method;
|
||||
zend_object_get_constructor_t get_constructor;
|
||||
zend_object_get_class_name_t get_class_name;
|
||||
zend_object_compare_t compare_objects;
|
||||
zend_object_cast_t cast_object;
|
||||
zend_object_count_elements_t count_elements;
|
||||
zend_object_get_debug_info_t get_debug_info;
|
||||
zend_object_get_closure_t get_closure;
|
||||
zend_object_get_gc_t get_gc;
|
||||
zend_object_do_operation_t do_operation;
|
||||
zend_object_compare_zvals_t compare;
|
||||
zend_object_get_properties_for_t get_properties_for; /* optional */
|
||||
/* object handlers */
|
||||
zend_object_free_obj_t free_obj; /* required */
|
||||
zend_object_dtor_obj_t dtor_obj; /* required */
|
||||
zend_object_clone_obj_t clone_obj; /* optional */
|
||||
zend_object_read_property_t read_property; /* required */
|
||||
zend_object_write_property_t write_property; /* required */
|
||||
zend_object_read_dimension_t read_dimension; /* required */
|
||||
zend_object_write_dimension_t write_dimension; /* required */
|
||||
zend_object_get_property_ptr_ptr_t get_property_ptr_ptr; /* required */
|
||||
zend_object_get_t get; /* optional */
|
||||
zend_object_set_t set; /* optional */
|
||||
zend_object_has_property_t has_property; /* required */
|
||||
zend_object_unset_property_t unset_property; /* required */
|
||||
zend_object_has_dimension_t has_dimension; /* required */
|
||||
zend_object_unset_dimension_t unset_dimension; /* required */
|
||||
zend_object_get_properties_t get_properties; /* required */
|
||||
zend_object_get_method_t get_method; /* required */
|
||||
zend_object_call_method_t call_method; /* optional */
|
||||
zend_object_get_constructor_t get_constructor; /* required */
|
||||
zend_object_get_class_name_t get_class_name; /* required */
|
||||
zend_object_compare_t compare_objects; /* optional */
|
||||
zend_object_cast_t cast_object; /* optional */
|
||||
zend_object_count_elements_t count_elements; /* optional */
|
||||
zend_object_get_debug_info_t get_debug_info; /* optional */
|
||||
zend_object_get_closure_t get_closure; /* optional */
|
||||
zend_object_get_gc_t get_gc; /* required */
|
||||
zend_object_do_operation_t do_operation; /* optional */
|
||||
zend_object_compare_zvals_t compare; /* optional */
|
||||
zend_object_get_properties_for_t get_properties_for; /* optional */
|
||||
};
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
@ -49,9 +49,8 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_call_destructors(zend_objects_sto
|
||||
if (!(OBJ_FLAGS(obj) & IS_OBJ_DESTRUCTOR_CALLED)) {
|
||||
GC_ADD_FLAGS(obj, IS_OBJ_DESTRUCTOR_CALLED);
|
||||
|
||||
if (obj->handlers->dtor_obj
|
||||
&& (obj->handlers->dtor_obj != zend_objects_destroy_object
|
||||
|| obj->ce->destructor)) {
|
||||
if (obj->handlers->dtor_obj != zend_objects_destroy_object
|
||||
|| obj->ce->destructor) {
|
||||
GC_ADDREF(obj);
|
||||
obj->handlers->dtor_obj(obj);
|
||||
GC_DELREF(obj);
|
||||
@ -98,7 +97,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_free_object_storage(zend_objects_
|
||||
if (IS_OBJ_VALID(obj)) {
|
||||
if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
|
||||
GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED);
|
||||
if (obj->handlers->free_obj && obj->handlers->free_obj != zend_object_std_dtor) {
|
||||
if (obj->handlers->free_obj != zend_object_std_dtor) {
|
||||
GC_ADDREF(obj);
|
||||
obj->handlers->free_obj(obj);
|
||||
GC_DELREF(obj);
|
||||
@ -113,11 +112,9 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_free_object_storage(zend_objects_
|
||||
if (IS_OBJ_VALID(obj)) {
|
||||
if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
|
||||
GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED);
|
||||
if (obj->handlers->free_obj) {
|
||||
GC_ADDREF(obj);
|
||||
obj->handlers->free_obj(obj);
|
||||
GC_DELREF(obj);
|
||||
}
|
||||
GC_ADDREF(obj);
|
||||
obj->handlers->free_obj(obj);
|
||||
GC_DELREF(obj);
|
||||
}
|
||||
}
|
||||
} while (obj_ptr != end);
|
||||
@ -163,9 +160,8 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ *
|
||||
if (!(OBJ_FLAGS(object) & IS_OBJ_DESTRUCTOR_CALLED)) {
|
||||
GC_ADD_FLAGS(object, IS_OBJ_DESTRUCTOR_CALLED);
|
||||
|
||||
if (object->handlers->dtor_obj
|
||||
&& (object->handlers->dtor_obj != zend_objects_destroy_object
|
||||
|| object->ce->destructor)) {
|
||||
if (object->handlers->dtor_obj != zend_objects_destroy_object
|
||||
|| object->ce->destructor) {
|
||||
GC_ADDREF(object);
|
||||
object->handlers->dtor_obj(object);
|
||||
GC_DELREF(object);
|
||||
@ -179,11 +175,9 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ *
|
||||
EG(objects_store).object_buckets[handle] = SET_OBJ_INVALID(object);
|
||||
if (!(OBJ_FLAGS(object) & IS_OBJ_FREE_CALLED)) {
|
||||
GC_ADD_FLAGS(object, IS_OBJ_FREE_CALLED);
|
||||
if (object->handlers->free_obj) {
|
||||
GC_ADDREF(object);
|
||||
object->handlers->free_obj(object);
|
||||
GC_DELREF(object);
|
||||
}
|
||||
GC_ADDREF(object);
|
||||
object->handlers->free_obj(object);
|
||||
GC_DELREF(object);
|
||||
}
|
||||
ptr = ((char*)object) - object->handlers->offset;
|
||||
GC_REMOVE_FROM_BUFFER(object);
|
||||
|
@ -822,8 +822,7 @@ ZEND_VM_HELPER(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV,
|
||||
|
||||
/* here we are sure we are dealing with an object */
|
||||
ZEND_VM_C_LABEL(assign_op_object):
|
||||
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
||||
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL))) != NULL)) {
|
||||
if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL))) != NULL)) {
|
||||
if (UNEXPECTED(Z_ISERROR_P(zptr))) {
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
@ -1084,8 +1083,7 @@ ZEND_VM_HELPER(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV,
|
||||
|
||||
/* here we are sure we are dealing with an object */
|
||||
ZEND_VM_C_LABEL(pre_incdec_object):
|
||||
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
||||
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL))) != NULL)) {
|
||||
if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL))) != NULL)) {
|
||||
if (UNEXPECTED(Z_ISERROR_P(zptr))) {
|
||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
@ -1162,8 +1160,7 @@ ZEND_VM_HELPER(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV,
|
||||
|
||||
/* here we are sure we are dealing with an object */
|
||||
ZEND_VM_C_LABEL(post_incdec_object):
|
||||
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
||||
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL))) != NULL)) {
|
||||
if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL))) != NULL)) {
|
||||
if (UNEXPECTED(Z_ISERROR_P(zptr))) {
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
@ -1795,7 +1792,9 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST
|
||||
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
|
||||
GET_OP2_UNDEF_CV(offset, BP_VAR_R);
|
||||
}
|
||||
ZEND_VM_C_GOTO(fetch_obj_r_no_object);
|
||||
zend_wrong_property_read(offset);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
ZEND_VM_C_GOTO(fetch_obj_r_finish);
|
||||
} while (0);
|
||||
}
|
||||
|
||||
@ -1847,21 +1846,16 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST
|
||||
GET_OP2_UNDEF_CV(offset, BP_VAR_R);
|
||||
}
|
||||
|
||||
if (UNEXPECTED(zobj->handlers->read_property == NULL)) {
|
||||
ZEND_VM_C_LABEL(fetch_obj_r_no_object):
|
||||
zend_wrong_property_read(offset);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
|
||||
retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
|
||||
|
||||
if (retval != EX_VAR(opline->result.var)) {
|
||||
ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval);
|
||||
} else if (UNEXPECTED(Z_ISREF_P(retval))) {
|
||||
zend_unwrap_reference(retval);
|
||||
}
|
||||
if (retval != EX_VAR(opline->result.var)) {
|
||||
ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval);
|
||||
} else if (UNEXPECTED(Z_ISREF_P(retval))) {
|
||||
zend_unwrap_reference(retval);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
ZEND_VM_C_LABEL(fetch_obj_r_finish):
|
||||
FREE_OP2();
|
||||
FREE_OP1();
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@ -1939,7 +1933,8 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C
|
||||
break;
|
||||
}
|
||||
}
|
||||
ZEND_VM_C_GOTO(fetch_obj_is_no_object);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
ZEND_VM_C_GOTO(fetch_obj_is_finish);
|
||||
} while (0);
|
||||
}
|
||||
|
||||
@ -1989,19 +1984,14 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C
|
||||
}
|
||||
}
|
||||
|
||||
if (UNEXPECTED(zobj->handlers->read_property == NULL)) {
|
||||
ZEND_VM_C_LABEL(fetch_obj_is_no_object):
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var));
|
||||
|
||||
retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var));
|
||||
|
||||
if (retval != EX_VAR(opline->result.var)) {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
||||
}
|
||||
if (retval != EX_VAR(opline->result.var)) {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
ZEND_VM_C_LABEL(fetch_obj_is_finish):
|
||||
FREE_OP2();
|
||||
FREE_OP1();
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@ -2179,12 +2169,6 @@ ZEND_VM_C_LABEL(fast_assign_obj):
|
||||
}
|
||||
}
|
||||
|
||||
if (!Z_OBJ_HT_P(object)->write_property) {
|
||||
zend_wrong_property_assignment(property OPLINE_CC EXECUTE_DATA_CC);
|
||||
FREE_OP_DATA();
|
||||
ZEND_VM_C_GOTO(exit_assign_obj);
|
||||
}
|
||||
|
||||
if (OP_DATA_TYPE == IS_CV || OP_DATA_TYPE == IS_VAR) {
|
||||
ZVAL_DEREF(value);
|
||||
}
|
||||
@ -3072,13 +3056,6 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
|
||||
} else {
|
||||
zend_object *orig_obj = obj;
|
||||
|
||||
if (UNEXPECTED(obj->handlers->get_method == NULL)) {
|
||||
zend_throw_error(NULL, "Object does not support method calls");
|
||||
FREE_OP2();
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
if (OP2_TYPE == IS_CONST) {
|
||||
function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
|
||||
}
|
||||
@ -5599,14 +5576,10 @@ ZEND_VM_C_LABEL(num_index_dim):
|
||||
offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
|
||||
}
|
||||
if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
||||
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
|
||||
zend_use_object_as_array();
|
||||
} else {
|
||||
if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) {
|
||||
offset++;
|
||||
}
|
||||
Z_OBJ_HT_P(container)->unset_dimension(container, offset);
|
||||
if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) {
|
||||
offset++;
|
||||
}
|
||||
Z_OBJ_HT_P(container)->unset_dimension(container, offset);
|
||||
} else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
|
||||
zend_throw_error(NULL, "Cannot unset string offsets");
|
||||
}
|
||||
@ -5642,11 +5615,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Z_OBJ_HT_P(container)->unset_property) {
|
||||
Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL));
|
||||
} else {
|
||||
zend_wrong_property_unset(offset);
|
||||
}
|
||||
Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL));
|
||||
} while (0);
|
||||
|
||||
FREE_OP2();
|
||||
@ -6367,22 +6336,20 @@ ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED
|
||||
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
||||
container = Z_REFVAL_P(container);
|
||||
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
||||
ZEND_VM_C_GOTO(isset_no_object);
|
||||
result = (opline->extended_value & ZEND_ISEMPTY);
|
||||
ZEND_VM_C_GOTO(isset_object_finish);
|
||||
}
|
||||
} else {
|
||||
ZEND_VM_C_GOTO(isset_no_object);
|
||||
result = (opline->extended_value & ZEND_ISEMPTY);
|
||||
ZEND_VM_C_GOTO(isset_object_finish);
|
||||
}
|
||||
}
|
||||
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
||||
zend_wrong_property_check(offset);
|
||||
ZEND_VM_C_LABEL(isset_no_object):
|
||||
result = (opline->extended_value & ZEND_ISEMPTY);
|
||||
} else {
|
||||
result =
|
||||
(opline->extended_value & ZEND_ISEMPTY) ^
|
||||
Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL));
|
||||
}
|
||||
|
||||
result =
|
||||
(opline->extended_value & ZEND_ISEMPTY) ^
|
||||
Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL));
|
||||
|
||||
ZEND_VM_C_LABEL(isset_object_finish):
|
||||
FREE_OP2();
|
||||
FREE_OP1();
|
||||
ZEND_VM_SMART_BRANCH(result, 1);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -562,7 +562,7 @@ zend_object_handlers php_com_object_handlers = {
|
||||
com_object_count,
|
||||
NULL, /* get_debug_info */
|
||||
NULL, /* get_closure */
|
||||
NULL, /* get_gc */
|
||||
zend_std_get_gc, /* get_gc */
|
||||
};
|
||||
|
||||
void php_com_object_enable_event_sink(php_com_dotnet_object *obj, int enable)
|
||||
|
@ -4173,7 +4173,7 @@ ZEND_METHOD(reflection_class, hasProperty)
|
||||
}
|
||||
RETURN_TRUE;
|
||||
} else {
|
||||
if (Z_TYPE(intern->obj) != IS_UNDEF && Z_OBJ_HANDLER(intern->obj, has_property)) {
|
||||
if (Z_TYPE(intern->obj) != IS_UNDEF) {
|
||||
ZVAL_STR_COPY(&property, name);
|
||||
if (Z_OBJ_HANDLER(intern->obj, has_property)(&intern->obj, &property, 2, NULL)) {
|
||||
zval_ptr_dtor(&property);
|
||||
|
@ -897,10 +897,8 @@ static zend_function *spl_recursive_it_get_method(zend_object **zobject, zend_st
|
||||
function_handler = zend_std_get_method(zobject, method, key);
|
||||
if (!function_handler) {
|
||||
if ((function_handler = zend_hash_find_ptr(&Z_OBJCE_P(zobj)->function_table, method)) == NULL) {
|
||||
if (Z_OBJ_HT_P(zobj)->get_method) {
|
||||
*zobject = Z_OBJ_P(zobj);
|
||||
function_handler = (*zobject)->handlers->get_method(zobject, method, key);
|
||||
}
|
||||
*zobject = Z_OBJ_P(zobj);
|
||||
function_handler = (*zobject)->handlers->get_method(zobject, method, key);
|
||||
} else {
|
||||
*zobject = Z_OBJ_P(zobj);
|
||||
}
|
||||
|
@ -4097,10 +4097,6 @@ static inline zval *array_column_fetch_prop(zval *data, zval *name, zval *rv) /*
|
||||
zval *prop = NULL;
|
||||
|
||||
if (Z_TYPE_P(data) == IS_OBJECT) {
|
||||
if (!Z_OBJ_HANDLER_P(data, has_property) || !Z_OBJ_HANDLER_P(data, read_property)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The has_property check is first performed in "exists" mode (which returns true for
|
||||
* properties that are null but exist) and then in "has" mode to handle objects that
|
||||
* implement __isset (which is not called in "exists" mode). */
|
||||
|
Loading…
Reference in New Issue
Block a user