@@ -420,6 +420,26 @@ rb_objspace_alloc(void)
420
420
421
421
static void initial_expand_heap (rb_objspace_t * objspace );
422
422
423
+
424
+ typedef struct mark_queue_node_struct mark_queue_node_t ;
425
+ struct mark_queue_node_struct {
426
+ rb_objspace_t * objspace ;
427
+ VALUE ptr ;
428
+ int lev ;
429
+ mark_queue_node_t * next ;
430
+ };
431
+
432
+ typedef struct mark_queue_struct {
433
+ mark_queue_node_t * head ;
434
+ mark_queue_node_t * tail ;
435
+ unsigned int size ;
436
+ } mark_queue_t ;
437
+
438
+ mark_queue_t mark_queue = {NULL , NULL , 0 };
439
+
440
+ void gc_mark_defer (rb_objspace_t * objspace , VALUE ptr , int lev );
441
+ int gc_mark_pop ();
442
+
423
443
void
424
444
rb_gc_set_params (void )
425
445
{
@@ -1419,7 +1439,7 @@ mark_locations_array(rb_objspace_t *objspace, register VALUE *x, register long n
1419
1439
v = * x ;
1420
1440
VALGRIND_MAKE_MEM_DEFINED (& v , sizeof (v ));
1421
1441
if (is_pointer_to_heap (objspace , (void * )v )) {
1422
- gc_mark (objspace , v , 0 );
1442
+ gc_mark_defer (objspace , v , 0 );
1423
1443
}
1424
1444
x ++ ;
1425
1445
}
@@ -1452,7 +1472,7 @@ static int
1452
1472
mark_entry (ID key , VALUE value , st_data_t data )
1453
1473
{
1454
1474
struct mark_tbl_arg * arg = (void * )data ;
1455
- gc_mark (arg -> objspace , value , arg -> lev );
1475
+ gc_mark_defer (arg -> objspace , value , arg -> lev );
1456
1476
return ST_CONTINUE ;
1457
1477
}
1458
1478
@@ -1470,7 +1490,7 @@ static int
1470
1490
mark_key (VALUE key , VALUE value , st_data_t data )
1471
1491
{
1472
1492
struct mark_tbl_arg * arg = (void * )data ;
1473
- gc_mark (arg -> objspace , key , arg -> lev );
1493
+ gc_mark_defer (arg -> objspace , key , arg -> lev );
1474
1494
return ST_CONTINUE ;
1475
1495
}
1476
1496
@@ -1494,8 +1514,8 @@ static int
1494
1514
mark_keyvalue (VALUE key , VALUE value , st_data_t data )
1495
1515
{
1496
1516
struct mark_tbl_arg * arg = (void * )data ;
1497
- gc_mark (arg -> objspace , key , arg -> lev );
1498
- gc_mark (arg -> objspace , value , arg -> lev );
1517
+ gc_mark_defer (arg -> objspace , key , arg -> lev );
1518
+ gc_mark_defer (arg -> objspace , value , arg -> lev );
1499
1519
return ST_CONTINUE ;
1500
1520
}
1501
1521
@@ -1520,18 +1540,18 @@ mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me, int lev)
1520
1540
{
1521
1541
const rb_method_definition_t * def = me -> def ;
1522
1542
1523
- gc_mark (objspace , me -> klass , lev );
1543
+ gc_mark_defer (objspace , me -> klass , lev );
1524
1544
if (!def ) return ;
1525
1545
switch (def -> type ) {
1526
1546
case VM_METHOD_TYPE_ISEQ :
1527
- gc_mark (objspace , def -> body .iseq -> self , lev );
1547
+ gc_mark_defer (objspace , def -> body .iseq -> self , lev );
1528
1548
break ;
1529
1549
case VM_METHOD_TYPE_BMETHOD :
1530
- gc_mark (objspace , def -> body .proc , lev );
1550
+ gc_mark_defer (objspace , def -> body .proc , lev );
1531
1551
break ;
1532
1552
case VM_METHOD_TYPE_ATTRSET :
1533
1553
case VM_METHOD_TYPE_IVAR :
1534
- gc_mark (objspace , def -> body .attr .location , lev );
1554
+ gc_mark_defer (objspace , def -> body .attr .location , lev );
1535
1555
break ;
1536
1556
default :
1537
1557
break ; /* ignore */
@@ -1580,7 +1600,7 @@ static int
1580
1600
mark_const_entry_i (ID key , const rb_const_entry_t * ce , st_data_t data )
1581
1601
{
1582
1602
struct mark_tbl_arg * arg = (void * )data ;
1583
- gc_mark (arg -> objspace , ce -> value , arg -> lev );
1603
+ gc_mark_defer (arg -> objspace , ce -> value , arg -> lev );
1584
1604
return ST_CONTINUE ;
1585
1605
}
1586
1606
@@ -1618,7 +1638,7 @@ void
1618
1638
rb_gc_mark_maybe (VALUE obj )
1619
1639
{
1620
1640
if (is_pointer_to_heap (& rb_objspace , (void * )obj )) {
1621
- gc_mark (& rb_objspace , obj , 0 );
1641
+ gc_mark_defer (& rb_objspace , obj , 0 );
1622
1642
}
1623
1643
}
1624
1644
@@ -1649,6 +1669,45 @@ gc_mark(rb_objspace_t *objspace, VALUE ptr, int lev)
1649
1669
gc_mark_children (objspace , ptr , lev + 1 );
1650
1670
}
1651
1671
1672
+ void
1673
+ gc_mark_defer (rb_objspace_t * objspace , VALUE ptr , int lev ) {
1674
+ mark_queue_node_t * node =
1675
+ (mark_queue_node_t * ) malloc (sizeof (mark_queue_node_t ));
1676
+ node -> objspace = objspace ;
1677
+ node -> ptr = ptr ;
1678
+ node -> lev = lev ;
1679
+ node -> next = NULL ;
1680
+ //lock
1681
+ if (mark_queue .tail == NULL ) {
1682
+ mark_queue .head = mark_queue .tail = node ;
1683
+ } else {
1684
+ mark_queue .tail -> next = node ;
1685
+ mark_queue .tail = node ;
1686
+ }
1687
+ mark_queue .size ++ ;
1688
+ //unlock
1689
+ }
1690
+
1691
+ int
1692
+ gc_mark_pop () {
1693
+ mark_queue_node_t * node ;
1694
+ //lock
1695
+ node = mark_queue .head ;
1696
+ if (node != NULL ) {
1697
+ mark_queue .head = node -> next ;
1698
+ if (mark_queue .head == NULL ) {
1699
+ mark_queue .tail = NULL ;
1700
+ }
1701
+ mark_queue .size -- ;
1702
+ }
1703
+ //unlock
1704
+ if (node != NULL ) {
1705
+ gc_mark (node -> objspace , node -> ptr , node -> lev );
1706
+ free (node );
1707
+ }
1708
+ return node != NULL ;
1709
+ }
1710
+
1652
1711
void
1653
1712
rb_gc_mark (VALUE ptr )
1654
1713
{
@@ -1692,7 +1751,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
1692
1751
case NODE_RESBODY :
1693
1752
case NODE_CLASS :
1694
1753
case NODE_BLOCK_PASS :
1695
- gc_mark (objspace , (VALUE )obj -> as .node .u2 .node , lev );
1754
+ gc_mark_defer (objspace , (VALUE )obj -> as .node .u2 .node , lev );
1696
1755
/* fall through */
1697
1756
case NODE_BLOCK : /* 1,3 */
1698
1757
case NODE_OPTBLOCK :
@@ -1706,7 +1765,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
1706
1765
case NODE_DEFS :
1707
1766
case NODE_OP_ASGN1 :
1708
1767
case NODE_ARGS :
1709
- gc_mark (objspace , (VALUE )obj -> as .node .u1 .node , lev );
1768
+ gc_mark_defer (objspace , (VALUE )obj -> as .node .u1 .node , lev );
1710
1769
/* fall through */
1711
1770
case NODE_SUPER : /* 3 */
1712
1771
case NODE_FCALL :
@@ -1733,7 +1792,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
1733
1792
case NODE_ALIAS :
1734
1793
case NODE_VALIAS :
1735
1794
case NODE_ARGSCAT :
1736
- gc_mark (objspace , (VALUE )obj -> as .node .u1 .node , lev );
1795
+ gc_mark_defer (objspace , (VALUE )obj -> as .node .u1 .node , lev );
1737
1796
/* fall through */
1738
1797
case NODE_GASGN : /* 2 */
1739
1798
case NODE_LASGN :
@@ -1769,7 +1828,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
1769
1828
case NODE_SCOPE : /* 2,3 */
1770
1829
case NODE_CDECL :
1771
1830
case NODE_OPT_ARG :
1772
- gc_mark (objspace , (VALUE )obj -> as .node .u3 .node , lev );
1831
+ gc_mark_defer (objspace , (VALUE )obj -> as .node .u3 .node , lev );
1773
1832
ptr = (VALUE )obj -> as .node .u2 .node ;
1774
1833
goto again ;
1775
1834
@@ -1801,19 +1860,19 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
1801
1860
1802
1861
default : /* unlisted NODE */
1803
1862
if (is_pointer_to_heap (objspace , obj -> as .node .u1 .node )) {
1804
- gc_mark (objspace , (VALUE )obj -> as .node .u1 .node , lev );
1863
+ gc_mark_defer (objspace , (VALUE )obj -> as .node .u1 .node , lev );
1805
1864
}
1806
1865
if (is_pointer_to_heap (objspace , obj -> as .node .u2 .node )) {
1807
- gc_mark (objspace , (VALUE )obj -> as .node .u2 .node , lev );
1866
+ gc_mark_defer (objspace , (VALUE )obj -> as .node .u2 .node , lev );
1808
1867
}
1809
1868
if (is_pointer_to_heap (objspace , obj -> as .node .u3 .node )) {
1810
- gc_mark (objspace , (VALUE )obj -> as .node .u3 .node , lev );
1869
+ gc_mark_defer (objspace , (VALUE )obj -> as .node .u3 .node , lev );
1811
1870
}
1812
1871
}
1813
1872
return ; /* no need to mark class. */
1814
1873
}
1815
1874
1816
- gc_mark (objspace , obj -> as .basic .klass , lev );
1875
+ gc_mark_defer (objspace , obj -> as .basic .klass , lev );
1817
1876
switch (BUILTIN_TYPE (obj )) {
1818
1877
case T_ICLASS :
1819
1878
case T_CLASS :
@@ -1833,7 +1892,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
1833
1892
long i , len = RARRAY_LEN (obj );
1834
1893
VALUE * ptr = RARRAY_PTR (obj );
1835
1894
for (i = 0 ; i < len ; i ++ ) {
1836
- gc_mark (objspace , * ptr ++ , lev );
1895
+ gc_mark_defer (objspace , * ptr ++ , lev );
1837
1896
}
1838
1897
}
1839
1898
break ;
@@ -1866,24 +1925,24 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
1866
1925
long i , len = ROBJECT_NUMIV (obj );
1867
1926
VALUE * ptr = ROBJECT_IVPTR (obj );
1868
1927
for (i = 0 ; i < len ; i ++ ) {
1869
- gc_mark (objspace , * ptr ++ , lev );
1928
+ gc_mark_defer (objspace , * ptr ++ , lev );
1870
1929
}
1871
1930
}
1872
1931
break ;
1873
1932
1874
1933
case T_FILE :
1875
1934
if (obj -> as .file .fptr ) {
1876
- gc_mark (objspace , obj -> as .file .fptr -> pathv , lev );
1877
- gc_mark (objspace , obj -> as .file .fptr -> tied_io_for_writing , lev );
1878
- gc_mark (objspace , obj -> as .file .fptr -> writeconv_asciicompat , lev );
1879
- gc_mark (objspace , obj -> as .file .fptr -> writeconv_pre_ecopts , lev );
1880
- gc_mark (objspace , obj -> as .file .fptr -> encs .ecopts , lev );
1881
- gc_mark (objspace , obj -> as .file .fptr -> write_lock , lev );
1935
+ gc_mark_defer (objspace , obj -> as .file .fptr -> pathv , lev );
1936
+ gc_mark_defer (objspace , obj -> as .file .fptr -> tied_io_for_writing , lev );
1937
+ gc_mark_defer (objspace , obj -> as .file .fptr -> writeconv_asciicompat , lev );
1938
+ gc_mark_defer (objspace , obj -> as .file .fptr -> writeconv_pre_ecopts , lev );
1939
+ gc_mark_defer (objspace , obj -> as .file .fptr -> encs .ecopts , lev );
1940
+ gc_mark_defer (objspace , obj -> as .file .fptr -> write_lock , lev );
1882
1941
}
1883
1942
break ;
1884
1943
1885
1944
case T_REGEXP :
1886
- gc_mark (objspace , obj -> as .regexp .src , lev );
1945
+ gc_mark_defer (objspace , obj -> as .regexp .src , lev );
1887
1946
break ;
1888
1947
1889
1948
case T_FLOAT :
@@ -1892,21 +1951,21 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
1892
1951
break ;
1893
1952
1894
1953
case T_MATCH :
1895
- gc_mark (objspace , obj -> as .match .regexp , lev );
1954
+ gc_mark_defer (objspace , obj -> as .match .regexp , lev );
1896
1955
if (obj -> as .match .str ) {
1897
1956
ptr = obj -> as .match .str ;
1898
1957
goto again ;
1899
1958
}
1900
1959
break ;
1901
1960
1902
1961
case T_RATIONAL :
1903
- gc_mark (objspace , obj -> as .rational .num , lev );
1904
- gc_mark (objspace , obj -> as .rational .den , lev );
1962
+ gc_mark_defer (objspace , obj -> as .rational .num , lev );
1963
+ gc_mark_defer (objspace , obj -> as .rational .den , lev );
1905
1964
break ;
1906
1965
1907
1966
case T_COMPLEX :
1908
- gc_mark (objspace , obj -> as .complex .real , lev );
1909
- gc_mark (objspace , obj -> as .complex .imag , lev );
1967
+ gc_mark_defer (objspace , obj -> as .complex .real , lev );
1968
+ gc_mark_defer (objspace , obj -> as .complex .imag , lev );
1910
1969
break ;
1911
1970
1912
1971
case T_STRUCT :
@@ -1915,7 +1974,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
1915
1974
VALUE * ptr = RSTRUCT_PTR (obj );
1916
1975
1917
1976
while (len -- ) {
1918
- gc_mark (objspace , * ptr ++ , lev );
1977
+ gc_mark_defer (objspace , * ptr ++ , lev );
1919
1978
}
1920
1979
}
1921
1980
break ;
@@ -2428,6 +2487,10 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_thread_t *th)
2428
2487
#endif
2429
2488
}
2430
2489
2490
+ static void gc_mark_loop () {
2491
+ while (gc_mark_pop ()){};
2492
+ }
2493
+
2431
2494
static void
2432
2495
gc_marks (rb_objspace_t * objspace )
2433
2496
{
@@ -2476,6 +2539,7 @@ gc_marks(rb_objspace_t *objspace)
2476
2539
gc_mark_rest (objspace );
2477
2540
}
2478
2541
}
2542
+ gc_mark_loop ();
2479
2543
GC_PROF_MARK_TIMER_STOP ;
2480
2544
}
2481
2545
0 commit comments