@@ -25,6 +25,13 @@ _Atomic(int) gc_master_tid;
25
25
uv_mutex_t gc_threads_lock ;
26
26
uv_cond_t gc_threads_cond ;
27
27
28
+ #ifdef GC_FIXED_HEAP
29
+ // Globally allocated bytes by malloc - used for fixed heap size
30
+ _Atomic(uint64_t ) malloc_bytes ;
31
+ // Globally allocated pool pages - used for fixed heap size
32
+ extern uint64_t jl_current_pg_count (void );
33
+ #endif
34
+
28
35
// Linked list of callback functions
29
36
30
37
typedef void (* jl_gc_cb_func_t )(void );
@@ -393,6 +400,9 @@ extern int64_t live_bytes;
393
400
static int64_t perm_scanned_bytes ; // old bytes scanned while marking
394
401
int prev_sweep_full = 1 ;
395
402
int current_sweep_full = 0 ;
403
+ #ifdef GC_FIXED_HEAP
404
+ int next_sweep_full = 0 ; // force next sweep to be a full sweep - used by fixed heap size
405
+ #endif
396
406
397
407
// Full collection heuristics
398
408
static int64_t promoted_bytes = 0 ;
@@ -574,6 +584,18 @@ void gc_setmark_buf(jl_ptls_t ptls, void *o, uint8_t mark_mode, size_t minsz) JL
574
584
575
585
inline void maybe_collect (jl_ptls_t ptls )
576
586
{
587
+ #ifdef GC_FIXED_HEAP
588
+ if (jl_options .fixed_heap_size ) {
589
+ uint64_t current_heap_size = ((uint64_t )jl_current_pg_count ()) << (uint64_t )14 ;
590
+ current_heap_size += jl_atomic_load_relaxed (& malloc_bytes );
591
+ if (current_heap_size >= jl_options .fixed_heap_size ) {
592
+ jl_gc_collect (JL_GC_AUTO );
593
+ } else {
594
+ jl_gc_safepoint_ (ptls );
595
+ }
596
+ return ;
597
+ }
598
+ #endif
577
599
if (jl_atomic_load_relaxed (& ptls -> gc_num .allocd ) >= 0 || jl_gc_debug_check_other ()) {
578
600
jl_gc_collect (JL_GC_AUTO );
579
601
}
@@ -2708,6 +2730,16 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection)
2708
2730
sweep_full = 1 ;
2709
2731
recollect = 1 ;
2710
2732
}
2733
+ #ifdef GC_FIXED_HEAP
2734
+ if (jl_options .fixed_heap_size ) {
2735
+ // For fixed heap size, do not trigger full sweep for any other heuristics
2736
+ sweep_full = 0 ;
2737
+ }
2738
+ if (next_sweep_full ) {
2739
+ next_sweep_full = 0 ;
2740
+ sweep_full = 1 ;
2741
+ }
2742
+ #endif
2711
2743
if (sweep_full ) {
2712
2744
// these are the difference between the number of gc-perm bytes scanned
2713
2745
// on the first collection after sweep_full, and the current scan
@@ -2824,6 +2856,15 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection)
2824
2856
}
2825
2857
}
2826
2858
2859
+ #ifdef GC_FIXED_HEAP
2860
+ if (jl_options .fixed_heap_size ) {
2861
+ uint64_t current_heap_size = ((uint64_t )jl_current_pg_count ()) << ((uint64_t )14 );
2862
+ if (current_heap_size > (jl_options .fixed_heap_size * 4 / 5 )) {
2863
+ next_sweep_full = 1 ;
2864
+ }
2865
+ }
2866
+ #endif
2867
+
2827
2868
gc_time_summary (sweep_full , t_start , gc_end_time , gc_num .freed ,
2828
2869
live_bytes , gc_num .interval , pause ,
2829
2870
gc_num .time_to_safepoint ,
@@ -3029,6 +3070,16 @@ void jl_gc_init(void)
3029
3070
#endif
3030
3071
if (jl_options .heap_size_hint )
3031
3072
jl_gc_set_max_memory (jl_options .heap_size_hint );
3073
+
3074
+ #ifdef GC_FIXED_HEAP
3075
+ if (jl_options .fixed_heap_size ) {
3076
+ // This guarantees that we will not trigger a GC before reaching heap limit
3077
+ gc_num .interval = jl_options .fixed_heap_size ;
3078
+ } else {
3079
+ jl_printf (JL_STDERR , "Warning: The option fixed-heap-size is not set for a build with WITH_GC_FIXED_HEAP\n" );
3080
+ }
3081
+ #endif
3082
+
3032
3083
t_start = jl_hrtime ();
3033
3084
}
3034
3085
@@ -3045,6 +3096,9 @@ JL_DLLEXPORT void *jl_gc_counted_malloc(size_t sz)
3045
3096
jl_atomic_load_relaxed (& ptls -> gc_num .allocd ) + sz );
3046
3097
jl_atomic_store_relaxed (& ptls -> gc_num .malloc ,
3047
3098
jl_atomic_load_relaxed (& ptls -> gc_num .malloc ) + 1 );
3099
+ #ifdef GC_FIXED_HEAP
3100
+ jl_atomic_fetch_add_relaxed (& malloc_bytes , sz );
3101
+ #endif
3048
3102
}
3049
3103
return malloc (sz );
3050
3104
}
@@ -3060,6 +3114,9 @@ JL_DLLEXPORT void *jl_gc_counted_calloc(size_t nm, size_t sz)
3060
3114
jl_atomic_load_relaxed (& ptls -> gc_num .allocd ) + nm * sz );
3061
3115
jl_atomic_store_relaxed (& ptls -> gc_num .malloc ,
3062
3116
jl_atomic_load_relaxed (& ptls -> gc_num .malloc ) + 1 );
3117
+ #ifdef GC_FIXED_HEAP
3118
+ jl_atomic_fetch_add_relaxed (& malloc_bytes , nm * sz );
3119
+ #endif
3063
3120
}
3064
3121
return calloc (nm , sz );
3065
3122
}
@@ -3075,6 +3132,9 @@ JL_DLLEXPORT void jl_gc_counted_free_with_size(void *p, size_t sz)
3075
3132
jl_atomic_load_relaxed (& ptls -> gc_num .freed ) + sz );
3076
3133
jl_atomic_store_relaxed (& ptls -> gc_num .freecall ,
3077
3134
jl_atomic_load_relaxed (& ptls -> gc_num .freecall ) + 1 );
3135
+ #ifdef GC_FIXED_HEAP
3136
+ jl_atomic_fetch_add_relaxed (& malloc_bytes , - sz );
3137
+ #endif
3078
3138
}
3079
3139
}
3080
3140
@@ -3085,12 +3145,19 @@ JL_DLLEXPORT void *jl_gc_counted_realloc_with_old_size(void *p, size_t old, size
3085
3145
if (pgcstack != NULL && ct -> world_age ) {
3086
3146
jl_ptls_t ptls = ct -> ptls ;
3087
3147
maybe_collect (ptls );
3088
- if (sz < old )
3148
+ if (sz < old ) {
3089
3149
jl_atomic_store_relaxed (& ptls -> gc_num .freed ,
3090
3150
jl_atomic_load_relaxed (& ptls -> gc_num .freed ) + (old - sz ));
3091
- else
3151
+ #ifdef GC_FIXED_HEAP
3152
+ jl_atomic_fetch_add_relaxed (& malloc_bytes , old - sz );
3153
+ #endif
3154
+ } else {
3092
3155
jl_atomic_store_relaxed (& ptls -> gc_num .allocd ,
3093
3156
jl_atomic_load_relaxed (& ptls -> gc_num .allocd ) + (sz - old ));
3157
+ #ifdef GC_FIXED_HEAP
3158
+ jl_atomic_fetch_add_relaxed (& malloc_bytes , sz - old );
3159
+ #endif
3160
+ }
3094
3161
jl_atomic_store_relaxed (& ptls -> gc_num .realloc ,
3095
3162
jl_atomic_load_relaxed (& ptls -> gc_num .realloc ) + 1 );
3096
3163
}
0 commit comments