mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Reuse zend_assign_to_variable() in zend_std_write_property()
This commit is contained in:
parent
899c24a8c1
commit
42d33a9fc6
3 changed files with 61 additions and 105 deletions
|
@ -692,7 +692,7 @@ static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t ar
|
|||
static zend_always_inline void zend_assign_to_object(zval *retval, zval *object, uint32_t object_op_type, zval *property_name, int value_type, const znode_op *value_op, const zend_execute_data *execute_data, int opcode, void **cache_slot TSRMLS_DC)
|
||||
{
|
||||
zend_free_op free_value;
|
||||
zval *value = get_zval_ptr(value_type, value_op, execute_data, &free_value, BP_VAR_R);
|
||||
zval *value = get_zval_ptr_deref(value_type, value_op, execute_data, &free_value, BP_VAR_R);
|
||||
zval tmp;
|
||||
|
||||
if (object_op_type != IS_UNUSED) {
|
||||
|
@ -830,65 +830,6 @@ static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *valu
|
|||
}
|
||||
}
|
||||
|
||||
static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type TSRMLS_DC)
|
||||
{
|
||||
do {
|
||||
if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
|
||||
zend_refcounted *garbage;
|
||||
|
||||
if (Z_ISREF_P(variable_ptr)) {
|
||||
variable_ptr = Z_REFVAL_P(variable_ptr);
|
||||
if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
|
||||
UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
|
||||
Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
|
||||
return variable_ptr;
|
||||
}
|
||||
if ((value_type & (IS_VAR|IS_CV)) && variable_ptr == value) {
|
||||
return variable_ptr;
|
||||
}
|
||||
garbage = Z_COUNTED_P(variable_ptr);
|
||||
if (--GC_REFCOUNT(garbage) == 0) {
|
||||
ZVAL_COPY_VALUE(variable_ptr, value);
|
||||
if (value_type == IS_CONST) {
|
||||
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
|
||||
if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
|
||||
zval_copy_ctor_func(variable_ptr);
|
||||
}
|
||||
} else if (value_type != IS_TMP_VAR) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
|
||||
Z_ADDREF_P(variable_ptr);
|
||||
}
|
||||
}
|
||||
_zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
|
||||
return variable_ptr;
|
||||
} else { /* we need to split */
|
||||
/* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
|
||||
if ((Z_COLLECTABLE_P(variable_ptr)) &&
|
||||
UNEXPECTED(!GC_INFO(garbage))) {
|
||||
gc_possible_root(garbage TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
ZVAL_COPY_VALUE(variable_ptr, value);
|
||||
if (value_type == IS_CONST) {
|
||||
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
|
||||
if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
|
||||
zval_copy_ctor_func(variable_ptr);
|
||||
}
|
||||
} else if (value_type != IS_TMP_VAR) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
|
||||
Z_ADDREF_P(variable_ptr);
|
||||
}
|
||||
}
|
||||
return variable_ptr;
|
||||
}
|
||||
|
||||
/* Utility Functions for Extensions */
|
||||
static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
|
||||
{
|
||||
|
|
|
@ -129,6 +129,65 @@ again:
|
|||
return result;
|
||||
}
|
||||
|
||||
static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type TSRMLS_DC)
|
||||
{
|
||||
do {
|
||||
if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
|
||||
zend_refcounted *garbage;
|
||||
|
||||
if (Z_ISREF_P(variable_ptr)) {
|
||||
variable_ptr = Z_REFVAL_P(variable_ptr);
|
||||
if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
|
||||
UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
|
||||
Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
|
||||
return variable_ptr;
|
||||
}
|
||||
if ((value_type & (IS_VAR|IS_CV)) && variable_ptr == value) {
|
||||
return variable_ptr;
|
||||
}
|
||||
garbage = Z_COUNTED_P(variable_ptr);
|
||||
if (--GC_REFCOUNT(garbage) == 0) {
|
||||
ZVAL_COPY_VALUE(variable_ptr, value);
|
||||
if (value_type == IS_CONST) {
|
||||
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
|
||||
if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
|
||||
zval_copy_ctor_func(variable_ptr);
|
||||
}
|
||||
} else if (value_type != IS_TMP_VAR) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
|
||||
Z_ADDREF_P(variable_ptr);
|
||||
}
|
||||
}
|
||||
_zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
|
||||
return variable_ptr;
|
||||
} else { /* we need to split */
|
||||
/* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
|
||||
if ((Z_COLLECTABLE_P(variable_ptr)) &&
|
||||
UNEXPECTED(!GC_INFO(garbage))) {
|
||||
gc_possible_root(garbage TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
ZVAL_COPY_VALUE(variable_ptr, value);
|
||||
if (value_type == IS_CONST) {
|
||||
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
|
||||
if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
|
||||
zval_copy_ctor_func(variable_ptr);
|
||||
}
|
||||
} else if (value_type != IS_TMP_VAR) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
|
||||
Z_ADDREF_P(variable_ptr);
|
||||
}
|
||||
}
|
||||
return variable_ptr;
|
||||
}
|
||||
|
||||
ZEND_API int zval_update_constant(zval *pp, zend_bool inline_change TSRMLS_DC);
|
||||
ZEND_API int zval_update_constant_inline_change(zval *pp, zend_class_entry *scope TSRMLS_DC);
|
||||
ZEND_API int zval_update_constant_no_inline_change(zval *pp, zend_class_entry *scope TSRMLS_DC);
|
||||
|
|
|
@ -545,51 +545,7 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, v
|
|||
} else if (EXPECTED(zobj->properties != NULL)) {
|
||||
if ((variable_ptr = zend_hash_find(zobj->properties, Z_STR_P(member))) != NULL) {
|
||||
found:
|
||||
/* if we already have this value there, we don't actually need to do anything */
|
||||
if (EXPECTED(variable_ptr != value)) {
|
||||
/* if we are assigning reference, we shouldn't move it, but instead assign variable
|
||||
to the same pointer */
|
||||
if (Z_ISREF_P(variable_ptr)) {
|
||||
zval garbage;
|
||||
|
||||
ZVAL_COPY_VALUE(&garbage, Z_REFVAL_P(variable_ptr)); /* old value should be destroyed */
|
||||
|
||||
/* To check: can't *variable_ptr be some system variable like error_zval here? */
|
||||
if (UNEXPECTED(Z_REFCOUNTED_P(value))) {
|
||||
if (EXPECTED(!Z_ISREF_P(value))) {
|
||||
Z_ADDREF_P(value);
|
||||
} else {
|
||||
if (Z_REFCOUNT_P(value) == 1) {
|
||||
ZVAL_UNREF(value);
|
||||
} else {
|
||||
value = Z_REFVAL_P(value);
|
||||
}
|
||||
if (Z_REFCOUNTED_P(value)) {
|
||||
if (UNEXPECTED(Z_REFVAL_P(variable_ptr) == value)) {
|
||||
goto exit;
|
||||
}
|
||||
Z_ADDREF_P(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
ZVAL_COPY_VALUE(Z_REFVAL_P(variable_ptr), value);
|
||||
zval_ptr_dtor(&garbage);
|
||||
} else {
|
||||
zval garbage;
|
||||
|
||||
ZVAL_COPY_VALUE(&garbage, variable_ptr);
|
||||
|
||||
/* if we assign referenced variable, we should separate it */
|
||||
ZVAL_COPY_VALUE(variable_ptr, value);
|
||||
if (Z_REFCOUNTED_P(variable_ptr)) {
|
||||
Z_ADDREF_P(variable_ptr);
|
||||
if (Z_ISREF_P(variable_ptr)) {
|
||||
SEPARATE_ZVAL(variable_ptr);
|
||||
}
|
||||
}
|
||||
zval_ptr_dtor(&garbage);
|
||||
}
|
||||
}
|
||||
zend_assign_to_variable(variable_ptr, value, (IS_VAR|IS_TMP_VAR) TSRMLS_CC);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue