mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Merge branch 'PHP-7.4'
* PHP-7.4: zend_assign_to_variable() optimization
This commit is contained in:
commit
207d928da8
2 changed files with 84 additions and 67 deletions
|
@ -3026,6 +3026,46 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference
|
||||||
return i_zend_verify_ref_assignable_zval(ref, zv, strict);
|
return i_zend_verify_ref_assignable_zval(ref, zv, strict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *value, zend_uchar value_type, zend_bool strict, zend_refcounted *ref)
|
||||||
|
{
|
||||||
|
zend_bool need_copy = ZEND_CONST_COND(value_type & (IS_CONST|IS_CV), 1) ||
|
||||||
|
((value_type & IS_VAR) && UNEXPECTED(ref) && GC_REFCOUNT(ref) > 1);
|
||||||
|
zend_bool ret;
|
||||||
|
zval tmp;
|
||||||
|
|
||||||
|
if (need_copy) {
|
||||||
|
ZVAL_COPY(&tmp, value);
|
||||||
|
value = &tmp;
|
||||||
|
}
|
||||||
|
ret = zend_verify_ref_assignable_zval(Z_REF_P(variable_ptr), value, strict);
|
||||||
|
if (need_copy) {
|
||||||
|
Z_TRY_DELREF_P(value);
|
||||||
|
}
|
||||||
|
if (!ret) {
|
||||||
|
zval_ptr_dtor(value);
|
||||||
|
return Z_REFVAL_P(variable_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
variable_ptr = Z_REFVAL_P(variable_ptr);
|
||||||
|
if (EXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
|
||||||
|
zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);
|
||||||
|
|
||||||
|
zend_copy_to_variable(variable_ptr, value, value_type, ref);
|
||||||
|
if (GC_DELREF(garbage) == 0) {
|
||||||
|
rc_dtor_func(garbage);
|
||||||
|
} else { /* we need to split */
|
||||||
|
/* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
|
||||||
|
if (UNEXPECTED(GC_MAY_LEAK(garbage))) {
|
||||||
|
gc_possible_root(garbage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return variable_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
zend_copy_to_variable(variable_ptr, value, value_type, ref);
|
||||||
|
return variable_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
ZEND_API zend_bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, zend_bool strict) {
|
ZEND_API zend_bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, zend_bool strict) {
|
||||||
zval *val = orig_val;
|
zval *val = orig_val;
|
||||||
if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) {
|
if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) {
|
||||||
|
|
|
@ -78,75 +78,12 @@ ZEND_API ZEND_COLD void zend_throw_ref_type_error_type(zend_property_info *prop1
|
||||||
ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_list *source_list, zend_property_info *prop);
|
ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_list *source_list, zend_property_info *prop);
|
||||||
ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_list *source_list, zend_property_info *prop);
|
ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_list *source_list, zend_property_info *prop);
|
||||||
|
|
||||||
static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type, zend_bool strict)
|
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *value, zend_uchar value_type, zend_bool strict, zend_refcounted *ref);
|
||||||
|
|
||||||
|
static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type, zend_refcounted *ref)
|
||||||
{
|
{
|
||||||
zend_refcounted *ref = NULL;
|
|
||||||
zval tmp;
|
|
||||||
|
|
||||||
if (ZEND_CONST_COND(value_type & (IS_VAR|IS_CV), 1) && 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;
|
|
||||||
|
|
||||||
if (Z_ISREF_P(variable_ptr)) {
|
|
||||||
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) {
|
|
||||||
zend_bool need_copy = ZEND_CONST_COND(value_type & (IS_CONST|IS_CV), 1) ||
|
|
||||||
((value_type & IS_VAR) && UNEXPECTED(ref) && GC_REFCOUNT(ref) > 1);
|
|
||||||
zend_bool ret;
|
|
||||||
if (need_copy) {
|
|
||||||
ZVAL_COPY(&tmp, value);
|
|
||||||
value = &tmp;
|
|
||||||
}
|
|
||||||
ret = zend_verify_ref_assignable_zval(Z_REF_P(variable_ptr), value, strict);
|
|
||||||
if (need_copy) {
|
|
||||||
Z_TRY_DELREF_P(value);
|
|
||||||
}
|
|
||||||
if (!ret) {
|
|
||||||
zval_ptr_dtor(value);
|
|
||||||
return Z_REFVAL_P(variable_ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
variable_ptr = Z_REFVAL_P(variable_ptr);
|
|
||||||
if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
garbage = Z_COUNTED_P(variable_ptr);
|
|
||||||
ZVAL_COPY_VALUE(variable_ptr, value);
|
|
||||||
if (ZEND_CONST_COND(value_type == IS_CONST, 0)) {
|
|
||||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
|
|
||||||
Z_ADDREF_P(variable_ptr);
|
|
||||||
}
|
|
||||||
} else if (value_type & (IS_CONST|IS_CV)) {
|
|
||||||
if (Z_OPT_REFCOUNTED_P(variable_ptr)) {
|
|
||||||
Z_ADDREF_P(variable_ptr);
|
|
||||||
}
|
|
||||||
} else if (ZEND_CONST_COND(value_type == IS_VAR, 1) && UNEXPECTED(ref)) {
|
|
||||||
if (UNEXPECTED(GC_DELREF(ref) == 0)) {
|
|
||||||
efree_size(ref, sizeof(zend_reference));
|
|
||||||
} else if (Z_OPT_REFCOUNTED_P(variable_ptr)) {
|
|
||||||
Z_ADDREF_P(variable_ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (GC_DELREF(garbage) == 0) {
|
|
||||||
rc_dtor_func(garbage);
|
|
||||||
} else { /* we need to split */
|
|
||||||
/* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
|
|
||||||
if (UNEXPECTED(GC_MAY_LEAK(garbage))) {
|
|
||||||
gc_possible_root(garbage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return variable_ptr;
|
|
||||||
}
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
ZVAL_COPY_VALUE(variable_ptr, value);
|
ZVAL_COPY_VALUE(variable_ptr, value);
|
||||||
if (ZEND_CONST_COND(value_type == IS_CONST, 0)) {
|
if (ZEND_CONST_COND(value_type == IS_CONST, 0)) {
|
||||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
|
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
|
||||||
Z_ADDREF_P(variable_ptr);
|
Z_ADDREF_P(variable_ptr);
|
||||||
}
|
}
|
||||||
|
@ -161,6 +98,46 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval
|
||||||
Z_ADDREF_P(variable_ptr);
|
Z_ADDREF_P(variable_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type, zend_bool strict)
|
||||||
|
{
|
||||||
|
zend_refcounted *ref = NULL;
|
||||||
|
|
||||||
|
if (ZEND_CONST_COND(value_type & (IS_VAR|IS_CV), 1) && 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;
|
||||||
|
|
||||||
|
if (Z_ISREF_P(variable_ptr)) {
|
||||||
|
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) {
|
||||||
|
return zend_assign_to_typed_ref(variable_ptr, value, value_type, strict, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
variable_ptr = Z_REFVAL_P(variable_ptr);
|
||||||
|
if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
garbage = Z_COUNTED_P(variable_ptr);
|
||||||
|
zend_copy_to_variable(variable_ptr, value, value_type, ref);
|
||||||
|
if (GC_DELREF(garbage) == 0) {
|
||||||
|
rc_dtor_func(garbage);
|
||||||
|
} else { /* we need to split */
|
||||||
|
/* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
|
||||||
|
if (UNEXPECTED(GC_MAY_LEAK(garbage))) {
|
||||||
|
gc_possible_root(garbage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return variable_ptr;
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
zend_copy_to_variable(variable_ptr, value, value_type, ref);
|
||||||
return variable_ptr;
|
return variable_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue