@@ -108,6 +108,7 @@ ZEND_API bool zend_verify_internal_return_type(zend_function *zf, zval *ret);
108
108
ZEND_API void ZEND_FASTCALL zend_ref_add_type_source (zend_property_info_source_list * source_list , zend_property_info * prop );
109
109
ZEND_API void ZEND_FASTCALL zend_ref_del_type_source (zend_property_info_source_list * source_list , zend_property_info * prop );
110
110
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 );
111
112
ZEND_API zval * zend_assign_to_typed_ref (zval * variable_ptr , zval * value , zend_uchar value_type , bool strict );
112
113
113
114
static 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
137
138
}
138
139
}
139
140
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
+
140
153
static zend_always_inline zval * zend_assign_to_variable (zval * variable_ptr , zval * value , zend_uchar value_type , bool strict )
141
154
{
142
155
do {
143
156
if (UNEXPECTED (Z_REFCOUNTED_P (variable_ptr ))) {
144
- zend_refcounted * garbage ;
145
-
146
157
if (Z_ISREF_P (variable_ptr )) {
147
158
if (UNEXPECTED (ZEND_REF_HAS_TYPE_SOURCES (Z_REF_P (variable_ptr )))) {
148
159
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
153
164
break ;
154
165
}
155
166
}
156
- garbage = Z_COUNTED_P (variable_ptr );
167
+ zend_refcounted * garbage = Z_COUNTED_P (variable_ptr );
157
168
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 ;
164
191
}
165
192
}
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 );
166
197
return variable_ptr ;
167
198
}
168
199
} while (0 );
169
200
170
201
zend_copy_to_variable (variable_ptr , value , value_type );
202
+ ZVAL_COPY (result_variable_ptr , variable_ptr );
171
203
return variable_ptr ;
172
204
}
173
205
0 commit comments