@@ -108,6 +108,7 @@ ZEND_API bool zend_verify_internal_return_type(zend_function *zf, zval *ret);
108108ZEND_API void ZEND_FASTCALL zend_ref_add_type_source (zend_property_info_source_list * source_list , zend_property_info * prop );
109109ZEND_API void ZEND_FASTCALL zend_ref_del_type_source (zend_property_info_source_list * source_list , zend_property_info * prop );
110110
111+ ZEND_API zval * zend_assign_to_typed_ref_and_result (zval * variable_ptr , zval * orig_value , zend_uchar value_type , bool strict , zval * result_variable_ptr );
111112ZEND_API zval * zend_assign_to_typed_ref (zval * variable_ptr , zval * value , zend_uchar value_type , bool strict );
112113
113114static zend_always_inline void zend_copy_to_variable (zval * variable_ptr , zval * value , zend_uchar value_type )
@@ -137,12 +138,22 @@ static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *v
137138 }
138139}
139140
141+ static zend_always_inline void zend_handle_garbage_from_variable_assignment (zend_refcounted * garbage )
142+ {
143+ if (GC_DELREF (garbage ) == 0 ) {
144+ rc_dtor_func (garbage );
145+ } else { /* we need to split */
146+ /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
147+ if (UNEXPECTED (GC_MAY_LEAK (garbage ))) {
148+ gc_possible_root (garbage );
149+ }
150+ }
151+ }
152+
140153static zend_always_inline zval * zend_assign_to_variable (zval * variable_ptr , zval * value , zend_uchar value_type , bool strict )
141154{
142155 do {
143156 if (UNEXPECTED (Z_REFCOUNTED_P (variable_ptr ))) {
144- zend_refcounted * garbage ;
145-
146157 if (Z_ISREF_P (variable_ptr )) {
147158 if (UNEXPECTED (ZEND_REF_HAS_TYPE_SOURCES (Z_REF_P (variable_ptr )))) {
148159 return zend_assign_to_typed_ref (variable_ptr , value , value_type , strict );
@@ -153,21 +164,42 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval
153164 break ;
154165 }
155166 }
156- garbage = Z_COUNTED_P (variable_ptr );
167+ zend_refcounted * garbage = Z_COUNTED_P (variable_ptr );
157168 zend_copy_to_variable (variable_ptr , value , value_type );
158- if (GC_DELREF (garbage ) == 0 ) {
159- rc_dtor_func (garbage );
160- } else { /* we need to split */
161- /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
162- if (UNEXPECTED (GC_MAY_LEAK (garbage ))) {
163- gc_possible_root (garbage );
169+ zend_handle_garbage_from_variable_assignment (garbage );
170+ return variable_ptr ;
171+ }
172+ } while (0 );
173+
174+ zend_copy_to_variable (variable_ptr , value , value_type );
175+ return variable_ptr ;
176+ }
177+
178+ static zend_always_inline zval * zend_assign_to_two_variables (zval * result_variable_ptr , zval * variable_ptr , zval * value , zend_uchar value_type , bool strict )
179+ {
180+ do {
181+ if (UNEXPECTED (Z_REFCOUNTED_P (variable_ptr ))) {
182+ if (Z_ISREF_P (variable_ptr )) {
183+ if (UNEXPECTED (ZEND_REF_HAS_TYPE_SOURCES (Z_REF_P (variable_ptr )))) {
184+ variable_ptr = zend_assign_to_typed_ref_and_result (variable_ptr , value , value_type , strict , result_variable_ptr );
185+ return variable_ptr ;
186+ }
187+
188+ variable_ptr = Z_REFVAL_P (variable_ptr );
189+ if (EXPECTED (!Z_REFCOUNTED_P (variable_ptr ))) {
190+ break ;
164191 }
165192 }
193+ zend_refcounted * garbage = Z_COUNTED_P (variable_ptr );
194+ zend_copy_to_variable (variable_ptr , value , value_type );
195+ ZVAL_COPY (result_variable_ptr , variable_ptr );
196+ zend_handle_garbage_from_variable_assignment (garbage );
166197 return variable_ptr ;
167198 }
168199 } while (0 );
169200
170201 zend_copy_to_variable (variable_ptr , value , value_type );
202+ ZVAL_COPY (result_variable_ptr , variable_ptr );
171203 return variable_ptr ;
172204}
173205
0 commit comments