From 82f6f6da67a265170fe533d97edb59520da0024f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 31 May 2021 12:31:56 +0200 Subject: [PATCH] Fixed bug #81090 For concatenation, the in-place variant can be much more efficient, because it will reallocate the string in-place. Special-case the typed property compound assignment code for the case where we concatenate to a string, in which case we know that the result will also be a string, and we don't need the type check anyway. --- NEWS | 2 ++ Zend/zend_execute.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/NEWS b/NEWS index 01235592d04..75cf4703756 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - Core: . Fixed bug #81068 (Double free in realpath_cache_clean()). (Dimitry Andric) . Fixed bug #76359 (open_basedir bypass through adding ".."). (cmb) + . Fixed bug #81090 (Typed property performance degradation with .= operator). + (Nikita) - Standard: . Fixed bug #81048 (phpinfo(INFO_VARIABLES) "Array to string conversion"). diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index fb4675b2f2a..0c9a85bff50 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1354,6 +1354,13 @@ static zend_never_inline void zend_binary_assign_op_typed_ref(zend_reference *re { zval z_copy; + /* Make sure that in-place concatenation is used if the LHS is a string. */ + if (opline->extended_value == ZEND_CONCAT && Z_TYPE(ref->val) == IS_STRING) { + concat_function(&ref->val, &ref->val, value); + ZEND_ASSERT(Z_TYPE(ref->val) == IS_STRING && "Concat should return string"); + return; + } + zend_binary_op(&z_copy, &ref->val, value OPLINE_CC); if (EXPECTED(zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()))) { zval_ptr_dtor(&ref->val); @@ -1367,6 +1374,13 @@ static zend_never_inline void zend_binary_assign_op_typed_prop(zend_property_inf { zval z_copy; + /* Make sure that in-place concatenation is used if the LHS is a string. */ + if (opline->extended_value == ZEND_CONCAT && Z_TYPE_P(zptr) == IS_STRING) { + concat_function(zptr, zptr, value); + ZEND_ASSERT(Z_TYPE_P(zptr) == IS_STRING && "Concat should return string"); + return; + } + zend_binary_op(&z_copy, zptr, value OPLINE_CC); if (EXPECTED(zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) { zval_ptr_dtor(zptr);