@@ -1328,14 +1328,14 @@ static int gc_collect_roots(uint32_t *flags, gc_stack *stack)
1328
1328
return count ;
1329
1329
}
1330
1330
1331
- static int gc_remove_nested_data_from_buffer (zend_refcounted * ref , gc_root_buffer * root )
1331
+ static int gc_remove_nested_data_from_buffer (zend_refcounted * ref , gc_root_buffer * root , gc_stack * stack )
1332
1332
{
1333
1333
HashTable * ht = NULL ;
1334
1334
Bucket * p , * end ;
1335
1335
zval * zv ;
1336
1336
int count = 0 ;
1337
+ GC_STACK_DCL (stack );
1337
1338
1338
- tail_call :
1339
1339
do {
1340
1340
if (root ) {
1341
1341
root = NULL ;
@@ -1348,11 +1348,11 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe
1348
1348
} else if (GC_TYPE (ref ) == IS_REFERENCE ) {
1349
1349
if (Z_REFCOUNTED (((zend_reference * )ref )-> val )) {
1350
1350
ref = Z_COUNTED (((zend_reference * )ref )-> val );
1351
- goto tail_call ;
1351
+ continue ;
1352
1352
}
1353
- return count ;
1353
+ goto next ;
1354
1354
} else {
1355
- return count ;
1355
+ goto next ;
1356
1356
}
1357
1357
1358
1358
if (GC_TYPE (ref ) == IS_OBJECT ) {
@@ -1364,10 +1364,10 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe
1364
1364
1365
1365
ht = obj -> handlers -> get_gc (obj , & zv , & n );
1366
1366
if (EXPECTED (!ht )) {
1367
- if (!n ) return count ;
1367
+ if (!n ) goto next ;
1368
1368
end = zv + n ;
1369
1369
while (!Z_REFCOUNTED_P (-- end )) {
1370
- if (zv == end ) return count ;
1370
+ if (zv == end ) goto next ;
1371
1371
}
1372
1372
} else {
1373
1373
if (!n ) goto handle_ht ;
@@ -1376,29 +1376,29 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe
1376
1376
while (zv != end ) {
1377
1377
if (Z_REFCOUNTED_P (zv )) {
1378
1378
ref = Z_COUNTED_P (zv );
1379
- count += gc_remove_nested_data_from_buffer (ref , NULL );
1379
+ GC_STACK_PUSH (ref );
1380
1380
}
1381
1381
zv ++ ;
1382
1382
}
1383
1383
if (EXPECTED (!ht )) {
1384
1384
ref = Z_COUNTED_P (zv );
1385
- goto tail_call ;
1385
+ continue ;
1386
1386
}
1387
1387
handle_ht :
1388
1388
if (GC_REF_ADDRESS (ht ) != 0 && GC_REF_CHECK_COLOR (ht , GC_BLACK )) {
1389
1389
GC_TRACE_REF (ht , "removing from buffer" );
1390
1390
GC_REMOVE_FROM_BUFFER (ht );
1391
1391
}
1392
1392
} else {
1393
- return count ;
1393
+ goto next ;
1394
1394
}
1395
1395
} else if (GC_TYPE (ref ) == IS_ARRAY ) {
1396
1396
ht = (zend_array * )ref ;
1397
1397
} else {
1398
- return count ;
1398
+ goto next ;
1399
1399
}
1400
1400
1401
- if (!ht -> nNumUsed ) return count ;
1401
+ if (!ht -> nNumUsed ) goto next ;
1402
1402
p = ht -> arData ;
1403
1403
end = p + ht -> nNumUsed ;
1404
1404
while (1 ) {
@@ -1410,7 +1410,7 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe
1410
1410
if (Z_REFCOUNTED_P (zv )) {
1411
1411
break ;
1412
1412
}
1413
- if (p == end ) return count ;
1413
+ if (p == end ) goto next ;
1414
1414
}
1415
1415
while (p != end ) {
1416
1416
zv = & p -> val ;
@@ -1419,7 +1419,7 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe
1419
1419
}
1420
1420
if (Z_REFCOUNTED_P (zv )) {
1421
1421
ref = Z_COUNTED_P (zv );
1422
- count += gc_remove_nested_data_from_buffer (ref , NULL );
1422
+ GC_STACK_PUSH (ref );
1423
1423
}
1424
1424
p ++ ;
1425
1425
}
@@ -1428,8 +1428,12 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe
1428
1428
zv = Z_INDIRECT_P (zv );
1429
1429
}
1430
1430
ref = Z_COUNTED_P (zv );
1431
- goto tail_call ;
1432
- } while (0 );
1431
+ continue ;
1432
+
1433
+ next :
1434
+ ref = GC_STACK_POP ();
1435
+ } while (ref );
1436
+ return count ;
1433
1437
}
1434
1438
1435
1439
static void zend_get_gc_buffer_release ();
@@ -1464,11 +1468,10 @@ ZEND_API int zend_gc_collect_cycles(void)
1464
1468
GC_TRACE ("Collecting roots" );
1465
1469
count = gc_collect_roots (& gc_flags , & stack );
1466
1470
1467
- gc_stack_free (& stack );
1468
-
1469
1471
if (!GC_G (num_roots )) {
1470
1472
/* nothing to free */
1471
1473
GC_TRACE ("Nothing to free" );
1474
+ gc_stack_free (& stack );
1472
1475
zend_get_gc_buffer_release ();
1473
1476
GC_G (gc_active ) = 0 ;
1474
1477
return 0 ;
@@ -1518,7 +1521,7 @@ ZEND_API int zend_gc_collect_cycles(void)
1518
1521
while (idx != end ) {
1519
1522
if (GC_IS_DTOR_GARBAGE (current -> ref )) {
1520
1523
p = GC_GET_PTR (current -> ref );
1521
- count -= gc_remove_nested_data_from_buffer (p , current );
1524
+ count -= gc_remove_nested_data_from_buffer (p , current , & stack );
1522
1525
}
1523
1526
current ++ ;
1524
1527
idx ++ ;
@@ -1557,6 +1560,8 @@ ZEND_API int zend_gc_collect_cycles(void)
1557
1560
}
1558
1561
}
1559
1562
1563
+ gc_stack_free (& stack );
1564
+
1560
1565
/* Destroy zvals. The root buffer may be reallocated. */
1561
1566
GC_TRACE ("Destroying zvals" );
1562
1567
idx = GC_FIRST_ROOT ;
0 commit comments