diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2018-10-13 15:30:27 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2018-10-16 20:53:59 +0200 |
commit | 1cfbb21790ff6dd4931223c5bdc18a0cebf3ffd4 (patch) | |
tree | 9fc9117f49dc0ad1dd6cd22d04d6068dcbf90902 /Zend/zend_execute.c | |
parent | fc0aa264c1bbe7304619e73940484b39ed39af2c (diff) | |
download | php-git-1cfbb21790ff6dd4931223c5bdc18a0cebf3ffd4.tar.gz |
Classify object handlers are required/optional
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r-- | Zend/zend_execute.c | 345 |
1 files changed, 124 insertions, 221 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index cbaa53f4e1..66ff7abfcd 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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; - } + 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); + 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); + ZVAL_COPY_DEREF(&z_copy, z); + ZVAL_COPY(EX_VAR(opline->result.var), &z_copy); + if (inc) { + increment_function(&z_copy); } else { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - ZVAL_NULL(EX_VAR(opline->result.var)); + 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; + 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 (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); + if (z == &rv) { + zval_ptr_dtor(&rv); } - 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); + ZVAL_COPY_VALUE(z, value); + } + ZVAL_COPY_DEREF(&z_copy, z); + if (inc) { + increment_function(&z_copy); } 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)); - } + 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_UNDEF(EX_VAR(opline->result.var)); } - 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)); + 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); } } |