2222#include "caml/frame_descriptors.h"
2323#include "caml/major_gc.h" /* for caml_major_cycles_completed */
2424#include "caml/memory.h"
25+ #include "caml/shared_heap.h"
2526#include <stddef.h>
2627
2728/* Defined in code generated by ocamlopt */
@@ -172,6 +173,15 @@ void caml_register_frametable(intnat *table)
172173 ft -> prev = old ;
173174 atomic_store_rel (& current_frametable , (uintnat )ft );
174175
176+ /* Ensure that we GC often enough to prevent more than 1/4 of
177+ heap memory being stale frame tables */
178+ caml_adjust_gc_speed (
179+ /* Size of the table just allocated */
180+ (sizeof (* ft ) + sizeof (ft -> table .descriptors [0 ]) * (ft -> table .mask + 1 )),
181+ /* 1/4 of the heap size */
182+ caml_heap_size (Caml_state -> shared_heap ) / 4
183+ );
184+
175185 caml_plat_unlock (& descr_mutex );
176186}
177187
@@ -182,11 +192,16 @@ caml_frame_descrs caml_get_frame_descrs(void)
182192 CAMLassert (ft );
183193 if (atomic_load_acq (& ft -> free_prev_after_cycle ) < caml_major_cycles_completed )
184194 {
185- /* it's now safe to free the old table */
195+ /* it's now safe to free the old table(s) */
186196 caml_plat_lock (& descr_mutex );
187197 if (ft -> prev != NULL ) {
188- caml_stat_free (ft -> prev -> table .descriptors );
189- caml_stat_free (ft -> prev );
198+ struct frametable_version * p = ft -> prev ;
199+ while (p != NULL ) {
200+ struct frametable_version * next = p -> prev ;
201+ caml_stat_free (p -> table .descriptors );
202+ caml_stat_free (p );
203+ p = next ;
204+ }
190205 ft -> prev = NULL ;
191206 atomic_store_rel (& ft -> free_prev_after_cycle , No_need_to_free );
192207 }
0 commit comments