all: support `-gc boehm` on systems with libgc-dev installed (#9382)
parent
a6ddd24f5c
commit
8810af76df
|
@ -69,6 +69,20 @@ see also `v help build`.
|
|||
and unsafe{free(x)} calls manually in this mode).
|
||||
Some short lived applications, like compilers and other CLI tools are
|
||||
more performant without autofree.
|
||||
|
||||
-gc <mode>
|
||||
Use and link an optional garbage collector.
|
||||
Only `-gc boehm` is supported currently. You need to install a
|
||||
`libgc-dev` package first, or install it manually from source:
|
||||
https://github.com/ivmai/bdwgc
|
||||
|
||||
Note, this option is complementary to -autofree. The Boehm garbage
|
||||
collector is conservative, and it may make your program significantly
|
||||
slower if it does many small allocations in a loop. This option
|
||||
is intended *mainly* for reducing the memory usage of programs, that
|
||||
process large amounts of text in *batch mode* on low/limited memory
|
||||
environments like small VPSes, and for which a few ms of garbage
|
||||
collection pauses from time to time *do not matter much*.
|
||||
|
||||
# Miscellaneous:
|
||||
-printfn <fn_name>
|
||||
|
|
|
@ -3698,6 +3698,9 @@ If you do need a custom flag file, that has platform dependent code, use the
|
|||
postfix `_d_customflag.v`, and then use plaftorm dependent compile time
|
||||
conditional blocks inside it, i.e. `$if linux {}` etc.
|
||||
|
||||
- `_notd_customflag.v` => similar to _d_customflag.v, but will be used
|
||||
*only* if you do NOT pass `-d customflag` to V.
|
||||
|
||||
## Compile time pseudo variables
|
||||
|
||||
V also gives your code access to a set of pseudo string variables,
|
||||
|
|
|
@ -482,7 +482,7 @@ pub fn (a &array) free() {
|
|||
// if a.is_slice {
|
||||
// return
|
||||
// }
|
||||
C.free(a.data)
|
||||
unsafe { free(a.data) }
|
||||
}
|
||||
|
||||
[unsafe]
|
||||
|
@ -493,7 +493,7 @@ pub fn (mut a []string) free() {
|
|||
for s in a {
|
||||
unsafe { s.free() }
|
||||
}
|
||||
C.free(a.data)
|
||||
unsafe { free(a.data) }
|
||||
}
|
||||
|
||||
// str returns a string representation of the array of strings
|
||||
|
|
|
@ -184,7 +184,11 @@ pub fn malloc(n int) byteptr {
|
|||
}
|
||||
nr_mallocs++
|
||||
} $else {
|
||||
res = unsafe { C.malloc(n) }
|
||||
$if gcboehm ? {
|
||||
res = unsafe { C.GC_MALLOC(n) }
|
||||
} $else {
|
||||
res = unsafe { C.malloc(n) }
|
||||
}
|
||||
if res == 0 {
|
||||
panic('malloc($n) failed')
|
||||
}
|
||||
|
@ -214,7 +218,11 @@ pub fn v_realloc(b byteptr, n int) byteptr {
|
|||
C.memcpy(new_ptr, b, n)
|
||||
}
|
||||
} $else {
|
||||
new_ptr = unsafe { C.realloc(b, n) }
|
||||
$if gcboehm ? {
|
||||
new_ptr = unsafe { C.GC_REALLOC(b, n) }
|
||||
} $else {
|
||||
new_ptr = unsafe { C.realloc(b, n) }
|
||||
}
|
||||
if new_ptr == 0 {
|
||||
panic('realloc($n) failed')
|
||||
}
|
||||
|
@ -254,11 +262,16 @@ pub fn realloc_data(old_data byteptr, old_size int, new_size int) byteptr {
|
|||
min_size := if old_size < new_size { old_size } else { new_size }
|
||||
C.memcpy(new_ptr, old_data, min_size)
|
||||
C.memset(old_data, 0x57, old_size)
|
||||
C.free(old_data)
|
||||
free(old_data)
|
||||
return new_ptr
|
||||
}
|
||||
}
|
||||
nptr := unsafe { C.realloc(old_data, new_size) }
|
||||
mut nptr := byteptr(0)
|
||||
$if gcboehm ? {
|
||||
nptr = unsafe { C.GC_REALLOC(old_data, new_size) }
|
||||
} $else {
|
||||
nptr = unsafe { C.realloc(old_data, new_size) }
|
||||
}
|
||||
if nptr == 0 {
|
||||
panic('realloc_data($old_data, $old_size, $new_size) failed')
|
||||
}
|
||||
|
@ -268,7 +281,11 @@ pub fn realloc_data(old_data byteptr, old_size int, new_size int) byteptr {
|
|||
// 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 {
|
||||
return C.calloc(1, n)
|
||||
$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.
|
||||
|
@ -280,7 +297,11 @@ pub fn vcalloc(n int) byteptr {
|
|||
} else if n == 0 {
|
||||
return byteptr(0)
|
||||
}
|
||||
return C.calloc(1, n)
|
||||
$if gcboehm ? {
|
||||
return C.GC_MALLOC(n)
|
||||
} $else {
|
||||
return C.calloc(1, n)
|
||||
}
|
||||
}
|
||||
|
||||
// free allows for manually freeing memory allocated at the address `ptr`.
|
||||
|
@ -289,6 +310,10 @@ pub fn free(ptr voidptr) {
|
|||
$if prealloc {
|
||||
return
|
||||
}
|
||||
$if gcboehm ? {
|
||||
C.GC_FREE(ptr)
|
||||
return
|
||||
}
|
||||
C.free(ptr)
|
||||
}
|
||||
|
||||
|
@ -306,14 +331,6 @@ pub fn memdup(src voidptr, sz int) voidptr {
|
|||
}
|
||||
}
|
||||
|
||||
// v_ptr_free is used internally to manually free up memory allocated at the address `ptr`.
|
||||
fn v_ptr_free(ptr voidptr) {
|
||||
$if prealloc {
|
||||
return
|
||||
}
|
||||
C.free(ptr)
|
||||
}
|
||||
|
||||
// is_atty returns 1 if the `fd` file descriptor is open and refers to a terminal
|
||||
pub fn is_atty(fd int) int {
|
||||
$if windows {
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
module builtin
|
||||
|
||||
#define GC_THREADS 1
|
||||
|
||||
#include <gc.h>
|
||||
|
||||
#flag -lgc
|
||||
|
||||
fn C.GC_MALLOC(n size_t) voidptr
|
||||
|
||||
fn C.GC_REALLOC(ptr voidptr, n size_t) voidptr
|
||||
|
||||
fn C.GC_FREE(ptr voidptr)
|
|
@ -0,0 +1,11 @@
|
|||
module builtin
|
||||
|
||||
// Just define the C functions, so that V does not error because of the missing definitions.
|
||||
|
||||
// NB: they will NOT be used, since calls to them are wrapped with `$if gcboehm ? { }`
|
||||
|
||||
fn C.GC_MALLOC(n size_t) voidptr
|
||||
|
||||
fn C.GC_REALLOC(ptr voidptr, n size_t) voidptr
|
||||
|
||||
fn C.GC_FREE(ptr voidptr)
|
|
@ -91,6 +91,6 @@ pub fn (ie &IError) free() {
|
|||
unsafe {
|
||||
ie.msg.free()
|
||||
cie := &C.IError(ie)
|
||||
C.free(cie._object)
|
||||
free(cie._object)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -422,6 +422,9 @@ pub fn (mut g Gen) init() {
|
|||
}
|
||||
g.comptime_defines.writeln('')
|
||||
}
|
||||
if g.pref.gc_mode == .boehm {
|
||||
g.comptime_defines.writeln('#define _VGCBOEHM (1)')
|
||||
}
|
||||
if g.pref.is_debug || 'debug' in g.pref.compile_defines {
|
||||
g.comptime_defines.writeln('#define _VDEBUG (1)')
|
||||
}
|
||||
|
|
|
@ -454,9 +454,10 @@ void _vcleanup();
|
|||
}
|
||||
#endif
|
||||
|
||||
void v_free(voidptr ptr);
|
||||
voidptr memdup(voidptr src, int sz);
|
||||
static voidptr memfreedup(voidptr ptr, voidptr src, int sz) {
|
||||
free(ptr);
|
||||
v_free(ptr);
|
||||
return memdup(src, sz);
|
||||
}
|
||||
'
|
||||
|
|
|
@ -533,6 +533,9 @@ fn (mut g Gen) comp_if_to_ifdef(name string, is_comptime_optional bool) ?string
|
|||
return '__cplusplus'
|
||||
}
|
||||
// other:
|
||||
'gcboehm' {
|
||||
return '_VGCBOEHM'
|
||||
}
|
||||
'debug' {
|
||||
return '_VDEBUG'
|
||||
}
|
||||
|
|
|
@ -26,7 +26,11 @@ void _STR_PRINT_ARG(const char *fmt, char** refbufp, int *nbytes, int *memsize,
|
|||
}
|
||||
// increase buffer (somewhat exponentially)
|
||||
*memsize += (*memsize + *memsize) / 3 + guess;
|
||||
#ifdef _VGCBOEHM
|
||||
*refbufp = (char*)GC_REALLOC((void*)*refbufp, *memsize);
|
||||
#else
|
||||
*refbufp = (char*)realloc((void*)*refbufp, *memsize);
|
||||
#endif
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
@ -35,7 +39,11 @@ string _STR(const char *fmt, int nfmts, ...) {
|
|||
va_list argptr;
|
||||
int memsize = 128;
|
||||
int nbytes = 0;
|
||||
#ifdef _VGCBOEHM
|
||||
char* buf = (char*)GC_MALLOC(memsize);
|
||||
#else
|
||||
char* buf = (char*)malloc(memsize);
|
||||
#endif
|
||||
va_start(argptr, nfmts);
|
||||
for (int i=0; i<nfmts; ++i) {
|
||||
int k = strlen(fmt);
|
||||
|
@ -84,11 +92,18 @@ string _STR(const char *fmt, int nfmts, ...) {
|
|||
}
|
||||
va_end(argptr);
|
||||
buf[nbytes] = 0;
|
||||
|
||||
#ifdef _VGCBOEHM
|
||||
buf = (char*)GC_REALLOC((void*)buf, nbytes+1);
|
||||
#else
|
||||
buf = (char*)realloc((void*)buf, nbytes+1);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
//puts('_STR:');
|
||||
puts(buf);
|
||||
#endif
|
||||
|
||||
#if _VAUTOFREE
|
||||
//g_cur_str = (byteptr)buf;
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,11 @@ pub enum BuildMode {
|
|||
build_module
|
||||
}
|
||||
|
||||
pub enum GarbageCollectionMode {
|
||||
no_gc
|
||||
boehm
|
||||
}
|
||||
|
||||
pub enum OutputMode {
|
||||
stdout
|
||||
silent
|
||||
|
@ -153,6 +158,7 @@ pub mut:
|
|||
build_options []string // list of options, that should be passed down to `build-module`, if needed for -usecache
|
||||
cache_manager vcache.CacheManager
|
||||
is_help bool // -h, -help or --help was passed
|
||||
gc_mode GarbageCollectionMode = .no_gc // .no_gc, .boehm
|
||||
// checker settings:
|
||||
checker_match_exhaustive_cutoff_limit int = 10
|
||||
}
|
||||
|
@ -177,7 +183,7 @@ pub fn parse_args(known_external_commands []string, args []string) (&Preferences
|
|||
target_arch := cmdline.option(current_args, '-arch', '')
|
||||
i++
|
||||
target_arch_kind := arch_from_string(target_arch) or {
|
||||
eprintln('unknown architercture target `$target_arch`')
|
||||
eprintln('unknown architecture target `$target_arch`')
|
||||
exit(1)
|
||||
}
|
||||
res.arch = target_arch_kind
|
||||
|
@ -214,6 +220,23 @@ pub fn parse_args(known_external_commands []string, args []string) (&Preferences
|
|||
'-silent' {
|
||||
res.output_mode = .silent
|
||||
}
|
||||
'-gc' {
|
||||
gc_mode := cmdline.option(current_args, '-gc', '')
|
||||
match gc_mode {
|
||||
'' {
|
||||
res.gc_mode = .no_gc
|
||||
}
|
||||
'boehm' {
|
||||
res.gc_mode = .boehm
|
||||
parse_define(mut res, 'gcboehm')
|
||||
}
|
||||
else {
|
||||
eprintln('unknown garbage collection mode, only `-gc boehm` is supported')
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
i++
|
||||
}
|
||||
'-g' {
|
||||
res.is_debug = true
|
||||
res.is_vlines = true
|
||||
|
|
|
@ -40,6 +40,19 @@ pub fn (prefs &Preferences) should_compile_filtered_files(dir string, files_ []s
|
|||
continue
|
||||
}
|
||||
}
|
||||
if file.contains('_notd_') {
|
||||
mut allowed := true
|
||||
for cdefine in prefs.compile_defines {
|
||||
file_postfix := '_notd_${cdefine}.v'
|
||||
if file.ends_with(file_postfix) {
|
||||
allowed = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if !allowed {
|
||||
continue
|
||||
}
|
||||
}
|
||||
all_v_files << os.join_path(dir, file)
|
||||
}
|
||||
//
|
||||
|
|
Loading…
Reference in New Issue