mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-28 05:50:30 +02:00
Merged Whippet into libguile/whippet
This commit is contained in:
commit
db181e67ff
112 changed files with 18115 additions and 0 deletions
198
libguile/whippet/src/gc-options.c
Normal file
198
libguile/whippet/src/gc-options.c
Normal file
|
@ -0,0 +1,198 @@
|
|||
#include <limits.h>
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define GC_IMPL 1
|
||||
|
||||
#include "gc-options-internal.h"
|
||||
#include "gc-platform.h"
|
||||
|
||||
// M(UPPER, lower, repr, type, parser, default, min, max)
|
||||
#define FOR_EACH_INT_GC_OPTION(M) \
|
||||
M(HEAP_SIZE_POLICY, heap_size_policy, "heap-size-policy", \
|
||||
int, heap_size_policy, GC_HEAP_SIZE_FIXED, GC_HEAP_SIZE_FIXED, \
|
||||
GC_HEAP_SIZE_ADAPTIVE) \
|
||||
M(PARALLELISM, parallelism, "parallelism", \
|
||||
int, int, default_parallelism(), 1, 64)
|
||||
|
||||
#define FOR_EACH_SIZE_GC_OPTION(M) \
|
||||
M(HEAP_SIZE, heap_size, "heap-size", \
|
||||
size, size, 6 * 1024 * 1024, 0, -1) \
|
||||
M(MAXIMUM_HEAP_SIZE, maximum_heap_size, "maximum-heap-size", \
|
||||
size, size, 0, 0, -1)
|
||||
|
||||
#define FOR_EACH_DOUBLE_GC_OPTION(M) \
|
||||
M(HEAP_SIZE_MULTIPLIER, heap_size_multiplier, "heap-size-multiplier", \
|
||||
double, double, 1.75, 1.0, 1e6) \
|
||||
M(HEAP_EXPANSIVENESS, heap_expansiveness, "heap-expansiveness", \
|
||||
double, double, 1.0, 0.0, 50.0)
|
||||
|
||||
typedef int gc_option_int;
|
||||
typedef size_t gc_option_size;
|
||||
typedef double gc_option_double;
|
||||
|
||||
#define FOR_EACH_COMMON_GC_OPTION(M) \
|
||||
FOR_EACH_INT_GC_OPTION(M) \
|
||||
FOR_EACH_SIZE_GC_OPTION(M) \
|
||||
FOR_EACH_DOUBLE_GC_OPTION(M)
|
||||
|
||||
static int clamp_int(int n, int lo, int hi) {
|
||||
return n < lo ? lo : n > hi ? hi : n;
|
||||
}
|
||||
static size_t clamp_size(size_t n, size_t lo, size_t hi) {
|
||||
return n < lo ? lo : n > hi ? hi : n;
|
||||
}
|
||||
static double clamp_double(double n, double lo, double hi) {
|
||||
return n < lo ? lo : n > hi ? hi : n;
|
||||
}
|
||||
|
||||
static int default_parallelism(void) {
|
||||
return clamp_int(gc_platform_processor_count(), 1, 8);
|
||||
}
|
||||
|
||||
void gc_init_common_options(struct gc_common_options *options) {
|
||||
#define INIT(UPPER, lower, repr, type, parser, default, min, max) \
|
||||
options->lower = default;
|
||||
FOR_EACH_COMMON_GC_OPTION(INIT)
|
||||
#undef INIT
|
||||
}
|
||||
|
||||
int gc_common_option_from_string(const char *str) {
|
||||
#define GET_OPTION(UPPER, lower, repr, type, parser, default, min, max) \
|
||||
if (strcmp(str, repr) == 0) return GC_OPTION_##UPPER;
|
||||
FOR_EACH_COMMON_GC_OPTION(GET_OPTION)
|
||||
#undef GET_OPTION
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define SET_OPTION(UPPER, lower, repr, type, parser, default, min, max) \
|
||||
case GC_OPTION_##UPPER: \
|
||||
if (value != clamp_##type(value, min, max)) return 0; \
|
||||
options->lower = value; \
|
||||
return 1;
|
||||
#define DEFINE_SETTER(STEM, stem, type) \
|
||||
int gc_common_options_set_##stem(struct gc_common_options *options, \
|
||||
int option, type value) { \
|
||||
switch (option) { \
|
||||
FOR_EACH_##STEM##_GC_OPTION(SET_OPTION) \
|
||||
default: return 0; \
|
||||
} \
|
||||
}
|
||||
DEFINE_SETTER(INT, int, int)
|
||||
DEFINE_SETTER(SIZE, size, size_t)
|
||||
DEFINE_SETTER(DOUBLE, double, double)
|
||||
#undef SET_OPTION
|
||||
#undef DEFINE_SETTER
|
||||
|
||||
static int parse_size(const char *arg, size_t *val) {
|
||||
char *end;
|
||||
long i = strtol(arg, &end, 0);
|
||||
if (i < 0 || i == LONG_MAX) return 0;
|
||||
if (end == arg) return 0;
|
||||
char delim = *end;
|
||||
if (delim == 'k' || delim == 'K')
|
||||
++end, i *= 1024L;
|
||||
else if (delim == 'm' || delim == 'M')
|
||||
++end, i *= 1024L * 1024L;
|
||||
else if (delim == 'g' || delim == 'G')
|
||||
++end, i *= 1024L * 1024L * 1024L;
|
||||
else if (delim == 't' || delim == 'T')
|
||||
++end, i *= 1024L * 1024L * 1024L * 1024L;
|
||||
|
||||
if (*end != '\0') return 0;
|
||||
*val = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse_int(const char *arg, int *val) {
|
||||
char *end;
|
||||
long i = strtol(arg, &end, 0);
|
||||
if (i == LONG_MIN || i == LONG_MAX || end == arg || *end)
|
||||
return 0;
|
||||
*val = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse_heap_size_policy(const char *arg, int *val) {
|
||||
if (strcmp(arg, "fixed") == 0) {
|
||||
*val = GC_HEAP_SIZE_FIXED;
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(arg, "growable") == 0) {
|
||||
*val = GC_HEAP_SIZE_GROWABLE;
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(arg, "adaptive") == 0) {
|
||||
*val = GC_HEAP_SIZE_ADAPTIVE;
|
||||
return 1;
|
||||
}
|
||||
return parse_int(arg, val);
|
||||
}
|
||||
|
||||
static int parse_double(const char *arg, double *val) {
|
||||
char *end;
|
||||
double d = strtod(arg, &end);
|
||||
if (end == arg || *end)
|
||||
return 0;
|
||||
*val = d;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int gc_common_options_parse_and_set(struct gc_common_options *options,
|
||||
int option, const char *value) {
|
||||
switch (option) {
|
||||
#define SET_OPTION(UPPER, lower, repr, type, parser, default, min, max) \
|
||||
case GC_OPTION_##UPPER: { \
|
||||
gc_option_##type v; \
|
||||
if (!parse_##parser(value, &v)) return 0; \
|
||||
return gc_common_options_set_##type(options, option, v); \
|
||||
}
|
||||
FOR_EACH_COMMON_GC_OPTION(SET_OPTION)
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int is_lower(char c) { return 'a' <= c && c <= 'z'; }
|
||||
static int is_digit(char c) { return '0' <= c && c <= '9'; }
|
||||
static int is_option(char c) { return is_lower(c) || c == '-'; }
|
||||
static int is_option_end(char c) { return c == '='; }
|
||||
static int is_value(char c) {
|
||||
return is_lower(c) || is_digit(c) || c == '-' || c == '+' || c == '.';
|
||||
}
|
||||
static int is_value_end(char c) { return c == '\0' || c == ','; }
|
||||
static char* read_token(char *p, int (*is_tok)(char c), int (*is_end)(char c),
|
||||
char *delim) {
|
||||
char c;
|
||||
for (c = *p; is_tok(c); c = *++p);
|
||||
if (!is_end(c)) return NULL;
|
||||
*delim = c;
|
||||
*p = '\0';
|
||||
return p + 1;
|
||||
}
|
||||
int gc_options_parse_and_set_many(struct gc_options *options,
|
||||
const char *str) {
|
||||
if (!*str) return 1;
|
||||
char *copy = strdup(str);
|
||||
char *cur = copy;
|
||||
int ret = 0;
|
||||
while (1) {
|
||||
char delim;
|
||||
char *next = read_token(cur, is_option, is_option_end, &delim);
|
||||
if (!next) break;
|
||||
int option = gc_option_from_string(cur);
|
||||
if (option < 0) break;
|
||||
|
||||
cur = next;
|
||||
next = read_token(cur, is_value, is_value_end, &delim);
|
||||
if (!next) break;
|
||||
if (!gc_options_parse_and_set(options, option, cur)) break;
|
||||
cur = next;
|
||||
if (delim == '\0') {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(copy);
|
||||
return ret;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue