@@ -1122,6 +1122,16 @@ match_init_copy(VALUE obj, VALUE orig)
1122
1122
RB_OBJ_WRITE (obj , & RMATCH (obj )-> regexp , RMATCH (orig )-> regexp );
1123
1123
1124
1124
rm = RMATCH_EXT (obj );
1125
+
1126
+ #if USE_MMTK
1127
+ if (rb_mmtk_enabled_p ()) {
1128
+ // The rb_reg_region_copy below may write to `obj` (`rm->registers.{beg,end}`).
1129
+ // We apply write barrier here. It's probably not necessary because the `RB_OBJ_WRITE`
1130
+ // above executes the same object-remembering operation.
1131
+ rb_gc_writebarrier_remember (obj );
1132
+ }
1133
+ #endif
1134
+
1125
1135
if (rb_reg_region_copy (& rm -> regs , RMATCH_REGS (orig )))
1126
1136
rb_memerror ();
1127
1137
@@ -1501,6 +1511,15 @@ match_set_string(VALUE m, VALUE string, long pos, long len)
1501
1511
1502
1512
RB_OBJ_WRITE (match , & RMATCH (match )-> str , string );
1503
1513
RB_OBJ_WRITE (match , & RMATCH (match )-> regexp , Qnil );
1514
+
1515
+ #if USE_MMTK
1516
+ if (rb_mmtk_enabled_p ()) {
1517
+ // The onig_region_resize below may write to `m` (`rmatch->registers.{beg,end}`).
1518
+ // We apply write barrier here. It's probably not necessary because the `RB_OBJ_WRITE`
1519
+ // above executes the same object-remembering operation.
1520
+ rb_gc_writebarrier_remember (m );
1521
+ }
1522
+ #endif
1504
1523
int err = onig_region_resize (& rmatch -> regs , 1 );
1505
1524
if (err ) rb_memerror ();
1506
1525
rmatch -> regs .beg [0 ] = pos ;
@@ -1825,10 +1844,35 @@ rb_reg_search_set_match(VALUE re, VALUE str, long pos, int reverse, int set_back
1825
1844
return ONIG_MISMATCH ;
1826
1845
}
1827
1846
1847
+ #if USE_MMTK
1848
+ VALUE root_beg ;
1849
+ VALUE root_end ;
1850
+ if (rb_mmtk_enabled_p ()) {
1851
+ // When using MMTk, the `beg` and `end` fields of `re_registers` point to heap objects,
1852
+ // but are interior pointers. The conservative stack scanner will not recognize interior
1853
+ // pointers as object references. We compute the pointers to the beginning of those
1854
+ // objects and use RB_GC_GUARD to keep them on the stack so that even if the `match_alloc`
1855
+ // invocation triggers GC, the `beg` and `end` will still be kept alive.
1856
+ root_beg = (VALUE )rb_mmtk_chars_to_strbuf ((char * )args .regs .beg );
1857
+ root_end = (VALUE )rb_mmtk_chars_to_strbuf ((char * )args .regs .end );
1858
+ } else {
1859
+ root_beg = root_end = Qnil ;
1860
+ }
1861
+ #endif
1862
+
1863
+ // MMTk note: `match_alloc` may trigger GC.
1828
1864
VALUE match = match_alloc (rb_cMatch );
1829
1865
rb_matchext_t * rm = RMATCH_EXT (match );
1830
1866
rm -> regs = args .regs ;
1831
1867
1868
+ #if USE_MMTK
1869
+ // Guard `root_beg` and `root_end` until here. Now that `args.regs` has been assigned to a
1870
+ // field of `match`, the conservative stack scanner will pick up the `match` variable, and
1871
+ // `gc_mark_children` will take care of the interior pointers when scanning the `T_MATCH`.
1872
+ RB_GC_GUARD (root_beg );
1873
+ RB_GC_GUARD (root_end );
1874
+ #endif
1875
+
1832
1876
if (set_backref_str ) {
1833
1877
RB_OBJ_WRITE (match , & RMATCH (match )-> str , rb_str_new4 (str ));
1834
1878
}
0 commit comments