diff options
author | Dmitry Stogov <dmitry@zend.com> | 2015-04-03 01:32:20 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2015-04-03 01:32:20 +0300 |
commit | adcf0c6052761350695da211b337edff12c6e63c (patch) | |
tree | adfa8f0c41009c5d04a6b612f289e3ec4e7a1d4d /Zend/zend_execute.h | |
parent | f26592846f8190fdab6cb148e484a4aeb032c096 (diff) | |
download | php-git-adcf0c6052761350695da211b337edff12c6e63c.tar.gz |
Improved reference counting
Diffstat (limited to 'Zend/zend_execute.h')
-rw-r--r-- | Zend/zend_execute.h | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index dce9e1c040..408a7c5032 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -55,6 +55,13 @@ ZEND_API void zend_verify_internal_return_error(const zend_function *zf, const c static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type) { + zend_refcounted *ref = NULL; + + if ((value_type & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ref = Z_COUNTED_P(value); + value = Z_REFVAL_P(value); + } + do { if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { zend_refcounted *garbage; @@ -81,12 +88,18 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) { zval_copy_ctor_func(variable_ptr); } - } else if (value_type != IS_TMP_VAR) { + } else if (value_type == IS_CV) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) { Z_ADDREF_P(variable_ptr); } + } else if (/* value_type == IS_VAR && */ UNEXPECTED(ref)) { + if (UNEXPECTED(--GC_REFCOUNT(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(variable_ptr)) { + Z_ADDREF_P(variable_ptr); + } } - _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC); + zval_dtor_func_for_ptr(garbage); return variable_ptr; } else { /* we need to split */ /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */ @@ -104,10 +117,16 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) { zval_copy_ctor_func(variable_ptr); } - } else if (value_type != IS_TMP_VAR) { + } else if (value_type == IS_CV) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) { Z_ADDREF_P(variable_ptr); } + } else if (/* value_type == IS_VAR && */ UNEXPECTED(ref)) { + if (UNEXPECTED(--GC_REFCOUNT(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(variable_ptr)) { + Z_ADDREF_P(variable_ptr); + } } return variable_ptr; } |