v2 / vlib / builtin / builtin_d_gcboehm.c.v
305 lines · 264 sloc · 8.56 KB · 9f76fd047dfac89e5b7328183dc7b75432de45d2
Raw
1module builtin
2
3$if !no_gc_threads ? {
4 #flag -DGC_THREADS=1
5}
6
7$if use_bundled_libgc ? {
8 #flag -DGC_BUILTIN_ATOMIC=1
9 #flag -I @VEXEROOT/thirdparty/libgc/include
10 #flag -DALL_INTERIOR_POINTERS=1
11 #flag @VEXEROOT/thirdparty/libgc/gc.o
12}
13
14$if dynamic_boehm ? {
15 $if windows {
16 $if tinyc {
17 #flag -I @VEXEROOT/thirdparty/libgc/include
18 #flag -L @VEXEROOT/thirdparty/tcc/lib
19 #flag -lgc
20 } $else $if msvc {
21 #flag -DGC_BUILTIN_ATOMIC=1
22 #flag -I @VEXEROOT/thirdparty/libgc/include
23 } $else {
24 #flag -DGC_WIN32_THREADS=1
25 #flag -DGC_BUILTIN_ATOMIC=1
26 #flag -I @VEXEROOT/thirdparty/libgc/include
27 #flag -DALL_INTERIOR_POINTERS=1
28 #flag @VEXEROOT/thirdparty/libgc/gc.o
29 }
30 } $else {
31 $if $pkgconfig('bdw-gc-threaded') {
32 #pkgconfig bdw-gc-threaded
33 } $else $if $pkgconfig('bdw-gc') {
34 #pkgconfig bdw-gc
35 } $else {
36 $if openbsd || freebsd {
37 #flag -I/usr/local/include
38 #flag -L/usr/local/lib
39 }
40 $if freebsd {
41 #flag -lgc-threaded
42 } $else {
43 #flag -lgc
44 }
45 }
46 }
47} $else {
48 $if macos || linux {
49 #flag -DGC_BUILTIN_ATOMIC=1
50 #flag -I @VEXEROOT/thirdparty/libgc/include
51 $if (prod && !tinyc && !debug) || !(amd64 || arm64 || i386 || arm32 || rv64) {
52 // TODO: replace the architecture check with a `!$exists("@VEXEROOT/thirdparty/tcc/lib/libgc.a")` comptime call
53 #flag -DALL_INTERIOR_POINTERS=1
54 #flag @VEXEROOT/thirdparty/libgc/gc.o
55 } $else {
56 $if !use_bundled_libgc ? {
57 $if macos {
58 $if tinyc {
59 $if arm64 {
60 // tcc on macOS arm64 can leave the bundled GC archive symbols unresolved.
61 #flag @VEXEROOT/thirdparty/tcc/lib/libgc.dylib
62 #flag -Wl,-rpath,"@VEXEROOT/thirdparty/tcc/lib"
63 } $else {
64 // macOS amd64 tccbin only ships libgc.a (no .dylib).
65 #flag @VEXEROOT/thirdparty/tcc/lib/libgc.a
66 }
67 } $else {
68 #flag -L@VEXEROOT/thirdparty/tcc/lib
69 #flag -lgc
70 #flag -Xlinker -rpath -Xlinker "@VEXEROOT/thirdparty/tcc/lib"
71 }
72 } $else {
73 #flag @VEXEROOT/thirdparty/tcc/lib/libgc.a
74 }
75 }
76 }
77 $if macos {
78 #flag -DMPROTECT_VDB=1
79 }
80 #flag -ldl
81 #flag -lpthread
82 } $else $if freebsd {
83 // Tested on FreeBSD 13.0-RELEASE-p3, with clang, gcc and tcc
84 #flag -DGC_BUILTIN_ATOMIC=1
85 #flag -DBUS_PAGE_FAULT=T_PAGEFLT
86 #flag -DALL_INTERIOR_POINTERS=1
87 $if !tinyc {
88 #flag -DUSE_MMAP
89 #flag -I @VEXEROOT/thirdparty/libgc/include
90 #flag @VEXEROOT/thirdparty/libgc/gc.o
91 }
92 $if tinyc {
93 // Prefer the bundled header: older FreeBSD libgc headers still use the
94 // unsupported `"X"` asm constraint in `GC_reachable_here` under tcc.
95 #flag -I @VEXEROOT/thirdparty/libgc/include
96 #flag -I/usr/local/include
97 #flag $first_existing("@VEXEROOT/thirdparty/tcc/lib/libgc.a", "/usr/local/lib/libgc-threaded.a", "/usr/lib/libgc-threaded.a")
98 #flag -lgc-threaded
99 }
100 #flag -lpthread
101 } $else $if openbsd {
102 // Tested on OpenBSD 7.5, with clang, gcc and tcc
103 #flag -DGC_BUILTIN_ATOMIC=1
104 $if !tinyc {
105 #flag -I @VEXEROOT/thirdparty/libgc/include
106 #flag -DALL_INTERIOR_POINTERS=1
107 #flag @VEXEROOT/thirdparty/libgc/gc.o
108 }
109 $if tinyc {
110 // Prefer the bundled header: older OpenBSD libgc headers still use the
111 // unsupported `"X"` asm constraint in `GC_reachable_here` under tcc.
112 #flag -I @VEXEROOT/thirdparty/libgc/include
113 #flag -L/usr/local/lib
114 #flag -I/usr/local/include
115 #flag $first_existing("/usr/local/lib/libgc.a", "/usr/lib/libgc.a")
116 #flag -lgc
117 }
118 #flag -lpthread
119 } $else $if windows {
120 #flag -DGC_NOT_DLL=1
121 #flag -DGC_WIN32_THREADS=1
122 #flag -luser32
123 $if tinyc {
124 #flag -DGC_BUILTIN_ATOMIC=1
125 #flag -I @VEXEROOT/thirdparty/libgc/include
126 $if !use_bundled_libgc ? {
127 #flag @VEXEROOT/thirdparty/tcc/lib/libgc.a
128 }
129 } $else $if msvc {
130 // Build libatomic_ops
131 #flag @VEXEROOT/thirdparty/libatomic_ops/atomic_ops.o
132 #flag -I @VEXEROOT/thirdparty/libatomic_ops
133
134 #flag -I @VEXEROOT/thirdparty/libgc/include
135 #flag -DALL_INTERIOR_POINTERS=1
136 #flag @VEXEROOT/thirdparty/libgc/gc.o
137 } $else {
138 #flag -DGC_BUILTIN_ATOMIC=1
139 #flag -I @VEXEROOT/thirdparty/libgc/include
140 #flag -DALL_INTERIOR_POINTERS=1
141 #flag @VEXEROOT/thirdparty/libgc/gc.o
142 }
143 } $else $if $pkgconfig('bdw-gc') {
144 #flag -DGC_BUILTIN_ATOMIC=1
145 #pkgconfig bdw-gc
146 } $else {
147 #flag -DGC_BUILTIN_ATOMIC=1
148 #flag -lgc
149 }
150}
151
152$if gcboehm_leak ? {
153 #flag -DGC_DEBUG=1
154}
155
156#include <gc.h>
157#include "@VEXEROOT/vlib/builtin/gc_debugger_linux.h"
158
159// #include <gc/gc_mark.h>
160
161// replacements for `malloc()/calloc()`, `realloc()` and `free()`
162// for use with Boehm-GC
163// Do not use them manually. They are automatically chosen when
164// compiled with `-gc boehm` or `-gc boehm_leak`.
165fn C.GC_MALLOC(n usize) voidptr
166
167fn C.GC_MALLOC_ATOMIC(n usize) voidptr
168
169fn C.GC_MALLOC_UNCOLLECTABLE(n usize) voidptr
170
171fn C.GC_REALLOC(ptr voidptr, n usize) voidptr
172
173fn C.GC_FREE(ptr voidptr)
174
175fn C.GC_memalign(align isize, size isize) voidptr
176
177// explicitly perform garbage collection now! Garbage collections
178// are done automatically when needed, so this function is hardly needed
179fn C.GC_gcollect()
180
181// functions to temporarily suspend/resume garbage collection
182fn C.GC_disable()
183
184fn C.GC_enable()
185
186// returns non-zero if GC is disabled
187fn C.GC_is_disabled() i32
188
189fn C.GC_set_no_dls(i32)
190
191// protect memory block from being freed before this call
192fn C.GC_reachable_here(voidptr)
193
194// gc_is_enabled returns true, if the GC is enabled at runtime.
195// See also gc_disable() and gc_enable().
196pub fn gc_is_enabled() bool {
197 return 0 == C.GC_is_disabled()
198}
199
200// gc_collect explicitly performs a single garbage collection run.
201// Note, that garbage collections, are done automatically, when needed in most cases,
202// so usually you should NOT need to call gc_collect() often.
203// Note that gc_collect() is a NOP with `-gc none`.
204pub fn gc_collect() {
205 C.GC_gcollect()
206}
207
208// gc_enable explicitly enables the GC.
209// Note, that garbage collections are done automatically, when needed in most cases,
210// and also that by default the GC is on, so you do not need to enable it.
211// See also gc_disable() and gc_collect().
212// Note that gc_enable() is a NOP with `-gc none`.
213pub fn gc_enable() {
214 C.GC_enable()
215}
216
217// gc_disable explicitly disables the GC. Do not forget to enable it again by calling gc_enable(), when your program is otherwise idle, and can afford it.
218// See also gc_enable() and gc_collect().
219// Note that gc_disable() is a NOP with `-gc none`.
220pub fn gc_disable() {
221 C.GC_disable()
222}
223
224// gc_check_leaks is useful for leak detection (it does an explicit garbage collections, but only when a program is compiled with `-gc boehm_leak`).
225pub fn gc_check_leaks() {
226 $if gcboehm_leak ? {
227 C.GC_gcollect()
228 }
229}
230
231fn C.GC_get_heap_usage_safe(pheap_size &usize, pfree_bytes &usize, punmapped_bytes &usize, pbytes_since_gc &usize,
232 ptotal_bytes &usize)
233fn C.GC_get_memory_use() usize
234
235pub struct C.GC_stack_base {
236 mem_base voidptr
237 // reg_base voidptr
238}
239
240fn C.GC_get_stack_base(voidptr) i32
241fn C.GC_register_my_thread(voidptr) i32
242fn C.GC_unregister_my_thread() i32
243
244// fn C.GC_get_my_stackbottom(voidptr) voidptr
245fn C.GC_set_stackbottom(voidptr, voidptr)
246
247// fn C.GC_push_all_stacks()
248
249fn C.GC_add_roots(voidptr, voidptr)
250fn C.GC_remove_roots(voidptr, voidptr)
251
252fn C.v__gc_can_register_main_data_roots_linux() i32
253fn C.v__gc_debugger_present_linux() i32
254fn C.v__gc_register_main_data_roots_linux()
255
256// fn C.GC_get_push_other_roots() fn()
257// fn C.GC_set_push_other_roots(fn())
258
259fn C.GC_get_sp_corrector() fn (voidptr, voidptr)
260fn C.GC_set_sp_corrector(fn (voidptr, voidptr))
261
262// FnGC_WarnCB is the type of the callback, that you have to define, if you want to redirect GC warnings and handle them.
263// Note: GC warnings are silenced by default. Use gc_set_warn_proc/1 to set your own handler for them.
264pub type FnGC_WarnCB = fn (const_msg &char, arg usize)
265
266fn C.GC_get_warn_proc() FnGC_WarnCB
267fn C.GC_set_warn_proc(cb FnGC_WarnCB)
268
269fn C.GC_register_displacement(offset usize)
270
271// gc_get_warn_proc returns the current callback fn, that will be used for printing GC warnings.
272pub fn gc_get_warn_proc() FnGC_WarnCB {
273 return C.GC_get_warn_proc()
274}
275
276// gc_set_warn_proc sets the callback fn, that will be used for printing GC warnings.
277pub fn gc_set_warn_proc(cb FnGC_WarnCB) {
278 C.GC_set_warn_proc(cb)
279}
280
281// used by builtin_init:
282fn internal_gc_warn_proc_none(const_msg &char, arg usize) {}
283
284@[markused]
285fn gc_prepare_for_debugger_init() bool {
286 $if linux {
287 if C.v__gc_debugger_present_linux() != 0
288 && C.v__gc_can_register_main_data_roots_linux() != 0 {
289 C.GC_set_no_dls(1)
290 return true
291 }
292 }
293 return false
294}
295
296@[markused]
297fn gc_restore_roots_after_debugger_init(use_manual_roots bool) {
298 if !use_manual_roots {
299 return
300 }
301 $if linux {
302 C.v__gc_register_main_data_roots_linux()
303 C.GC_set_no_dls(0)
304 }
305}
306