|
@@ -34,6 +34,30 @@ void *qi_malloc_atomic(qi_size_t size)
|
|
|
return ptr;
|
|
return ptr;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void *qi_malloc_uncollectable(size_t size)
|
|
|
|
|
+{
|
|
|
|
|
+ void *ptr = malloc(size);
|
|
|
|
|
+
|
|
|
|
|
+ if (!ptr)
|
|
|
|
|
+ abort();
|
|
|
|
|
+
|
|
|
|
|
+ memset(ptr, 0, size);
|
|
|
|
|
+
|
|
|
|
|
+ return ptr;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void *qi_malloc_root(size_t size)
|
|
|
|
|
+{
|
|
|
|
|
+ void *ptr = GC_malloc_uncollectable(size);
|
|
|
|
|
+
|
|
|
|
|
+ if (!ptr)
|
|
|
|
|
+ abort();
|
|
|
|
|
+
|
|
|
|
|
+ memset(ptr, 0, size);
|
|
|
|
|
+
|
|
|
|
|
+ return ptr;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void *qi_realloc(void *old_ptr, qi_size_t size)
|
|
void *qi_realloc(void *old_ptr, qi_size_t size)
|
|
|
{
|
|
{
|
|
|
void *ptr = GC_realloc(old_ptr, size);
|
|
void *ptr = GC_realloc(old_ptr, size);
|
|
@@ -80,6 +104,24 @@ qi_list_t *qi_list_make(void)
|
|
|
return list;
|
|
return list;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static qi_list_t *qi_list_make_uncollectable(void)
|
|
|
|
|
+{
|
|
|
|
|
+ qi_list_t *list = qi_malloc_uncollectable(sizeof(qi_list_t));
|
|
|
|
|
+ list->data = NULL;
|
|
|
|
|
+ list->length = 0;
|
|
|
|
|
+
|
|
|
|
|
+ return list;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static qi_list_t *qi_list_make_root(void)
|
|
|
|
|
+{
|
|
|
|
|
+ qi_list_t *list = qi_malloc_root(sizeof(qi_list_t));
|
|
|
|
|
+ list->data = NULL;
|
|
|
|
|
+ list->length = 0;
|
|
|
|
|
+
|
|
|
|
|
+ return list;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
qi_list_t *qi_list_resize(qi_list_t *list, qi_size_t size)
|
|
qi_list_t *qi_list_resize(qi_list_t *list, qi_size_t size)
|
|
|
{
|
|
{
|
|
|
if (list->length == size)
|
|
if (list->length == size)
|
|
@@ -251,6 +293,17 @@ qi_table_t *qi_table_make(void)
|
|
|
return table;
|
|
return table;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static qi_table_t *qi_table_make_root(void)
|
|
|
|
|
+{
|
|
|
|
|
+ qi_table_t *table = qi_malloc_root(sizeof(qi_table_t));
|
|
|
|
|
+ table->used = 0;
|
|
|
|
|
+
|
|
|
|
|
+ table->capacity = QI_TABLE_MIN_CAP;
|
|
|
|
|
+ table->entries = qi_calloc(table->capacity, sizeof(qi_table_entry_t));
|
|
|
|
|
+
|
|
|
|
|
+ return table;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static uint64_t MM86128(void *key, const int len, uint32_t seed)
|
|
static uint64_t MM86128(void *key, const int len, uint32_t seed)
|
|
|
{
|
|
{
|
|
|
#define ROTL32(x, r) ((x << r) | (x >> (32 - r)))
|
|
#define ROTL32(x, r) ((x << r) | (x >> (32 - r)))
|
|
@@ -820,6 +873,16 @@ qi_value_t *qi_make_value(qi_type_t type)
|
|
|
return value;
|
|
return value;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static qi_value_t *qi_make_uncollectable_value(qi_type_t type)
|
|
|
|
|
+{
|
|
|
|
|
+ qi_value_t *value = qi_malloc_uncollectable(sizeof(qi_value_t));
|
|
|
|
|
+
|
|
|
|
|
+ value->type = type;
|
|
|
|
|
+ value->mutex = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ return value;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
qi_value_t *qi_make_number(qi_state_t *state, double number)
|
|
qi_value_t *qi_make_number(qi_state_t *state, double number)
|
|
|
{
|
|
{
|
|
|
qi_value_t *value;
|
|
qi_value_t *value;
|
|
@@ -5090,23 +5153,23 @@ static void qi_state_setup(qi_state_t *state)
|
|
|
{
|
|
{
|
|
|
QI_HASH_SEED = time(NULL);
|
|
QI_HASH_SEED = time(NULL);
|
|
|
|
|
|
|
|
- state->nil = qi_make_value(QI_NULL);
|
|
|
|
|
|
|
+ state->nil = qi_make_uncollectable_value(QI_NULL);
|
|
|
|
|
|
|
|
- state->_true = qi_make_value(QI_BOOLEAN);
|
|
|
|
|
|
|
+ state->_true = qi_make_uncollectable_value(QI_BOOLEAN);
|
|
|
state->_true->value.boolean = true;
|
|
state->_true->value.boolean = true;
|
|
|
|
|
|
|
|
- state->_false = qi_make_value(QI_BOOLEAN);
|
|
|
|
|
|
|
+ state->_false = qi_make_uncollectable_value(QI_BOOLEAN);
|
|
|
state->_false->value.boolean = false;
|
|
state->_false->value.boolean = false;
|
|
|
|
|
|
|
|
- state->zero = qi_make_value(QI_NUMBER);
|
|
|
|
|
|
|
+ state->zero = qi_make_uncollectable_value(QI_NUMBER);
|
|
|
state->zero->value.number = 0;
|
|
state->zero->value.number = 0;
|
|
|
|
|
|
|
|
- state->one = qi_make_value(QI_NUMBER);
|
|
|
|
|
|
|
+ state->one = qi_make_uncollectable_value(QI_NUMBER);
|
|
|
state->one->value.number = 1;
|
|
state->one->value.number = 1;
|
|
|
|
|
|
|
|
for (int i = 1; i <= 8; i++)
|
|
for (int i = 1; i <= 8; i++)
|
|
|
{
|
|
{
|
|
|
- state->nnumbers[i - 1] = qi_make_value(QI_NUMBER);
|
|
|
|
|
|
|
+ state->nnumbers[i - 1] = qi_make_uncollectable_value(QI_NUMBER);
|
|
|
state->nnumbers[i - 1]->value.number = -i;
|
|
state->nnumbers[i - 1]->value.number = -i;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -5115,11 +5178,11 @@ static void qi_state_setup(qi_state_t *state)
|
|
|
|
|
|
|
|
for (int i = 2; i < 256; i++)
|
|
for (int i = 2; i < 256; i++)
|
|
|
{
|
|
{
|
|
|
- state->numbers[i] = qi_make_value(QI_NUMBER);
|
|
|
|
|
|
|
+ state->numbers[i] = qi_make_uncollectable_value(QI_NUMBER);
|
|
|
state->numbers[i]->value.number = i;
|
|
state->numbers[i]->value.number = i;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- state->intern_strs = qi_table_make();
|
|
|
|
|
|
|
+ state->intern_strs = qi_table_make_root();
|
|
|
state->intern_strs_mutex = qi_mutex_create();
|
|
state->intern_strs_mutex = qi_mutex_create();
|
|
|
|
|
|
|
|
for (int c = 1; c < 256; c++)
|
|
for (int c = 1; c < 256; c++)
|
|
@@ -5130,58 +5193,61 @@ static void qi_state_setup(qi_state_t *state)
|
|
|
|
|
|
|
|
char *s = qi_strdup(buf);
|
|
char *s = qi_strdup(buf);
|
|
|
|
|
|
|
|
- qi_value_t *value = qi_make_value(QI_STRING);
|
|
|
|
|
|
|
+ qi_value_t *value = qi_make_uncollectable_value(QI_STRING);
|
|
|
value->value.string = s;
|
|
value->value.string = s;
|
|
|
|
|
|
|
|
qi_table_set(state->intern_strs, s, value);
|
|
qi_table_set(state->intern_strs, s, value);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- qi_table_set(state->intern_strs, __recerror_msg, qi_make_string(state, __recerror_msg));
|
|
|
|
|
|
|
+ qi_value_t *recerror_string = qi_make_uncollectable_value(QI_STRING);
|
|
|
|
|
+ recerror_string->value.string = __recerror_msg;
|
|
|
|
|
+
|
|
|
|
|
+ qi_table_set(state->intern_strs, __recerror_msg, recerror_string);
|
|
|
|
|
|
|
|
- state->pseudomethods = qi_table_make();
|
|
|
|
|
|
|
+ state->pseudomethods = qi_table_make_root();
|
|
|
state->pseudomethods_mutex = qi_mutex_create();
|
|
state->pseudomethods_mutex = qi_mutex_create();
|
|
|
|
|
|
|
|
- state->nan = qi_make_value(QI_NUMBER);
|
|
|
|
|
|
|
+ state->nan = qi_make_uncollectable_value(QI_NUMBER);
|
|
|
state->nan->value.number = NAN;
|
|
state->nan->value.number = NAN;
|
|
|
|
|
|
|
|
- state->infinity = qi_make_value(QI_NUMBER);
|
|
|
|
|
|
|
+ state->infinity = qi_make_uncollectable_value(QI_NUMBER);
|
|
|
state->infinity->value.number = INFINITY;
|
|
state->infinity->value.number = INFINITY;
|
|
|
|
|
|
|
|
- state->ninfinity = qi_make_value(QI_NUMBER);
|
|
|
|
|
|
|
+ state->ninfinity = qi_make_uncollectable_value(QI_NUMBER);
|
|
|
state->ninfinity->value.number = -INFINITY;
|
|
state->ninfinity->value.number = -INFINITY;
|
|
|
|
|
|
|
|
- state->empty_string = qi_make_value(QI_STRING);
|
|
|
|
|
|
|
+ state->empty_string = qi_make_uncollectable_value(QI_STRING);
|
|
|
state->empty_string->value.string = qi_strdup("");
|
|
state->empty_string->value.string = qi_strdup("");
|
|
|
|
|
|
|
|
- state->empty_bytes = qi_make_value(QI_BYTES);
|
|
|
|
|
- state->empty_bytes->value.bytes = qi_malloc(sizeof(qi_bytes_t));
|
|
|
|
|
|
|
+ state->empty_bytes = qi_make_uncollectable_value(QI_BYTES);
|
|
|
|
|
+ state->empty_bytes->value.bytes = qi_malloc_atomic(sizeof(qi_bytes_t));
|
|
|
state->empty_bytes->value.bytes->data = (unsigned char *)qi_strdup("");
|
|
state->empty_bytes->value.bytes->data = (unsigned char *)qi_strdup("");
|
|
|
state->empty_bytes->value.bytes->size = 0;
|
|
state->empty_bytes->value.bytes->size = 0;
|
|
|
|
|
|
|
|
- state->empty_tuple = qi_make_value(QI_TUPLE);
|
|
|
|
|
- state->empty_tuple->value.list = qi_list_make();
|
|
|
|
|
|
|
+ state->empty_tuple = qi_make_uncollectable_value(QI_TUPLE);
|
|
|
|
|
+ state->empty_tuple->value.list = qi_list_make_uncollectable();
|
|
|
|
|
|
|
|
- state->_stdin = qi_make_value(QI_FILE);
|
|
|
|
|
|
|
+ state->_stdin = qi_make_uncollectable_value(QI_FILE);
|
|
|
state->_stdin->value.file.fd = stdin;
|
|
state->_stdin->value.file.fd = stdin;
|
|
|
strcpy(state->_stdin->value.file.mode, "r");
|
|
strcpy(state->_stdin->value.file.mode, "r");
|
|
|
state->_stdin->value.file.is_open = true;
|
|
state->_stdin->value.file.is_open = true;
|
|
|
|
|
|
|
|
- state->_stderr = qi_make_value(QI_FILE);
|
|
|
|
|
|
|
+ state->_stderr = qi_make_uncollectable_value(QI_FILE);
|
|
|
state->_stderr->value.file.fd = stderr;
|
|
state->_stderr->value.file.fd = stderr;
|
|
|
strcpy(state->_stderr->value.file.mode, "w");
|
|
strcpy(state->_stderr->value.file.mode, "w");
|
|
|
state->_stderr->value.file.is_open = true;
|
|
state->_stderr->value.file.is_open = true;
|
|
|
|
|
|
|
|
- state->_stdout = qi_make_value(QI_FILE);
|
|
|
|
|
|
|
+ state->_stdout = qi_make_uncollectable_value(QI_FILE);
|
|
|
state->_stdout->value.file.fd = stdout;
|
|
state->_stdout->value.file.fd = stdout;
|
|
|
strcpy(state->_stdout->value.file.mode, "w");
|
|
strcpy(state->_stdout->value.file.mode, "w");
|
|
|
state->_stdout->value.file.is_open = true;
|
|
state->_stdout->value.file.is_open = true;
|
|
|
|
|
|
|
|
- state->traps = qi_list_make();
|
|
|
|
|
- state->exceptions = qi_list_make();
|
|
|
|
|
- state->scopes = qi_list_make();
|
|
|
|
|
|
|
+ state->traps = qi_list_make_root();
|
|
|
|
|
+ state->exceptions = qi_list_make_root();
|
|
|
|
|
+ state->scopes = qi_list_make_root();
|
|
|
qi_new_sticky_scope(state);
|
|
qi_new_sticky_scope(state);
|
|
|
|
|
|
|
|
- state->calltrace = qi_list_make();
|
|
|
|
|
|
|
+ state->calltrace = qi_list_make_root();
|
|
|
state->rlimit = QI_DEFAULT_RLIMIT;
|
|
state->rlimit = QI_DEFAULT_RLIMIT;
|
|
|
|
|
|
|
|
qi_decl_const(state, "nil", state->nil);
|
|
qi_decl_const(state, "nil", state->nil);
|