@@ -32,27 +32,38 @@ extern "C" {
32
32
zend_class_entry *IntlIterator_ce_ptr;
33
33
zend_object_handlers IntlIterator_handlers;
34
34
35
+ static void zoi_with_current_destroy_self (zend_object_iterator *iter, zoi_with_current *zoiwc)
36
+ {
37
+ /* Object not here anymore (we've been called by the object free handler)
38
+ * Note that the iterator wrapper objects (that also depend on this
39
+ * structure) call this function earlier, in the destruction phase, which
40
+ * precedes the object free phase. Therefore there's no risk on this
41
+ * function being called by the iterator wrapper destructor function and
42
+ * not finding the memory of this iterator allocated anymore. */
43
+ iter->funcs ->invalidate_current (iter);
44
+ zoiwc->destroy_it (iter);
45
+ }
46
+
35
47
void zoi_with_current_dtor (zend_object_iterator *iter)
36
48
{
37
49
zoi_with_current *zoiwc = (zoi_with_current*)iter;
38
50
39
51
if (!Z_ISUNDEF (zoiwc->wrapping_obj )) {
40
52
/* we have to copy the pointer because zoiwc->wrapping_obj may be
41
- * changed midway the execution of zval_ptr_dtor() */
53
+ * changed midway the execution of zval_ptr_dtor() */
42
54
zval *zwo = &zoiwc->wrapping_obj ;
43
55
44
56
/* object is still here, we can rely on it to call this again and
45
57
* destroy this object */
46
58
zval_ptr_dtor (zwo);
59
+
60
+ /* We may only invalidate and destroy if this was actually the last instance.
61
+ * If it was, then IntlIterator_objects_free() will have set zwo to UNDEF. */
62
+ if (Z_ISUNDEF_P (zwo)) {
63
+ zoi_with_current_destroy_self (iter, zoiwc);
64
+ }
47
65
} else {
48
- /* Object not here anymore (we've been called by the object free handler)
49
- * Note that the iterator wrapper objects (that also depend on this
50
- * structure) call this function earlier, in the destruction phase, which
51
- * precedes the object free phase. Therefore there's no risk on this
52
- * function being called by the iterator wrapper destructor function and
53
- * not finding the memory of this iterator allocated anymore. */
54
- iter->funcs ->invalidate_current (iter);
55
- zoiwc->destroy_it (iter);
66
+ zoi_with_current_destroy_self (iter, zoiwc);
56
67
}
57
68
}
58
69
@@ -126,6 +137,16 @@ static void string_enum_destroy_it(zend_object_iterator *iter)
126
137
delete (StringEnumeration*)Z_PTR (iter->data );
127
138
}
128
139
140
+ static HashTable *string_enum_get_gc (zend_object_iterator *object, zval **table, int *n)
141
+ {
142
+ zoi_with_current *zoiwc = (zoi_with_current *) object;
143
+
144
+ *table = &zoiwc->wrapping_obj ;
145
+ *n = 1 ;
146
+
147
+ return NULL ;
148
+ }
149
+
129
150
static const zend_object_iterator_funcs string_enum_object_iterator_funcs = {
130
151
zoi_with_current_dtor,
131
152
zoi_with_current_valid,
@@ -134,7 +155,7 @@ static const zend_object_iterator_funcs string_enum_object_iterator_funcs = {
134
155
string_enum_current_move_forward,
135
156
string_enum_rewind,
136
157
zoi_with_current_invalidate_current,
137
- NULL , /* get_gc */
158
+ string_enum_get_gc,
138
159
};
139
160
140
161
U_CFUNC void IntlIterator_from_StringEnumeration (StringEnumeration *se, zval *object)
@@ -148,7 +169,8 @@ U_CFUNC void IntlIterator_from_StringEnumeration(StringEnumeration *se, zval *ob
148
169
ii->iterator ->funcs = &string_enum_object_iterator_funcs;
149
170
ii->iterator ->index = 0 ;
150
171
((zoi_with_current*)ii->iterator )->destroy_it = string_enum_destroy_it;
151
- ZVAL_OBJ (&((zoi_with_current*)ii->iterator )->wrapping_obj , Z_OBJ_P (object));
172
+ /* This iterator holds a reference to the object, the object may not disappear */
173
+ ZVAL_OBJ_COPY (&((zoi_with_current*)ii->iterator )->wrapping_obj , Z_OBJ_P (object));
152
174
ZVAL_UNDEF (&((zoi_with_current*)ii->iterator )->current );
153
175
}
154
176
@@ -158,6 +180,7 @@ static void IntlIterator_objects_free(zend_object *object)
158
180
159
181
if (ii->iterator ) {
160
182
zval *wrapping_objp = &((zoi_with_current*)ii->iterator )->wrapping_obj ;
183
+ /* Signal that it was the last reference that got destroyed */
161
184
ZVAL_UNDEF (wrapping_objp);
162
185
zend_iterator_dtor (ii->iterator );
163
186
}
@@ -166,6 +189,22 @@ static void IntlIterator_objects_free(zend_object *object)
166
189
zend_object_std_dtor (&ii->zo );
167
190
}
168
191
192
+ static HashTable *IntlIterator_get_gc (zend_object *object, zval **table, int *n)
193
+ {
194
+ IntlIterator_object *ii = php_intl_iterator_fetch_object (object);
195
+
196
+ if (ii->iterator ) {
197
+ zend_get_gc_buffer *gc = zend_get_gc_buffer_create ();
198
+ zend_get_gc_buffer_add_obj (gc, &ii->iterator ->std );
199
+ zend_get_gc_buffer_use (gc, table, n);
200
+ } else {
201
+ *table = NULL ;
202
+ *n = 0 ;
203
+ }
204
+
205
+ return NULL ;
206
+ }
207
+
169
208
static zend_object_iterator *IntlIterator_get_iterator (
170
209
zend_class_entry *ce, zval *object, int by_ref)
171
210
{
@@ -293,6 +332,7 @@ U_CFUNC void intl_register_common_symbols(int module_number)
293
332
IntlIterator_handlers.offset = XtOffsetOf (IntlIterator_object, zo);
294
333
IntlIterator_handlers.clone_obj = NULL ;
295
334
IntlIterator_handlers.free_obj = IntlIterator_objects_free;
335
+ IntlIterator_handlers.get_gc = IntlIterator_get_gc;
296
336
297
337
register_common_symbols (module_number);
298
338
}
0 commit comments