@@ -152,12 +152,6 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
152
152
OBJ_RELEASE (ZEND_CLOSURE_OBJECT (EX (func )));
153
153
}
154
154
155
- /* Free GC buffer. GC for closed generators doesn't need an allocated buffer */
156
- if (generator -> gc_buffer ) {
157
- efree (generator -> gc_buffer );
158
- generator -> gc_buffer = NULL ;
159
- }
160
-
161
155
efree (execute_data );
162
156
}
163
157
}
@@ -279,63 +273,11 @@ static void zend_generator_free_storage(zend_object *object) /* {{{ */
279
273
}
280
274
/* }}} */
281
275
282
- static uint32_t calc_gc_buffer_size (zend_generator * generator ) /* {{{ */
283
- {
284
- uint32_t size = 4 ; /* value, key, retval, values */
285
- if (generator -> execute_data ) {
286
- zend_execute_data * execute_data = generator -> execute_data ;
287
- zend_op_array * op_array = & EX (func )-> op_array ;
288
-
289
- /* Compiled variables */
290
- if (!(EX_CALL_INFO () & ZEND_CALL_HAS_SYMBOL_TABLE )) {
291
- size += op_array -> last_var ;
292
- }
293
- /* Extra args */
294
- if (EX_CALL_INFO () & ZEND_CALL_FREE_EXTRA_ARGS ) {
295
- size += EX_NUM_ARGS () - op_array -> num_args ;
296
- }
297
- size += (EX_CALL_INFO () & ZEND_CALL_RELEASE_THIS ) != 0 ; /* $this */
298
- size += (EX_CALL_INFO () & ZEND_CALL_CLOSURE ) != 0 ; /* Closure object */
299
-
300
- /* Live vars */
301
- if (execute_data -> opline != op_array -> opcodes ) {
302
- /* -1 required because we want the last run opcode, not the next to-be-run one. */
303
- uint32_t i , op_num = execute_data -> opline - op_array -> opcodes - 1 ;
304
- for (i = 0 ; i < op_array -> last_live_range ; i ++ ) {
305
- const zend_live_range * range = & op_array -> live_range [i ];
306
- if (range -> start > op_num ) {
307
- /* Further ranges will not be relevant... */
308
- break ;
309
- } else if (op_num < range -> end ) {
310
- /* LIVE_ROPE and LIVE_SILENCE not relevant for GC */
311
- uint32_t kind = range -> var & ZEND_LIVE_MASK ;
312
- if (kind == ZEND_LIVE_TMPVAR || kind == ZEND_LIVE_LOOP ) {
313
- size ++ ;
314
- }
315
- }
316
- }
317
- }
318
-
319
- /* Yield from root references */
320
- if (generator -> node .children == 0 ) {
321
- zend_generator * root = generator -> node .ptr .root ;
322
- while (root != generator ) {
323
- root = zend_generator_get_child (& root -> node , generator );
324
- size ++ ;
325
- }
326
- }
327
- }
328
- return size ;
329
- }
330
- /* }}} */
331
-
332
276
static HashTable * zend_generator_get_gc (zend_object * object , zval * * table , int * n ) /* {{{ */
333
277
{
334
278
zend_generator * generator = (zend_generator * )object ;
335
279
zend_execute_data * execute_data = generator -> execute_data ;
336
280
zend_op_array * op_array ;
337
- zval * gc_buffer ;
338
- uint32_t gc_buffer_size ;
339
281
340
282
if (!execute_data ) {
341
283
/* If the generator has been closed, it can only hold on to three values: The value, key
@@ -346,40 +288,33 @@ static HashTable *zend_generator_get_gc(zend_object *object, zval **table, int *
346
288
}
347
289
348
290
op_array = & EX (func )-> op_array ;
349
- gc_buffer_size = calc_gc_buffer_size (generator );
350
- if (generator -> gc_buffer_size < gc_buffer_size ) {
351
- generator -> gc_buffer = safe_erealloc (generator -> gc_buffer , sizeof (zval ), gc_buffer_size , 0 );
352
- generator -> gc_buffer_size = gc_buffer_size ;
353
- }
354
-
355
- * n = gc_buffer_size ;
356
- * table = gc_buffer = generator -> gc_buffer ;
357
291
358
- ZVAL_COPY_VALUE (gc_buffer ++ , & generator -> value );
359
- ZVAL_COPY_VALUE (gc_buffer ++ , & generator -> key );
360
- ZVAL_COPY_VALUE (gc_buffer ++ , & generator -> retval );
361
- ZVAL_COPY_VALUE (gc_buffer ++ , & generator -> values );
292
+ zend_get_gc_buffer * gc_buffer = zend_get_gc_buffer_create ();
293
+ zend_get_gc_buffer_add_zval (gc_buffer , & generator -> value );
294
+ zend_get_gc_buffer_add_zval (gc_buffer , & generator -> key );
295
+ zend_get_gc_buffer_add_zval (gc_buffer , & generator -> retval );
296
+ zend_get_gc_buffer_add_zval (gc_buffer , & generator -> values );
362
297
363
298
if (!(EX_CALL_INFO () & ZEND_CALL_HAS_SYMBOL_TABLE )) {
364
299
uint32_t i , num_cvs = EX (func )-> op_array .last_var ;
365
300
for (i = 0 ; i < num_cvs ; i ++ ) {
366
- ZVAL_COPY_VALUE (gc_buffer ++ , EX_VAR_NUM (i ));
301
+ zend_get_gc_buffer_add_zval (gc_buffer , EX_VAR_NUM (i ));
367
302
}
368
303
}
369
304
370
305
if (EX_CALL_INFO () & ZEND_CALL_FREE_EXTRA_ARGS ) {
371
306
zval * zv = EX_VAR_NUM (op_array -> last_var + op_array -> T );
372
307
zval * end = zv + (EX_NUM_ARGS () - op_array -> num_args );
373
308
while (zv != end ) {
374
- ZVAL_COPY_VALUE (gc_buffer ++ , zv ++ );
309
+ zend_get_gc_buffer_add_zval (gc_buffer , zv ++ );
375
310
}
376
311
}
377
312
378
313
if (EX_CALL_INFO () & ZEND_CALL_RELEASE_THIS ) {
379
- ZVAL_OBJ (gc_buffer ++ , Z_OBJ (execute_data -> This ));
314
+ zend_get_gc_buffer_add_obj (gc_buffer , Z_OBJ (execute_data -> This ));
380
315
}
381
316
if (EX_CALL_INFO () & ZEND_CALL_CLOSURE ) {
382
- ZVAL_OBJ (gc_buffer ++ , ZEND_CLOSURE_OBJECT (EX (func )));
317
+ zend_get_gc_buffer_add_obj (gc_buffer , ZEND_CLOSURE_OBJECT (EX (func )));
383
318
}
384
319
385
320
if (execute_data -> opline != op_array -> opcodes ) {
@@ -393,7 +328,7 @@ static HashTable *zend_generator_get_gc(zend_object *object, zval **table, int *
393
328
uint32_t var_num = range -> var & ~ZEND_LIVE_MASK ;
394
329
zval * var = EX_VAR (var_num );
395
330
if (kind == ZEND_LIVE_TMPVAR || kind == ZEND_LIVE_LOOP ) {
396
- ZVAL_COPY_VALUE (gc_buffer ++ , var );
331
+ zend_get_gc_buffer_add_zval (gc_buffer , var );
397
332
}
398
333
}
399
334
}
@@ -402,11 +337,12 @@ static HashTable *zend_generator_get_gc(zend_object *object, zval **table, int *
402
337
if (generator -> node .children == 0 ) {
403
338
zend_generator * root = generator -> node .ptr .root ;
404
339
while (root != generator ) {
405
- ZVAL_OBJ (gc_buffer ++ , & root -> std );
340
+ zend_get_gc_buffer_add_obj (gc_buffer , & root -> std );
406
341
root = zend_generator_get_child (& root -> node , generator );
407
342
}
408
343
}
409
344
345
+ zend_get_gc_buffer_use (gc_buffer , table , n );
410
346
if (EX_CALL_INFO () & ZEND_CALL_HAS_SYMBOL_TABLE ) {
411
347
return execute_data -> symbol_table ;
412
348
} else {
0 commit comments