@@ -274,6 +274,19 @@ static void Mark_Series(REBSER *series, REBCNT depth);
274
274
}
275
275
}
276
276
277
+ /***********************************************************************
278
+ **
279
+ */ static void Queue_Mark_Series (REBSER * series )
280
+ /*
281
+ ** Instead of directly marking all series, queue them for later
282
+ ** to avoid a stack overflow in case of deep recursion.
283
+ **
284
+ ***********************************************************************/
285
+ {
286
+ if (SERIES_FULL (GC_Mark_Queue )) Extend_Series (GC_Mark_Queue , 8 );
287
+ ((REBSER * * )GC_Mark_Queue -> data )[GC_Mark_Queue -> tail ++ ] = series ;
288
+ }
289
+
277
290
/***********************************************************************
278
291
**
279
292
*/ static void Mark_Series (REBSER * series , REBCNT depth )
@@ -371,9 +384,10 @@ static void Mark_Series(REBSER *series, REBCNT depth);
371
384
// Object is just a block with special first value (context):
372
385
mark_obj :
373
386
if (!IS_MARK_SERIES (VAL_OBJ_FRAME (val ))) {
374
- Mark_Series (VAL_OBJ_FRAME (val ), depth );
375
- if (SERIES_TAIL (VAL_OBJ_FRAME (val )) >= 1 )
376
- ; //Dump_Frame(VAL_OBJ_FRAME(val), 4);
387
+ if (depth >= 64 ) Queue_Mark_Series (VAL_OBJ_FRAME (val ));
388
+ else Mark_Series (VAL_OBJ_FRAME (val ), depth );
389
+ //if (SERIES_TAIL(VAL_OBJ_FRAME(val)) >= 1)
390
+ // Dump_Frame(VAL_OBJ_FRAME(val), 4);
377
391
}
378
392
break ;
379
393
@@ -467,12 +481,12 @@ static void Mark_Series(REBSER *series, REBCNT depth);
467
481
#endif
468
482
if (SERIES_WIDE (ser ) != sizeof (REBVAL ) && SERIES_WIDE (ser ) != 4 && SERIES_WIDE (ser ) != 0 )
469
483
Crash (RP_BAD_WIDTH , 16 , SERIES_WIDE (ser ), VAL_TYPE (val ));
470
- CHECK_MARK (ser , depth );
484
+ QUEUE_CHECK_MARK (ser , depth );
471
485
break ;
472
486
473
487
case REB_MAP :
474
488
ser = VAL_SERIES (val );
475
- CHECK_MARK (ser , depth );
489
+ QUEUE_CHECK_MARK (ser , depth );
476
490
if (ser -> series ) {
477
491
MARK_SERIES (ser -> series );
478
492
}
@@ -664,7 +678,7 @@ static void Mark_Series(REBSER *series, REBCNT depth);
664
678
PG_Reb_Stats -> Recycle_Counter ++ ;
665
679
PG_Reb_Stats -> Recycle_Series = Mem_Pools [SERIES_POOL ].free ;
666
680
667
- PG_Reb_Stats -> Mark_Count = 0 ;
681
+ // PG_Reb_Stats->Mark_Count = 0;
668
682
669
683
// WARNING: These terminate existing open blocks. This could
670
684
// be a problem if code is building a new value at the tail,
@@ -701,12 +715,19 @@ static void Mark_Series(REBSER *series, REBCNT depth);
701
715
}
702
716
}
703
717
718
+ MARK_SERIES (GC_Mark_Queue );
719
+
704
720
// Mark all root series:
705
721
Mark_Series (VAL_SERIES (ROOT_ROOT ), 0 );
706
722
Mark_Series (Task_Series , 0 );
707
723
708
724
// Mark all devices:
709
725
Mark_Devices (0 );
726
+
727
+ // Mark series queued to avoid a stack overflow in case of deep recursion
728
+ while (GC_Mark_Queue -> tail > 0 ) {
729
+ Mark_Series (((REBSER * * )GC_Mark_Queue -> data )[-- GC_Mark_Queue -> tail ], 0 );
730
+ }
710
731
711
732
count = Sweep_Series ();
712
733
count += Sweep_Gobs ();
@@ -802,6 +823,11 @@ static void Mark_Series(REBSER *series, REBCNT depth);
802
823
803
824
GC_Series = Make_Series (60 , sizeof (REBSER * ), FALSE);
804
825
KEEP_SERIES (GC_Series , "gc guarded" );
826
+
827
+ // Series queued to be marked in case of deep recursion.
828
+ GC_Mark_Queue = Make_Series (15 , sizeof (REBSER * ), FALSE);
829
+ BARE_SERIES (GC_Mark_Queue );
830
+ LABEL_SERIES (GC_Mark_Queue , "gc mark queue" );
805
831
}
806
832
807
833
/***********************************************************************
0 commit comments