IS_CONST operands don't have to be separated. Use reference-counting instead of duplication.

- with opcache all IS_CONST operands are not refcounted (scalars, interned strings or immutable arrays)
- without opcache IS_CONST operands are not shared between processes or threads and may use common reference counters
This commit is contained in:
Dmitry Stogov 2016-04-05 20:09:14 +03:00
parent a5e21665ee
commit a186ac0e47
7 changed files with 198 additions and 364 deletions

View File

@ -10,7 +10,6 @@ class Node {
public $parent;
function __construct($name) {
$this->name = $name;
$this->children = array();
$this->parent = null;
}
function insert($node) {

View File

@ -33,7 +33,7 @@ void free_zend_constant(zval *zv)
zend_constant *c = Z_PTR_P(zv);
if (!(c->flags & CONST_PERSISTENT)) {
zval_dtor(&c->value);
zval_ptr_dtor(&c->value);
} else {
zval_internal_dtor(&c->value);
}

View File

@ -1090,7 +1090,6 @@ static zend_never_inline void zend_assign_to_object_dim(zval *retval, zval *obje
{
zend_free_op free_value;
zval *value = get_zval_ptr_deref(value_type, value_op, execute_data, &free_value, BP_VAR_R);
zval tmp;
/* Note: property_name in this case is really the array index! */
if (!Z_OBJ_HT_P(object)->write_dimension) {
@ -1101,10 +1100,8 @@ static zend_never_inline void zend_assign_to_object_dim(zval *retval, zval *obje
/* separate our value if necessary */
if (value_type == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
ZVAL_COPY_VALUE(&tmp, value);
zval_copy_ctor_func(&tmp);
value = &tmp;
if (UNEXPECTED(Z_REFCOUNTED_P(value))) {
Z_ADDREF_P(value);
}
}

View File

@ -84,12 +84,7 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval
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_CV) {
if (value_type & (IS_CONST|IS_CV)) {
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
Z_ADDREF_P(variable_ptr);
}
@ -113,12 +108,7 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval
} 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_CV) {
if (value_type & (IS_CONST|IS_CV)) {
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
Z_ADDREF_P(variable_ptr);
}

View File

@ -227,7 +227,7 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o
zval new_obj;
ZVAL_OBJ(&new_obj, new_object);
zval_copy_ctor(&new_obj);
Z_ADDREF(new_obj);
zend_call_method_with_0_params(&new_obj, old_object->ce, &old_object->ce->clone, ZEND_CLONE_FUNC_NAME, NULL);
zval_ptr_dtor(&new_obj);
}

View File

@ -2257,10 +2257,8 @@ ZEND_VM_C_LABEL(fast_assign_obj):
}
/* separate our value if necessary */
if (OP_DATA_TYPE == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
ZVAL_COPY_VALUE(&tmp, value);
zval_copy_ctor_func(&tmp);
value = &tmp;
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) {
Z_ADDREF_P(value);
}
} else if (OP_DATA_TYPE != IS_TMP_VAR) {
if (Z_ISREF_P(value)) {
@ -2306,10 +2304,8 @@ ZEND_VM_C_LABEL(fast_assign_obj):
/* separate our value if necessary */
if (OP_DATA_TYPE == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
ZVAL_COPY_VALUE(&tmp, value);
zval_copy_ctor_func(&tmp);
value = &tmp;
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) {
Z_ADDREF_P(value);
}
} else if (OP_DATA_TYPE != IS_TMP_VAR) {
ZVAL_DEREF(value);
@ -4166,8 +4162,8 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
ZVAL_COPY_VALUE(return_value, retval_ptr);
if (OP1_TYPE == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE_P(return_value))) {
zval_copy_ctor_func(return_value);
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) {
Z_ADDREF_P(return_value);
}
}
} else if (OP1_TYPE == IS_CV) {
@ -4277,8 +4273,8 @@ ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, CONST|TMP|VAR|CV, ANY)
if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
ZVAL_COPY_VALUE(&generator->retval, retval);
if (OP1_TYPE == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->retval))) {
zval_copy_ctor_func(&generator->retval);
if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) {
Z_ADDREF(generator->retval);
}
}
} else if (OP1_TYPE == IS_CV) {
@ -4407,8 +4403,8 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, NUM)
arg = ZEND_CALL_VAR(EX(call), opline->result.var);
ZVAL_COPY_VALUE(arg, value);
if (OP1_TYPE == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
zval_copy_ctor_func(arg);
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) {
Z_ADDREF_P(arg);
}
}
ZEND_VM_NEXT_OPCODE();
@ -4438,8 +4434,8 @@ ZEND_VM_C_LABEL(send_val_by_ref):
arg = ZEND_CALL_VAR(EX(call), opline->result.var);
ZVAL_COPY_VALUE(arg, value);
if (OP1_TYPE == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
zval_copy_ctor_func(arg);
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) {
Z_ADDREF_P(arg);
}
}
ZEND_VM_NEXT_OPCODE();
@ -4955,9 +4951,8 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, NUM, CONST)
HANDLE_EXCEPTION();
}
} else {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) {
zval_copy_ctor_func(param);
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(param))) {
Z_ADDREF_P(param);
}
}
}
@ -7536,9 +7531,8 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
HANDLE_EXCEPTION();
}
} else {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE(c.value))) {
zval_copy_ctor_func(&c.value);
if (UNEXPECTED(Z_OPT_REFCOUNTED(c.value))) {
Z_ADDREF(c.value);
}
}
c.flags = CONST_CS; /* non persistent, case sensetive */

File diff suppressed because it is too large Load Diff