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? */
- ZVAL_COPY_VALUE(Z_REFVAL_P(variable_ptr), value);
- if (Z_REFCOUNTED_P(value) && Z_REFCOUNT_P(value) > 0) {
- zval_copy_ctor(Z_REFVAL_P(variable_ptr));
+ 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;