diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a138d057d0..9767d166a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -129,7 +129,9 @@ jobs: thirdparty/tcc/tcc.exe -version ./v -cg -o v cmd/v # Make sure vtcc can build itself twice - name: v self compilation with -gc boehm - run: ./v -gc boehm -o v2 cmd/v && ./v2 -gc boehm -o v3 cmd/v && ./v3 -gc boehm -o v4 cmd/v + run: | + ./v -gc boehm -o v2 cmd/v && ./v2 -gc boehm -o v3 cmd/v && ./v3 -gc boehm -o v4 cmd/v + mv v4 v - name: v doctor run: | ./v doctor @@ -137,8 +139,7 @@ jobs: run: | ./v -gc boehm cmd/tools/test_if_v_test_system_works.v ./cmd/tools/test_if_v_test_system_works - - name: Self tests with `-gc boehm` - ## The test cases are run with non-gc `v` for now + - name: Self tests with `-gc boehm` with V compiler using Boehm-GC itself run: ./v -gc boehm -silent test-self - name: Test leak detector run: | diff --git a/vlib/builtin/builtin.c.v b/vlib/builtin/builtin.c.v index d8033f94ce..19c779ebfd 100644 --- a/vlib/builtin/builtin.c.v +++ b/vlib/builtin/builtin.c.v @@ -189,7 +189,13 @@ pub fn malloc(n int) byteptr { nr_mallocs++ } $else { $if gcboehm ? { - res = unsafe { C.GC_MALLOC(n) } + unsafe { + if C.__v_inside_init == 0 { + res = C.GC_MALLOC(n) + } else { + res = C.GC_MALLOC_UNCOLLECTABLE(n) + } + } } $else { res = unsafe { C.malloc(n) } } @@ -282,16 +288,6 @@ pub fn realloc_data(old_data byteptr, old_size int, new_size int) byteptr { return nptr } -// v_calloc dynamically allocates a zeroed `n` bytes block of memory on the heap. -// v_calloc returns a `byteptr` pointing to the memory address of the allocated space. -pub fn v_calloc(n int) byteptr { - $if gcboehm ? { - return C.GC_MALLOC(n) - } $else { - return C.calloc(1, n) - } -} - // vcalloc dynamically allocates a zeroed `n` bytes block of memory on the heap. // vcalloc returns a `byteptr` pointing to the memory address of the allocated space. // Unlike `v_calloc` vcalloc checks for negative values given in `n`. @@ -302,7 +298,11 @@ pub fn vcalloc(n int) byteptr { return byteptr(0) } $if gcboehm ? { - return C.GC_MALLOC(n) + return if C.__v_inside_init == 0 { + byteptr(C.GC_MALLOC(n)) + } else { + byteptr(C.GC_MALLOC_UNCOLLECTABLE(n)) + } } $else { return C.calloc(1, n) } diff --git a/vlib/builtin/builtin_d_gcboehm.v b/vlib/builtin/builtin_d_gcboehm.v index 2e454e1974..a7362912a0 100644 --- a/vlib/builtin/builtin_d_gcboehm.v +++ b/vlib/builtin/builtin_d_gcboehm.v @@ -22,6 +22,8 @@ $if gcboehm_leak ? { // compiled with `-gc boehm` or `-gc boehm_leak`. fn C.GC_MALLOC(n size_t) voidptr +fn C.GC_MALLOC_UNCOLLECTABLE(n size_t) voidptr + fn C.GC_REALLOC(ptr voidptr, n size_t) voidptr fn C.GC_FREE(ptr voidptr) diff --git a/vlib/builtin/builtin_notd_gcboehm.v b/vlib/builtin/builtin_notd_gcboehm.v index acaf42e98c..a3aae70721 100644 --- a/vlib/builtin/builtin_notd_gcboehm.v +++ b/vlib/builtin/builtin_notd_gcboehm.v @@ -6,6 +6,8 @@ module builtin fn C.GC_MALLOC(n size_t) voidptr +fn C.GC_MALLOC_UNCOLLECTABLE(n size_t) voidptr + fn C.GC_REALLOC(ptr voidptr, n size_t) voidptr fn C.GC_FREE(ptr voidptr) diff --git a/vlib/v/gen/c/cheaders.v b/vlib/v/gen/c/cheaders.v index ab0c70c9bf..50ab7c4f24 100644 --- a/vlib/v/gen/c/cheaders.v +++ b/vlib/v/gen/c/cheaders.v @@ -335,6 +335,9 @@ static inline bool _us64_lt(uint64_t a, int64_t b) { return a < INT64_MAX && (in #endif //================================== GLOBALS =================================*/ +#if defined(_VGCBOEHM) + int __v_inside_init = 1; +#endif //byte g_str_buf[1024]; byte* g_str_buf; int load_so(byteptr); diff --git a/vlib/v/gen/c/cmain.v b/vlib/v/gen/c/cmain.v index d08dc766f1..6abfa6f18d 100644 --- a/vlib/v/gen/c/cmain.v +++ b/vlib/v/gen/c/cmain.v @@ -76,6 +76,11 @@ fn (mut g Gen) gen_c_main_header() { g.writeln('#endif') } g.writeln('\t_vinit(___argc, (voidptr)___argv);') + if g.pref.gc_mode in [.boehm, .boehm_leak] { + g.writeln('#if defined(_VGCBOEHM)') + g.writeln('\t__v_inside_init = 0;') + g.writeln('#endif') + } if g.pref.is_prof { g.writeln('') g.writeln('\tatexit(vprint_profile_stats);') @@ -167,6 +172,11 @@ pub fn (mut g Gen) gen_c_main_for_tests() { g.writeln('#endif') } g.writeln('\t_vinit(___argc, (voidptr)___argv);') + if g.pref.gc_mode in [.boehm, .boehm_leak] { + g.writeln('#if defined(_VGCBOEHM)') + g.writeln('\t__v_inside_init = 0;') + g.writeln('#endif') + } all_tfuncs := g.get_all_test_function_names() if g.pref.is_stats { g.writeln('\tmain__BenchedTests bt = main__start_testing($all_tfuncs.len, _SLIT("$g.pref.path"));')