summaryrefslogtreecommitdiff
path: root/Zend/zend_execute.h
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2015-04-03 01:32:20 +0300
committerDmitry Stogov <dmitry@zend.com>2015-04-03 01:32:20 +0300
commitadcf0c6052761350695da211b337edff12c6e63c (patch)
treeadfa8f0c41009c5d04a6b612f289e3ec4e7a1d4d /Zend/zend_execute.h
parentf26592846f8190fdab6cb148e484a4aeb032c096 (diff)
downloadphp-git-adcf0c6052761350695da211b337edff12c6e63c.tar.gz
Improved reference counting
Diffstat (limited to 'Zend/zend_execute.h')
-rw-r--r--Zend/zend_execute.h25
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;
}