diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 6c17fdbb525..41c270ab405 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -4,7 +4,7 @@ PHP 8.0 INTERNALS UPGRADE NOTES a. Object Handlers API b. ZEND_OVERLOADED_FUNCTION and corresponding call_method() object handler c. TSRM changes - d. set() object handler + d. get() and set() object handlers 2. Build system changes a. Abstract @@ -40,9 +40,12 @@ PHP 8.0 INTERNALS UPGRADE NOTES - tsrm_free_interpreter_context - support for GNUPTH, SGI ST, and BETHREADS - d. The set() object handler, which allowed overloading the assignment - operator, has been removed. There is no direct replacement for this - functionality, though some use-cases may be replaced by do_operation(). + d. The get() and set() object handlers have been removed. The get() handler + can generally be replaced with cast_object(). Some uses of set() may be + replaced by do_operation(). If set() was used to overload direct + assignments using "=", then this is no longer supported and the + functionality should be provided in some other way (for example, as + modification of an object property). ======================== diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 3627cc6bbae..9115129a04e 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -438,22 +438,6 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest *dest = Z_STR_P(arg); return 1; } - } else if (zobj->handlers->get) { - zval rv; - zval *z = zobj->handlers->get(zobj, &rv); - - if (Z_TYPE_P(z) != IS_OBJECT) { - OBJ_RELEASE(zobj); - if (Z_TYPE_P(z) == IS_STRING) { - ZVAL_COPY_VALUE(arg, z); - } else { - ZVAL_STR(arg, zval_get_string_func(z)); - zval_ptr_dtor(z); - } - *dest = Z_STR_P(arg); - return 1; - } - zval_ptr_dtor(z); } return 0; } else { diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 87928e8b2bb..4ea2dc9dc6b 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -789,7 +789,6 @@ ZEND_FUNCTION(define) ZVAL_UNDEF(&val_free); -repeat: switch (Z_TYPE_P(val)) { case IS_LONG: case IS_DOUBLE: @@ -810,17 +809,10 @@ repeat: } break; case IS_OBJECT: - if (Z_TYPE(val_free) == IS_UNDEF) { - if (Z_OBJ_HT_P(val)->get) { - zval rv; - val = Z_OBJ_HT_P(val)->get(Z_OBJ_P(val), &rv); - ZVAL_COPY_VALUE(&val_free, val); - goto repeat; - } else if (Z_OBJ_HT_P(val)->cast_object) { - if (Z_OBJ_HT_P(val)->cast_object(Z_OBJ_P(val), &val_free, IS_STRING) == SUCCESS) { - val = &val_free; - break; - } + if (Z_OBJ_HT_P(val)->cast_object) { + if (Z_OBJ_HT_P(val)->cast_object(Z_OBJ_P(val), &val_free, IS_STRING) == SUCCESS) { + val = &val_free; + break; } } /* no break */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index bf4a8e224a1..e031fa412e5 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1296,15 +1296,6 @@ static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval * if ((z = Z_OBJ_HT_P(object)->read_dimension(Z_OBJ_P(object), property, BP_VAR_R, &rv)) != NULL) { - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { - zval rv2; - zval *value = Z_OBJ_HT_P(z)->get(Z_OBJ_P(z), &rv2); - - if (z == &rv) { - zval_ptr_dtor(&rv); - } - ZVAL_COPY_VALUE(z, value); - } if (binary_op(&res, z, value) == SUCCESS) { Z_OBJ_HT_P(object)->write_dimension(Z_OBJ_P(object), property, &res); } @@ -1783,15 +1774,6 @@ static zend_never_inline void zend_post_incdec_overloaded_property(zend_object * 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_OBJ_P(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) { @@ -1821,15 +1803,6 @@ static zend_never_inline void zend_pre_incdec_overloaded_property(zend_object *o 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_OBJ_P(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); @@ -1859,15 +1832,6 @@ static zend_never_inline void zend_assign_op_overloaded_property(zend_object *ob } 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_OBJ_P(z), &rv2); - - if (z == &rv) { - zval_ptr_dtor(&rv); - } - ZVAL_COPY_VALUE(z, value); - } if (binary_op(&res, z, value) == SUCCESS) { object->handlers->write_property(object, name, &res, cache_slot); } diff --git a/Zend/zend_iterators.c b/Zend/zend_iterators.c index 4691d8218e2..f09ff227638 100644 --- a/Zend/zend_iterators.c +++ b/Zend/zend_iterators.c @@ -36,7 +36,6 @@ static const zend_object_handlers iterator_object_handlers = { NULL, /* read dim */ NULL, /* write dim */ NULL, - NULL, /* get */ NULL, /* has prop */ NULL, /* unset prop */ NULL, /* has dim */ diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 142c0408c1a..88b8aa16a06 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1837,7 +1837,6 @@ ZEND_API const zend_object_handlers std_object_handlers = { zend_std_read_dimension, /* read_dimension */ zend_std_write_dimension, /* write_dimension */ zend_std_get_property_ptr_ptr, /* get_property_ptr_ptr */ - NULL, /* get */ zend_std_has_property, /* has_property */ zend_std_unset_property, /* unset_property */ zend_std_has_dimension, /* has_dimension */ diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index b6bdcae99c5..05ebb0b1ef2 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -63,11 +63,6 @@ typedef void (*zend_object_write_dimension_t)(zend_object *object, zval *offset, /* Used to create pointer to the property of the object, for future direct r/w access */ typedef zval *(*zend_object_get_property_ptr_ptr_t)(zend_object *object, zend_string *member, int type, void **cache_slot); -/* Used to get object value. Can be used when converting object value to - * one of the basic types and when using scalar ops (like ++, +=) on the object - */ -typedef zval* (*zend_object_get_t)(zend_object *object, zval *rv); - /* Used to check if a property of the object exists */ /* param has_set_exists: * 0 (has) whether property exists and is not NULL @@ -158,7 +153,6 @@ struct _zend_object_handlers { 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_has_property_t has_property; /* required */ zend_object_unset_property_t unset_property; /* required */ zend_object_has_dimension_t has_dimension; /* required */ diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 5b134e46b7f..9cf0dcd22f5 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -143,13 +143,6 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) /* { "Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(op)->name),\ zend_get_type_by_const(ctype)); \ } \ - } else if (Z_OBJ_HT_P(op)->get) { \ - zval *newop = Z_OBJ_HT_P(op)->get(Z_OBJ_P(op), dst); \ - if (Z_TYPE_P(newop) != IS_OBJECT) { \ - /* for safety - avoid loop */ \ - ZVAL_COPY_VALUE(dst, newop); \ - conv_func(dst); \ - } \ } /* }}} */ @@ -866,14 +859,6 @@ try_again: if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), &tmp, IS_STRING) == SUCCESS) { return Z_STR(tmp); } - } else if (Z_OBJ_HT_P(op)->get) { - zval *z = Z_OBJ_HT_P(op)->get(Z_OBJ_P(op), &tmp); - if (Z_TYPE_P(z) != IS_OBJECT) { - zend_string *str = zval_get_string(z); - zval_ptr_dtor(z); - return str; - } - zval_ptr_dtor(z); } zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name)); return ZSTR_EMPTY_ALLOC(); @@ -1969,8 +1954,7 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) { int ret; int converted = 0; - zval op1_copy, op2_copy; - zval *op_free, tmp_free; + zval op1_copy, op2_copy, tmp_free; while (1) { switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { @@ -2076,13 +2060,7 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) } } if (Z_TYPE_P(op1) == IS_OBJECT) { - if (Z_OBJ_HT_P(op1)->get) { - zval rv; - op_free = Z_OBJ_HT_P(op1)->get(Z_OBJ_P(op1), &rv); - ret = compare_function(result, op_free, op2); - zend_free_obj_get_result(op_free); - return ret; - } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) { + if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) { ZVAL_UNDEF(&tmp_free); if (Z_OBJ_HT_P(op1)->cast_object(Z_OBJ_P(op1), &tmp_free, ((Z_TYPE_P(op2) == IS_FALSE || Z_TYPE_P(op2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op2))) == FAILURE) { ZVAL_LONG(result, 1); @@ -2095,13 +2073,7 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) } } if (Z_TYPE_P(op2) == IS_OBJECT) { - if (Z_OBJ_HT_P(op2)->get) { - zval rv; - op_free = Z_OBJ_HT_P(op2)->get(Z_OBJ_P(op2), &rv); - ret = compare_function(result, op1, op_free); - zend_free_obj_get_result(op_free); - return ret; - } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) { + if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) { ZVAL_UNDEF(&tmp_free); if (Z_OBJ_HT_P(op2)->cast_object(Z_OBJ_P(op2), &tmp_free, ((Z_TYPE_P(op1) == IS_FALSE || Z_TYPE_P(op1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op1))) == FAILURE) { ZVAL_LONG(result, -1); @@ -2549,17 +2521,6 @@ ZEND_API int ZEND_FASTCALL zend_object_is_true(zval *op) /* {{{ */ return Z_TYPE(tmp) == IS_TRUE; } zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to bool", ZSTR_VAL(zobj->ce->name)); - } else if (zobj->handlers->get) { - int result; - zval rv; - zval *tmp = zobj->handlers->get(zobj, &rv); - - if (Z_TYPE_P(tmp) != IS_OBJECT) { - /* for safety - avoid loop */ - result = i_zend_is_true(tmp); - zval_ptr_dtor(tmp); - return result; - } } return 1; } diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index feda1a96436..38930175532 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -174,14 +174,6 @@ static void com_write_dimension(zend_object *object, zval *offset, zval *value) } } -#if 0 -static zval *com_object_get(zval *property) -{ - /* Not yet implemented in the engine */ - return NULL; -} -#endif - static int com_property_exists(zend_object *object, zend_string *member, int check_empty, void **cache_slot) { DISPID dispid; @@ -540,7 +532,6 @@ zend_object_handlers php_com_object_handlers = { com_read_dimension, com_write_dimension, NULL, - NULL, /* com_object_get, */ com_property_exists, com_property_delete, com_dimension_exists, diff --git a/ext/com_dotnet/com_saproxy.c b/ext/com_dotnet/com_saproxy.c index 8d76af3830f..96a743290a0 100644 --- a/ext/com_dotnet/com_saproxy.c +++ b/ext/com_dotnet/com_saproxy.c @@ -274,14 +274,6 @@ static void saproxy_write_dimension(zend_object *object, zval *offset, zval *val } } -#if 0 -static zval *saproxy_object_get(zval *property) -{ - /* Not yet implemented in the engine */ - return NULL; -} -#endif - static int saproxy_property_exists(zend_object *object, zend_string *member, int check_empty, void **cache_slot) { /* no properties */ @@ -397,7 +389,6 @@ zend_object_handlers php_com_saproxy_handlers = { saproxy_read_dimension, saproxy_write_dimension, NULL, - NULL, /* saproxy_object_get, */ saproxy_property_exists, saproxy_property_delete, saproxy_dimension_exists, diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 3fad4e17f8f..86f7e6ad6c9 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -4610,13 +4610,6 @@ static ZEND_COLD void zend_ffi_free_unset_property(zend_object *obj, zend_string } /* }}} */ -static zval* zend_ffi_free_get(zend_object *obj, zval *rv) /* {{{ */ -{ - zend_ffi_use_after_free(); - return NULL; -} -/* }}} */ - static HashTable *zend_ffi_free_get_debug_info(zend_object *obj, int *is_temp) /* {{{ */ { zend_ffi_use_after_free(); @@ -4767,7 +4760,6 @@ ZEND_MINIT_FUNCTION(ffi) zend_ffi_cdata_free_handlers.read_dimension = zend_ffi_free_read_dimension; zend_ffi_cdata_free_handlers.write_dimension = zend_ffi_free_write_dimension; zend_ffi_cdata_free_handlers.get_property_ptr_ptr = zend_fake_get_property_ptr_ptr; - zend_ffi_cdata_free_handlers.get = zend_ffi_free_get; zend_ffi_cdata_free_handlers.has_property = zend_ffi_free_has_property; zend_ffi_cdata_free_handlers.unset_property = zend_ffi_free_unset_property; zend_ffi_cdata_free_handlers.has_dimension = zend_ffi_free_has_dimension; diff --git a/ext/intl/collator/collator_convert.c b/ext/intl/collator/collator_convert.c index fc9d7da41f3..6a2442a8a94 100644 --- a/ext/intl/collator/collator_convert.c +++ b/ext/intl/collator/collator_convert.c @@ -226,29 +226,7 @@ zval* collator_convert_object_to_string( zval* obj, zval *rv ) } /* Try object's handlers. */ - if( Z_OBJ_HT_P(obj)->get ) - { - zstr = Z_OBJ_HT_P(obj)->get( Z_OBJ_P(obj), rv ); - - switch( Z_TYPE_P( zstr ) ) - { - case IS_OBJECT: - { - /* Bail out. */ - zval_ptr_dtor( zstr ); - COLLATOR_CONVERT_RETURN_FAILED( obj ); - } break; - - case IS_STRING: - break; - - default: - { - convert_to_string( zstr ); - } break; - } - } - else if( Z_OBJ_HT_P(obj)->cast_object ) + if( Z_OBJ_HT_P(obj)->cast_object ) { zstr = rv; diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 8df29adce09..231870de734 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -968,15 +968,6 @@ static void ZEND_FASTCALL zend_jit_assign_dim_op_helper(zval *container, zval *d z = Z_OBJ_HT_P(object)->read_dimension(Z_OBJ_P(object), property, BP_VAR_R, &rv); if (z != NULL) { - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { - zval rv2; - zval *value = Z_OBJ_HT_P(z)->get(Z_OBJ_P(z), &rv2); - - if (z == &rv) { - zval_ptr_dtor(&rv); - } - ZVAL_COPY_VALUE(z, value); - } if (binary_op(&res, Z_ISREF_P(z) ? Z_REFVAL_P(z) : z, value) == SUCCESS) { Z_OBJ_HT_P(object)->write_dimension(Z_OBJ_P(object), property, &res); } diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 2ea83a1aa25..0738f0364b1 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -50,13 +50,13 @@ PHP_SXE_API zend_class_entry *sxe_get_element_class_entry() /* {{{ */ static php_sxe_object* php_sxe_object_new(zend_class_entry *ce, zend_function *fptr_count); static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data); static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data); -static zval *sxe_get_value(zend_object *z, zval *rv); static void php_sxe_iterator_dtor(zend_object_iterator *iter); static int php_sxe_iterator_valid(zend_object_iterator *iter); static zval *php_sxe_iterator_current_data(zend_object_iterator *iter); static void php_sxe_iterator_current_key(zend_object_iterator *iter, zval *key); static void php_sxe_iterator_move_forward(zend_object_iterator *iter); static void php_sxe_iterator_rewind(zend_object_iterator *iter); +static int sxe_object_cast_ex(zend_object *readobj, zval *writeobj, int type); /* {{{ _node_as_zval() */ @@ -519,7 +519,12 @@ long_dim: break; case IS_OBJECT: if (Z_OBJCE_P(value) == sxe_class_entry) { - value = sxe_get_value(Z_OBJ_P(value), &zval_copy); + if (sxe_object_cast_ex(Z_OBJ_P(value), &zval_copy, IS_STRING) == FAILURE) { + zend_error(E_ERROR, "Unable to cast node to string"); + /* FIXME: Should not be fatal */ + } + + value = &zval_copy; new_value = 1; break; } @@ -1999,17 +2004,6 @@ SXE_METHOD(count) } /* }}} */ -static zval *sxe_get_value(zend_object *zobj, zval *rv) /* {{{ */ -{ - if (sxe_object_cast_ex(zobj, rv, IS_STRING) == FAILURE) { - zend_error(E_ERROR, "Unable to cast node to string"); - /* FIXME: Should not be fatal */ - } - - return rv; -} -/* }}} */ - static zend_object_handlers sxe_object_handlers; /* {{{ sxe_object_clone() @@ -2706,7 +2700,6 @@ PHP_MINIT_FUNCTION(simplexml) sxe_object_handlers.read_dimension = sxe_dimension_read; sxe_object_handlers.write_dimension = sxe_dimension_write; sxe_object_handlers.get_property_ptr_ptr = sxe_property_get_adr; - sxe_object_handlers.get = sxe_get_value; sxe_object_handlers.has_property = sxe_property_exists; sxe_object_handlers.unset_property = sxe_property_delete; sxe_object_handlers.has_dimension = sxe_dimension_exists;