aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--meson.build1
-rw-r--r--src/boot/boot.janet1
-rw-r--r--src/core/array.c4
-rw-r--r--src/core/capi.c34
-rw-r--r--src/core/compile.c4
-rw-r--r--src/core/corelib.c22
-rw-r--r--src/core/debug.c6
-rw-r--r--src/core/ev.c300
-rw-r--r--src/core/fiber.c26
-rw-r--r--src/core/fiber.h2
-rw-r--r--src/core/gc.c130
-rw-r--r--src/core/math.c11
-rw-r--r--src/core/pp.c2
-rw-r--r--src/core/state.c49
-rw-r--r--src/core/state.h186
-rw-r--r--src/core/symcache.c94
-rw-r--r--src/core/thread.c98
-rw-r--r--src/core/util.c12
-rw-r--r--src/core/value.c40
-rw-r--r--src/core/vm.c158
-rw-r--r--src/core/wrap.c2
-rw-r--r--src/include/janet.h7
23 files changed, 611 insertions, 579 deletions
diff --git a/Makefile b/Makefile
index 2070b1ca..79badc5c 100644
--- a/Makefile
+++ b/Makefile
@@ -113,6 +113,7 @@ JANET_CORE_SOURCES=src/core/abstract.c \
src/core/regalloc.c \
src/core/run.c \
src/core/specials.c \
+ src/core/state.c \
src/core/string.c \
src/core/strtod.c \
src/core/struct.c \
diff --git a/meson.build b/meson.build
index 1327bd1c..b47e9519 100644
--- a/meson.build
+++ b/meson.build
@@ -127,6 +127,7 @@ core_src = [
'src/core/regalloc.c',
'src/core/run.c',
'src/core/specials.c',
+ 'src/core/state.c',
'src/core/string.c',
'src/core/strtod.c',
'src/core/struct.c',
diff --git a/src/boot/boot.janet b/src/boot/boot.janet
index 035c5f24..d7e1bbe2 100644
--- a/src/boot/boot.janet
+++ b/src/boot/boot.janet
@@ -3681,6 +3681,7 @@
"src/core/regalloc.c"
"src/core/run.c"
"src/core/specials.c"
+ "src/core/state.c"
"src/core/string.c"
"src/core/strtod.c"
"src/core/struct.c"
diff --git a/src/core/array.c b/src/core/array.c
index 378f64b0..8e1e3f6b 100644
--- a/src/core/array.c
+++ b/src/core/array.c
@@ -35,7 +35,7 @@ JanetArray *janet_array(int32_t capacity) {
JanetArray *array = janet_gcalloc(JANET_MEMORY_ARRAY, sizeof(JanetArray));
Janet *data = NULL;
if (capacity > 0) {
- janet_vm_next_collection += capacity * sizeof(Janet);
+ janet_vm.next_collection += capacity * sizeof(Janet);
data = (Janet *) janet_malloc(sizeof(Janet) * (size_t) capacity);
if (NULL == data) {
JANET_OUT_OF_MEMORY;
@@ -72,7 +72,7 @@ void janet_array_ensure(JanetArray *array, int32_t capacity, int32_t growth) {
if (NULL == newData) {
JANET_OUT_OF_MEMORY;
}
- janet_vm_next_collection += (capacity - array->capacity) * sizeof(Janet);
+ janet_vm.next_collection += (capacity - array->capacity) * sizeof(Janet);
array->data = newData;
array->capacity = capacity;
}
diff --git a/src/core/capi.c b/src/core/capi.c
index b931676a..c86e9783 100644
--- a/src/core/capi.c
+++ b/src/core/capi.c
@@ -51,15 +51,15 @@ JANET_NO_RETURN static void janet_top_level_signal(const char *msg) {
}
void janet_signalv(JanetSignal sig, Janet message) {
- if (janet_vm_return_reg != NULL) {
- *janet_vm_return_reg = message;
- if (NULL != janet_vm_fiber) {
- janet_vm_fiber->flags |= JANET_FIBER_DID_LONGJUMP;
+ if (janet_vm.return_reg != NULL) {
+ *janet_vm.return_reg = message;
+ if (NULL != janet_vm.fiber) {
+ janet_vm.fiber->flags |= JANET_FIBER_DID_LONGJUMP;
}
#if defined(JANET_BSD) || defined(JANET_APPLE)
- _longjmp(*janet_vm_jmp_buf, sig);
+ _longjmp(*janet_vm.signal_buf, sig);
#else
- longjmp(*janet_vm_jmp_buf, sig);
+ longjmp(*janet_vm.signal_buf, sig);
#endif
} else {
const char *str = (const char *)janet_formatc("janet top level signal - %v\n", message);
@@ -358,26 +358,26 @@ JanetRange janet_getslice(int32_t argc, const Janet *argv) {
}
Janet janet_dyn(const char *name) {
- if (!janet_vm_fiber) {
- if (!janet_vm_top_dyns) return janet_wrap_nil();
- return janet_table_get(janet_vm_top_dyns, janet_ckeywordv(name));
+ if (!janet_vm.fiber) {
+ if (!janet_vm.top_dyns) return janet_wrap_nil();
+ return janet_table_get(janet_vm.top_dyns, janet_ckeywordv(name));
}
- if (janet_vm_fiber->env) {
- return janet_table_get(janet_vm_fiber->env, janet_ckeywordv(name));
+ if (janet_vm.fiber->env) {
+ return janet_table_get(janet_vm.fiber->env, janet_ckeywordv(name));
} else {
return janet_wrap_nil();
}
}
void janet_setdyn(const char *name, Janet value) {
- if (!janet_vm_fiber) {
- if (!janet_vm_top_dyns) janet_vm_top_dyns = janet_table(10);
- janet_table_put(janet_vm_top_dyns, janet_ckeywordv(name), value);
+ if (!janet_vm.fiber) {
+ if (!janet_vm.top_dyns) janet_vm.top_dyns = janet_table(10);
+ janet_table_put(janet_vm.top_dyns, janet_ckeywordv(name), value);
} else {
- if (!janet_vm_fiber->env) {
- janet_vm_fiber->env = janet_table(1);
+ if (!janet_vm.fiber->env) {
+ janet_vm.fiber->env = janet_table(1);
}
- janet_table_put(janet_vm_fiber->env, janet_ckeywordv(name), value);
+ janet_table_put(janet_vm.fiber->env, janet_ckeywordv(name), value);
}
}
diff --git a/src/core/compile.c b/src/core/compile.c
index f906778d..a502b7fa 100644
--- a/src/core/compile.c
+++ b/src/core/compile.c
@@ -944,10 +944,10 @@ JanetCompileResult janet_compile(Janet source, JanetTable *env, const uint8_t *w
/* C Function for compiling */
static Janet cfun(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 4);
- JanetTable *env = argc > 1 ? janet_gettable(argv, 1) : janet_vm_fiber->env;
+ JanetTable *env = argc > 1 ? janet_gettable(argv, 1) : janet_vm.fiber->env;
if (NULL == env) {
env = janet_table(0);
- janet_vm_fiber->env = env;
+ janet_vm.fiber->env = env;
}
const uint8_t *source = NULL;
if (argc >= 3) {
diff --git a/src/core/corelib.c b/src/core/corelib.c
index 4d11e1f5..063c77c5 100644
--- a/src/core/corelib.c
+++ b/src/core/corelib.c
@@ -269,8 +269,8 @@ static Janet janet_core_expand_path(int32_t argc, Janet *argv) {
static Janet janet_core_dyn(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 2);
Janet value;
- if (janet_vm_fiber->env) {
- value = janet_table_get(janet_vm_fiber->env, argv[0]);
+ if (janet_vm.fiber->env) {
+ value = janet_table_get(janet_vm.fiber->env, argv[0]);
} else {
value = janet_wrap_nil();
}
@@ -282,10 +282,10 @@ static Janet janet_core_dyn(int32_t argc, Janet *argv) {
static Janet janet_core_setdyn(int32_t argc, Janet *argv) {
janet_fixarity(argc, 2);
- if (!janet_vm_fiber->env) {
- janet_vm_fiber->env = janet_table(2);
+ if (!janet_vm.fiber->env) {
+ janet_vm.fiber->env = janet_table(2);
}
- janet_table_put(janet_vm_fiber->env, argv[0], argv[1]);
+ janet_table_put(janet_vm.fiber->env, argv[0], argv[1]);
return argv[1];
}
@@ -428,14 +428,14 @@ static Janet janet_core_gcsetinterval(int32_t argc, Janet *argv) {
janet_panic("interval too large");
}
#endif
- janet_vm_gc_interval = s;
+ janet_vm.gc_interval = s;
return janet_wrap_nil();
}
static Janet janet_core_gcinterval(int32_t argc, Janet *argv) {
(void) argv;
janet_fixarity(argc, 0);
- return janet_wrap_number((double) janet_vm_gc_interval);
+ return janet_wrap_number((double) janet_vm.gc_interval);
}
static Janet janet_core_type(int32_t argc, Janet *argv) {
@@ -1215,8 +1215,8 @@ JanetTable *janet_core_env(JanetTable *replacements) {
JanetTable *janet_core_env(JanetTable *replacements) {
/* Memoize core env, ignoring replacements the second time around. */
- if (NULL != janet_vm_core_env) {
- return janet_vm_core_env;
+ if (NULL != janet_vm.core_env) {
+ return janet_vm.core_env;
}
JanetTable *dict = janet_core_lookup_table(replacements);
@@ -1232,7 +1232,7 @@ JanetTable *janet_core_env(JanetTable *replacements) {
/* Memoize */
janet_gcroot(marsh_out);
JanetTable *env = janet_unwrap_table(marsh_out);
- janet_vm_core_env = env;
+ janet_vm.core_env = env;
/* Invert image dict manually here. We can't do this in boot.janet as it
* breaks deterministic builds */
@@ -1265,7 +1265,7 @@ JanetTable *janet_core_lookup_table(JanetTable *replacements) {
if (!janet_checktype(kv.key, JANET_NIL)) {
janet_table_put(dict, kv.key, kv.value);
if (janet_checktype(kv.value, JANET_CFUNCTION)) {
- janet_table_put(janet_vm_registry, kv.value, kv.key);
+ janet_table_put(janet_vm.registry, kv.value, kv.key);
}
}
}
diff --git a/src/core/debug.c b/src/core/debug.c
index 5d4b1fc9..ff4b55f8 100644
--- a/src/core/debug.c
+++ b/src/core/debug.c
@@ -55,7 +55,7 @@ void janet_debug_find(
JanetFuncDef **def_out, int32_t *pc_out,
const uint8_t *source, int32_t sourceLine, int32_t sourceColumn) {
/* Scan the heap for right func def */
- JanetGCObject *current = janet_vm_blocks;
+ JanetGCObject *current = janet_vm.blocks;
/* Keep track of the best source mapping we have seen so far */
int32_t besti = -1;
int32_t best_line = -1;
@@ -144,7 +144,7 @@ void janet_stacktrace(JanetFiber *fiber, Janet err) {
} else {
JanetCFunction cfun = (JanetCFunction)(frame->pc);
if (cfun) {
- Janet name = janet_table_get(janet_vm_registry, janet_wrap_cfunction(cfun));
+ Janet name = janet_table_get(janet_vm.registry, janet_wrap_cfunction(cfun));
if (!janet_checktype(name, JANET_NIL))
janet_eprintf(" %s", (const char *)janet_to_string(name));
else
@@ -252,7 +252,7 @@ static Janet doframe(JanetStackFrame *frame) {
} else {
JanetCFunction cfun = (JanetCFunction)(frame->pc);
if (cfun) {
- Janet name = janet_table_get(janet_vm_registry, janet_wrap_cfunction(cfun));
+ Janet name = janet_table_get(janet_vm.registry, janet_wrap_cfunction(cfun));
if (!janet_checktype(name, JANET_NIL)) {
janet_table_put(t, janet_ckeywordv("name"), name);
}
diff --git a/src/core/ev.c b/src/core/ev.c
index b13c4037..93381bf7 100644
--- a/src/core/ev.c
+++ b/src/core/ev.c
@@ -56,12 +56,6 @@
#endif
/* Ring buffer for storing a list of fibers */
-typedef struct {
- int32_t capacity;
- int32_t head;
- int32_t tail;
- void *data;
-} JanetQueue;
typedef struct {
JanetFiber *fiber;
@@ -143,31 +137,9 @@ struct JanetTask {
JanetSignal sig;
};
-/* Min priority queue of timestamps for timeouts. */
-typedef int64_t JanetTimestamp;
-typedef struct JanetTimeout JanetTimeout;
-struct JanetTimeout {
- JanetTimestamp when;
- JanetFiber *fiber;
- JanetFiber *curr_fiber;
- uint32_t sched_id;
- int is_error;
-};
-
/* Forward declaration */
static void janet_unlisten(JanetListenerState *state);
-/* Global data */
-JANET_THREAD_LOCAL size_t janet_vm_tq_count = 0;
-JANET_THREAD_LOCAL size_t janet_vm_tq_capacity = 0;
-JANET_THREAD_LOCAL JanetQueue janet_vm_spawn;
-JANET_THREAD_LOCAL JanetTimeout *janet_vm_tq = NULL;
-JANET_THREAD_LOCAL JanetRNG janet_vm_ev_rng;
-JANET_THREAD_LOCAL JanetListenerState **janet_vm_listeners = NULL;
-JANET_THREAD_LOCAL size_t janet_vm_listener_count = 0;
-JANET_THREAD_LOCAL size_t janet_vm_listener_cap = 0;
-JANET_THREAD_LOCAL size_t janet_vm_extra_listeners = 0;
-
/* Get current timestamp (millisecond precision) */
static JanetTimestamp ts_now(void);
@@ -180,58 +152,58 @@ static JanetTimestamp ts_delta(JanetTimestamp ts, double delta) {
/* Look at the next timeout value without
* removing it. */
static int peek_timeout(JanetTimeout *out) {
- if (janet_vm_tq_count == 0) return 0;
- *out = janet_vm_tq[0];
+ if (janet_vm.tq_count == 0) return 0;
+ *out = janet_vm.tq[0];
return 1;
}
/* Remove the next timeout from the priority queue */
static void pop_timeout(size_t index) {
- if (janet_vm_tq_count <= index) return;
- janet_vm_tq[index] = janet_vm_tq[--janet_vm_tq_count];
+ if (janet_vm.tq_count <= index) return;
+ janet_vm.tq[index] = janet_vm.tq[--janet_vm.tq_count];
for (;;) {
size_t left = (index << 1) + 1;
size_t right = left + 1;
size_t smallest = index;
- if (left < janet_vm_tq_count &&
- (janet_vm_tq[left].when < janet_vm_tq[smallest].when))
+ if (left < janet_vm.tq_count &&
+ (janet_vm.tq[left].when < janet_vm.tq[smallest].when))
smallest = left;
- if (right < janet_vm_tq_count &&
- (janet_vm_tq[right].when < janet_vm_tq[smallest].when))
+ if (right < janet_vm.tq_count &&
+ (janet_vm.tq[right].when < janet_vm.tq[smallest].when))
smallest = right;
if (smallest == index) return;
- JanetTimeout temp = janet_vm_tq[index];
- janet_vm_tq[index] = janet_vm_tq[smallest];
- janet_vm_tq[smallest] = temp;
+ JanetTimeout temp = janet_vm.tq[index];
+ janet_vm.tq[index] = janet_vm.tq[smallest];
+ janet_vm.tq[smallest] = temp;
index = smallest;
}
}
/* Add a timeout to the timeout min heap */
static void add_timeout(JanetTimeout to) {
- size_t oldcount = janet_vm_tq_count;
+ size_t oldcount = janet_vm.tq_count;
size_t newcount = oldcount + 1;
- if (newcount > janet_vm_tq_capacity) {
+ if (newcount > janet_vm.tq_capacity) {
size_t newcap = 2 * newcount;
- JanetTimeout *tq = janet_realloc(janet_vm_tq, newcap * sizeof(JanetTimeout));
+ JanetTimeout *tq = janet_realloc(janet_vm.tq, newcap * sizeof(JanetTimeout));
if (NULL == tq) {
JANET_OUT_OF_MEMORY;
}
- janet_vm_tq = tq;
- janet_vm_tq_capacity = newcap;
+ janet_vm.tq = tq;
+ janet_vm.tq_capacity = newcap;
}
/* Append */
- janet_vm_tq_count = (int32_t) newcount;
- janet_vm_tq[oldcount] = to;
+ janet_vm.tq_count = (int32_t) newcount;
+ janet_vm.tq[oldcount] = to;
/* Heapify */
size_t index = oldcount;
while (index > 0) {
size_t parent = (index - 1) >> 1;
- if (janet_vm_tq[parent].when <= janet_vm_tq[index].when) break;
+ if (janet_vm.tq[parent].when <= janet_vm.tq[index].when) break;
/* Swap */
- JanetTimeout tmp = janet_vm_tq[index];
- janet_vm_tq[index] = janet_vm_tq[parent];
- janet_vm_tq[parent] = tmp;
+ JanetTimeout tmp = janet_vm.tq[index];
+ janet_vm.tq[index] = janet_vm.tq[parent];
+ janet_vm.tq[parent] = tmp;
/* Next */
index = parent;
}
@@ -242,7 +214,7 @@ static JanetListenerState *janet_listen_impl(JanetStream *stream, JanetListener
if (stream->_mask & mask) {
janet_panic("cannot listen for duplicate event on stream");
}
- if (janet_vm_root_fiber->waiting != NULL) {
+ if (janet_vm.root_fiber->waiting != NULL) {
janet_panic("current fiber is already waiting for event");
}
if (size < sizeof(JanetListenerState))
@@ -252,8 +224,8 @@ static JanetListenerState *janet_listen_impl(JanetStream *stream, JanetListener
JANET_OUT_OF_MEMORY;
}
state->machine = behavior;
- state->fiber = janet_vm_root_fiber;
- janet_vm_root_fiber->waiting = state;
+ state->fiber = janet_vm.root_fiber;
+ janet_vm.root_fiber->waiting = state;
state->stream = stream;
state->_mask = mask;
stream->_mask |= mask;
@@ -261,17 +233,17 @@ static JanetListenerState *janet_listen_impl(JanetStream *stream, JanetListener
stream->state = state;
/* Keep track of a listener for GC purposes */
- int resize = janet_vm_listener_cap == janet_vm_listener_count;
+ int resize = janet_vm.listener_cap == janet_vm.listener_count;
if (resize) {
- size_t newcap = janet_vm_listener_count ? janet_vm_listener_cap * 2 : 16;
- janet_vm_listeners = janet_realloc(janet_vm_listeners, newcap * sizeof(JanetListenerState *));
- if (NULL == janet_vm_listeners) {
+ size_t newcap = janet_vm.listener_count ? janet_vm.listener_cap * 2 : 16;
+ janet_vm.listeners = janet_realloc(janet_vm.listeners, newcap * sizeof(JanetListenerState *));
+ if (NULL == janet_vm.listeners) {
JANET_OUT_OF_MEMORY;
}
- janet_vm_listener_cap = newcap;
+ janet_vm.listener_cap = newcap;
}
- size_t index = janet_vm_listener_count++;
- janet_vm_listeners[index] = state;
+ size_t index = janet_vm.listener_count++;
+ janet_vm.listeners[index] = state;
state->_index = index;
/* Emit INIT event for convenience */
@@ -299,8 +271,8 @@ static void janet_unlisten_impl(JanetListenerState *state) {
}
/* Untrack a listener for gc purposes */
size_t index = state->_index;
- janet_vm_listeners[index] = janet_vm_listeners[--janet_vm_listener_count];
- janet_vm_listeners[index]->_index = index;
+ janet_vm.listeners[index] = janet_vm.listeners[--janet_vm.listener_count];
+ janet_vm.listeners[index]->_index = index;
janet_free(state);
}
@@ -459,7 +431,7 @@ void janet_schedule_signal(JanetFiber *fiber, Janet value, JanetSignal sig) {
fiber->flags |= JANET_FIBER_FLAG_SCHEDULED;
fiber->sched_id++;
JanetTask t = { fiber, value, sig };
- janet_q_push(&janet_vm_spawn, &t, sizeof(t));
+ janet_q_push(&janet_vm.spawn, &t, sizeof(t));
}
void janet_cancel(JanetFiber *fiber, Janet value) {
@@ -482,34 +454,34 @@ void janet_fiber_did_resume(JanetFiber *fiber) {
void janet_ev_mark(void) {
/* Pending tasks */
- JanetTask *tasks = janet_vm_spawn.data;
- if (janet_vm_spawn.head <= janet_vm_spawn.tail) {
- for (int32_t i = janet_vm_spawn.head; i < janet_vm_spawn.tail; i++) {
+ JanetTask *tasks = janet_vm.spawn.data;
+ if (janet_vm.spawn.head <= janet_vm.spawn.tail) {
+ for (int32_t i = janet_vm.spawn.head; i < janet_vm.spawn.tail; i++) {
janet_mark(janet_wrap_fiber(tasks[i].fiber));
janet_mark(tasks[i].value);
}
} else {
- for (int32_t i = janet_vm_spawn.head; i < janet_vm_spawn.capacity; i++) {
+ for (int32_t i = janet_vm.spawn.head; i < janet_vm.spawn.capacity; i++) {
janet_mark(janet_wrap_fiber(tasks[i].fiber));
janet_mark(tasks[i].value);
}
- for (int32_t i = 0; i < janet_vm_spawn.tail; i++) {
+ for (int32_t i = 0; i < janet_vm.spawn.tail; i++) {
janet_mark(janet_wrap_fiber(tasks[i].fiber));
janet_mark(tasks[i].value);
}
}
/* Pending timeouts */
- for (size_t i = 0; i < janet_vm_tq_count; i++) {
- janet_mark(janet_wrap_fiber(janet_vm_tq[i].fiber));
- if (janet_vm_tq[i].curr_fiber != NULL) {
- janet_mark(janet_wrap_fiber(janet_vm_tq[i].curr_fiber));
+ for (size_t i = 0; i < janet_vm.tq_count; i++) {
+ janet_mark(janet_wrap_fiber(janet_vm.tq[i].fiber));
+ if (janet_vm.tq[i].curr_fiber != NULL) {
+ janet_mark(janet_wrap_fiber(janet_vm.tq[i].curr_fiber));
}
}
/* Pending listeners */
- for (size_t i = 0; i < janet_vm_listener_count; i++) {
- JanetListenerState *state = janet_vm_listeners[i];
+ for (size_t i = 0; i < janet_vm.listener_count; i++) {
+ JanetListenerState *state = janet_vm.listeners[i];
if (NULL != state->fiber) {
janet_mark(janet_wrap_fiber(state->fiber));
}
@@ -544,22 +516,22 @@ static void run_one(JanetFiber *fiber, Janet value, JanetSignal sigin) {
/* Common init code */
void janet_ev_init_common(void) {
- janet_q_init(&janet_vm_spawn);
- janet_vm_listener_count = 0;
- janet_vm_listener_cap = 0;
- janet_vm_listeners = NULL;
- janet_vm_tq = NULL;
- janet_vm_tq_count = 0;
- janet_vm_tq_capacity = 0;
- janet_rng_seed(&janet_vm_ev_rng, 0);
+ janet_q_init(&janet_vm.spawn);
+ janet_vm.listener_count = 0;
+ janet_vm.listener_cap = 0;
+ janet_vm.listeners = NULL;
+ janet_vm.tq = NULL;
+ janet_vm.tq_count = 0;
+ janet_vm.tq_capacity = 0;
+ janet_rng_seed(&janet_vm.ev_rng, 0);
}
/* Common deinit code */
void janet_ev_deinit_common(void) {
- janet_q_deinit(&janet_vm_spawn);
- janet_free(janet_vm_tq);
- janet_free(janet_vm_listeners);
- janet_vm_listeners = NULL;
+ janet_q_deinit(&janet_vm.spawn);
+ janet_free(janet_vm.tq);
+ janet_free(janet_vm.listeners);
+ janet_vm.listeners = NULL;
}
/* Short hand to yield to event loop */
@@ -569,7 +541,7 @@ void janet_await(void) {
/* Set timeout for the current root fiber */
void janet_addtimeout(double sec) {
- JanetFiber *fiber = janet_vm_root_fiber;
+ JanetFiber *fiber = janet_vm.root_fiber;
JanetTimeout to;
to.when = ts_delta(ts_now(), sec);
to.fiber = fiber;
@@ -580,11 +552,11 @@ void janet_addtimeout(double sec) {
}
void janet_ev_inc_refcount(void) {
- janet_vm_extra_listeners++;
+ janet_vm.extra_listeners++;
}
void janet_ev_dec_refcount(void) {
- janet_vm_extra_listeners--;
+ janet_vm.extra_listeners--;
}
/* Channels */
@@ -699,8 +671,8 @@ static int janet_channel_push(JanetChannel *channel, Janet x, int mode) {
if (mode == 2) return 0;
/* Pushed successfully, but should block. */
JanetChannelPending pending;
- pending.fiber = janet_vm_root_fiber,
- pending.sched_id = janet_vm_root_fiber->sched_id,
+ pending.fiber = janet_vm.root_fiber,
+ pending.sched_id = janet_vm.root_fiber->sched_id,
pending.mode = mode ? JANET_CP_MODE_CHOICE_WRITE : JANET_CP_MODE_ITEM;
janet_q_push(&channel->write_pending, &pending, sizeof(pending));
return 1;
@@ -724,8 +696,8 @@ static int janet_channel_pop(JanetChannel *channel, Janet *item, int is_choice)
if (janet_q_pop(&channel->items, item, sizeof(Janet))) {
/* Queue empty */
JanetChannelPending pending;
- pending.fiber = janet_vm_root_fiber,
- pending.sched_id = janet_vm_root_fiber->sched_id;
+ pending.fiber = janet_vm.root_fiber,
+ pending.sched_id = janet_vm.root_fiber->sched_id;
pending.mode = is_choice ? JANET_CP_MODE_CHOICE_READ : JANET_CP_MODE_ITEM;
janet_q_push(&channel->read_pending, &pending, sizeof(pending));
return 0;
@@ -757,7 +729,7 @@ static Janet cfun_channel_pop(int32_t argc, Janet *argv) {
JanetChannel *channel = janet_getabstract(argv, 0, &ChannelAT);
Janet item;
if (janet_channel_pop(channel, &item, 0)) {
- janet_schedule(janet_vm_root_fiber, item);
+ janet_schedule(janet_vm.root_fiber, item);
}
janet_await();
}
@@ -825,7 +797,7 @@ static Janet cfun_channel_count(int32_t argc, Janet *argv) {
/* Fisher yates shuffle of arguments to get fairness */
static void fisher_yates_args(int32_t argc, Janet *argv) {
for (int32_t i = argc; i > 1; i--) {
- int32_t swap_index = janet_rng_u32(&janet_vm_ev_rng) % i;
+ int32_t swap_index = janet_rng_u32(&janet_vm.ev_rng) % i;
Janet temp = argv[swap_index];
argv[swap_index] = argv[i - 1];
argv[i - 1] = temp;
@@ -903,14 +875,14 @@ void janet_loop1(void) {
}
/* Run scheduled fibers */
- while (janet_vm_spawn.head != janet_vm_spawn.tail) {
+ while (janet_vm.spawn.head != janet_vm.spawn.tail) {
JanetTask task = {NULL, janet_wrap_nil(), JANET_SIGNAL_OK};
- janet_q_pop(&janet_vm_spawn, &task, sizeof(task));
+ janet_q_pop(&janet_vm.spawn, &task, sizeof(task));
run_one(task.fiber, task.value, task.sig);
}
/* Poll for events */
- if (janet_vm_listener_count || janet_vm_tq_count || janet_vm_extra_listeners) {
+ if (janet_vm.listener_count || janet_vm.tq_count || janet_vm.extra_listeners) {
JanetTimeout to;
memset(&to, 0, sizeof(to));
int has_timeout;
@@ -919,14 +891,14 @@ void janet_loop1(void) {
pop_timeout(0);
}
/* Run polling implementation only if pending timeouts or pending events */
- if (janet_vm_tq_count || janet_vm_listener_count || janet_vm_extra_listeners) {
+ if (janet_vm.tq_count || janet_vm.listener_count || janet_vm.extra_listeners) {
janet_loop1_impl(has_timeout, to.when);
}
}
}
void janet_loop(void) {
- while (janet_vm_listener_count || (janet_vm_spawn.head != janet_vm_spawn.tail) || janet_vm_tq_count || janet_vm_extra_listeners) {
+ while (janet_vm.listener_count || (janet_vm.spawn.head != janet_vm.spawn.tail) || janet_vm.tq_count || janet_vm.extra_listeners) {
janet_loop1();
}
}
@@ -958,10 +930,8 @@ typedef struct {
#else
-static JANET_THREAD_LOCAL JanetHandle janet_vm_selfpipe[2];
-
static void janet_ev_setup_selfpipe(void) {
- if (janet_make_pipe(janet_vm_selfpipe, 0)) {
+ if (janet_make_pipe(janet_vm.selfpipe, 0)) {
JANET_EXIT("failed to initialize self pipe in event loop");
}
}
@@ -969,43 +939,41 @@ static void janet_ev_setup_selfpipe(void) {
/* Handle events from the self pipe inside the event loop */
static void janet_ev_handle_selfpipe(void) {
JanetSelfPipeEvent response;
- while (read(janet_vm_selfpipe[0], &response, sizeof(response)) > 0) {
+ while (read(janet_vm.selfpipe[0], &response, sizeof(response)) > 0) {
response.cb(response.msg);
janet_ev_dec_refcount();
}
}
static void janet_ev_cleanup_selfpipe(void) {
- close(janet_vm_selfpipe[0]);
- close(janet_vm_selfpipe[1]);
+ close(janet_vm.selfpipe[0]);
+ close(janet_vm.selfpipe[1]);
}
#endif
#ifdef JANET_WINDOWS
-JANET_THREAD_LOCAL HANDLE janet_vm_iocp = NULL;
-
static JanetTimestamp ts_now(void) {
return (JanetTimestamp) GetTickCount64();
}
void janet_ev_init(void) {
janet_ev_init_common();
- janet_vm_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
- if (NULL == janet_vm_iocp) janet_panic("could not create io completion port");
+ janet_vm.iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
+ if (NULL == janet_vm.iocp) janet_panic("could not create io completion port");
}
void janet_ev_deinit(void) {
janet_ev_deinit_common();
- CloseHandle(janet_vm_iocp);
+ CloseHandle(janet_vm.iocp);
}
JanetListenerState *janet_listen(JanetStream *stream, JanetListener behavior, int mask, size_t size, void *user) {
/* Add the handle to the io completion port if not already added */
JanetListenerState *state = janet_listen_impl(stream, behavior, mask, size, user);
if (!(stream->flags & JANET_STREAM_IOCP)) {
- if (NULL == CreateIoCompletionPort(stream->handle, janet_vm_iocp, (ULONG_PTR) stream, 0)) {
+ if (NULL == CreateIoCompletionPort(stream->handle, janet_vm.iocp, (ULONG_PTR) stream, 0)) {
janet_panicf("failed to listen for events: %V", janet_ev_lasterr());
}
stream->flags |= JANET_STREAM_IOCP;
@@ -1035,7 +1003,7 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp to) {
} else {
waittime = INFINITE;
}
- BOOL result = GetQueuedCompletionStatus(janet_vm_iocp, &num_bytes_transfered, &completionKey, &overlapped, (DWORD) waittime);
+ BOOL result = GetQueuedCompletionStatus(janet_vm.iocp, &num_bytes_transfered, &completionKey, &overlapped, (DWORD) waittime);
if (result || overlapped) {
if (0 == completionKey) {
@@ -1067,10 +1035,6 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp to) {
#elif defined(JANET_EV_EPOLL)
-JANET_THREAD_LOCAL int janet_vm_epoll = 0;
-JANET_THREAD_LOCAL int janet_vm_timerfd = 0;
-JANET_THREAD_LOCAL int janet_vm_timer_enabled = 0;
-
static JanetTimestamp ts_now(void) {
struct timespec now;
janet_assert(-1 != clock_gettime(CLOCK_MONOTONIC, &now), "failed to get time");
@@ -1098,7 +1062,7 @@ JanetListenerState *janet_listen(JanetStream *stream, JanetListener behavior, in
ev.data.ptr = stream;
int status;
do {
- status = epoll_ctl(janet_vm_epoll, op, stream->handle, &ev);
+ status = epoll_ctl(janet_vm.epoll, op, stream->handle, &ev);
} while (status == -1 && errno == EINTR);
if (status == -1) {
janet_unlisten_impl(state);
@@ -1118,7 +1082,7 @@ static void janet_unlisten(JanetListenerState *state) {
ev.data.ptr = stream;
int status;
do {
- status = epoll_ctl(janet_vm_epoll, op, stream->handle, &ev);
+ status = epoll_ctl(janet_vm.epoll, op, stream->handle, &ev);
} while (status == -1 && errno == EINTR);
if (status == -1) {
janet_panicv(janet_ev_lasterr());
@@ -1131,21 +1095,21 @@ static void janet_unlisten(JanetListenerState *state) {
#define JANET_EPOLL_MAX_EVENTS 64
void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
struct itimerspec its;
- if (janet_vm_timer_enabled || has_timeout) {
+ if (janet_vm.timer_enabled || has_timeout) {
memset(&its, 0, sizeof(its));
if (has_timeout) {
its.it_value.tv_sec = timeout / 1000;
its.it_value.tv_nsec = (timeout % 1000) * 1000000;
}
- timerfd_settime(janet_vm_timerfd, TFD_TIMER_ABSTIME, &its, NULL);
+ timerfd_settime(janet_vm.timerfd, TFD_TIMER_ABSTIME, &its, NULL);
}
- janet_vm_timer_enabled = has_timeout;
+ janet_vm.timer_enabled = has_timeout;
/* Poll for events */
struct epoll_event events[JANET_EPOLL_MAX_EVENTS];
int ready;
do {
- ready = epoll_wait(janet_vm_epoll, events, JANET_EPOLL_MAX_EVENTS, -1);
+ ready = epoll_wait(janet_vm.epoll, events, JANET_EPOLL_MAX_EVENTS, -1);
} while (ready == -1 && errno == EINTR);
if (ready == -1) {
JANET_EXIT("failed to poll events");
@@ -1154,9 +1118,9 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
/* Step state machines */
for (int i = 0; i < ready; i++) {
void *p = events[i].data.ptr;
- if (&janet_vm_timerfd == p) {
+ if (&janet_vm.timerfd == p) {
/* Timer expired, ignore */;
- } else if (janet_vm_selfpipe == p) {
+ } else if (janet_vm.selfpipe == p) {
/* Self-pipe handling */
janet_ev_handle_selfpipe();
} else {
@@ -1192,17 +1156,17 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
void janet_ev_init(void) {
janet_ev_init_common();
janet_ev_setup_selfpipe();
- janet_vm_epoll = epoll_create1(EPOLL_CLOEXEC);
- janet_vm_timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
- janet_vm_timer_enabled = 0;
- if (janet_vm_epoll == -1 || janet_vm_timerfd == -1) goto error;
+ janet_vm.epoll = epoll_create1(EPOLL_CLOEXEC);
+ janet_vm.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
+ janet_vm.timer_enabled = 0;
+ if (janet_vm.epoll == -1 || janet_vm.timerfd == -1) goto error;
struct epoll_event ev;
ev.events = EPOLLIN | EPOLLET;
- ev.data.ptr = &janet_vm_timerfd;
- if (-1 == epoll_ctl(janet_vm_epoll, EPOLL_CTL_ADD, janet_vm_timerfd, &ev)) goto error;
+ ev.data.ptr = &janet_vm.timerfd;
+ if (-1 == epoll_ctl(janet_vm.epoll, EPOLL_CTL_ADD, janet_vm.timerfd, &ev)) goto error;
ev.events = EPOLLIN | EPOLLET;
- ev.data.ptr = janet_vm_selfpipe;
- if (-1 == epoll_ctl(janet_vm_epoll, EPOLL_CTL_ADD, janet_vm_selfpipe[0], &ev)) goto error;
+ ev.data.ptr = janet_vm.selfpipe;
+ if (-1 == epoll_ctl(janet_vm.epoll, EPOLL_CTL_ADD, janet_vm.selfpipe[0], &ev)) goto error;
return;
error:
JANET_EXIT("failed to initialize event loop");
@@ -1210,10 +1174,10 @@ error:
void janet_ev_deinit(void) {
janet_ev_deinit_common();
- close(janet_vm_epoll);
- close(janet_vm_timerfd);
+ close(janet_vm.epoll);
+ close(janet_vm.timerfd);
janet_ev_cleanup_selfpipe();
- janet_vm_epoll = 0;
+ janet_vm.epoll = 0;
}
/*
@@ -1224,8 +1188,6 @@ void janet_ev_deinit(void) {
#include <poll.h>
-JANET_THREAD_LOCAL struct pollfd *janet_vm_fds = NULL;
-
static JanetTimestamp ts_now(void) {
struct timespec now;
janet_assert(-1 != clock_gettime(CLOCK_REALTIME, &now), "failed to get time");
@@ -1245,12 +1207,12 @@ static int make_poll_events(int mask) {
/* Wait for the next event */
JanetListenerState *janet_listen(JanetStream *stream, JanetListener behavior, int mask, size_t size, void *user) {
- size_t oldsize = janet_vm_listener_cap;
+ size_t oldsize = janet_vm.listener_cap;
JanetListenerState *state = janet_listen_impl(stream, behavior, mask, size, user);
- size_t newsize = janet_vm_listener_cap;
+ size_t newsize = janet_vm.listener_cap;
if (newsize > oldsize) {
- janet_vm_fds = janet_realloc(janet_vm_fds, (newsize + 1) * sizeof(struct pollfd));
- if (NULL == janet_vm_fds) {
+ janet_vm.fds = janet_realloc(janet_vm.fds, (newsize + 1) * sizeof(struct pollfd));
+ if (NULL == janet_vm.fds) {
JANET_OUT_OF_MEMORY;
}
}
@@ -1258,12 +1220,12 @@ JanetListenerState *janet_listen(JanetStream *stream, JanetListener behavior, in
ev.fd = stream->handle;
ev.events = make_poll_events(state->stream->_mask);
ev.revents = 0;
- janet_vm_fds[state->_index + 1] = ev;
+ janet_vm.fds[state->_index + 1] = ev;
return state;
}
static void janet_unlisten(JanetListenerState *state) {
- janet_vm_fds[state->_index + 1] = janet_vm_fds[janet_vm_listener_count];
+ janet_vm.fds[state->_index + 1] = janet_vm.fds[janet_vm.listener_count];
janet_unlisten_impl(state);
}
@@ -1276,23 +1238,23 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
JanetTimestamp now = ts_now();
to = now > timeout ? 0 : (int)(timeout - now);
}
- ready = poll(janet_vm_fds, janet_vm_listener_count + 1, to);
+ ready = poll(janet_vm.fds, janet_vm.listener_count + 1, to);
} while (ready == -1 && errno == EINTR);
if (ready == -1) {
JANET_EXIT("failed to poll events");
}
/* Check selfpipe */
- if (janet_vm_fds[0].revents & POLLIN) {
- janet_vm_fds[0].revents = 0;
+ if (janet_vm.fds[0].revents & POLLIN) {
+ janet_vm.fds[0].revents = 0;
janet_ev_handle_selfpipe();
}
/* Step state machines */
- for (size_t i = 0; i < janet_vm_listener_count; i++) {
- struct pollfd *pfd = janet_vm_fds + i + 1;
+ for (size_t i = 0; i < janet_vm.listener_count; i++) {
+ struct pollfd *pfd = janet_vm.fds + i + 1;
/* Skip fds where nothing interesting happened */
- JanetListenerState *state = janet_vm_listeners[i];
+ JanetListenerState *state = janet_vm.listeners[i];
/* Normal event */
int mask = pfd->revents;
JanetAsyncStatus status1 = JANET_ASYNC_STATUS_NOT_DONE;
@@ -1318,23 +1280,23 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
void janet_ev_init(void) {
janet_ev_init_common();
- janet_vm_fds = NULL;
+ janet_vm.fds = NULL;
janet_ev_setup_selfpipe();
- janet_vm_fds = janet_malloc(sizeof(struct pollfd));
- if (NULL == janet_vm_fds) {
+ janet_vm.fds = janet_malloc(sizeof(struct pollfd));
+ if (NULL == janet_vm.fds) {
JANET_OUT_OF_MEMORY;
}
- janet_vm_fds[0].fd = janet_vm_selfpipe[0];
- janet_vm_fds[0].events = POLLIN;
- janet_vm_fds[0].revents = 0;
+ janet_vm.fds[0].fd = janet_vm.selfpipe[0];
+ janet_vm.fds[0].events = POLLIN;
+ janet_vm.fds[0].revents = 0;
return;
}
void janet_ev_deinit(void) {
janet_ev_deinit_common();
janet_ev_cleanup_selfpipe();
- janet_free(janet_vm_fds);
- janet_vm_fds = NULL;
+ janet_free(janet_vm.fds);
+ janet_vm.fds = NULL;
}
#endif
@@ -1400,7 +1362,7 @@ void janet_ev_threaded_call(JanetThreadedSubroutine fp, JanetEVGenericMessage ar
init->cb = cb;
#ifdef JANET_WINDOWS
- init->write_pipe = janet_vm_iocp;
+ init->write_pipe = janet_vm.iocp;
HANDLE thread_handle = CreateThread(NULL, 0, janet_thread_body, init, 0, NULL);
if (NULL == thread_handle) {
janet_free(init);
@@ -1408,7 +1370,7 @@ void janet_ev_threaded_call(JanetThreadedSubroutine fp, JanetEVGenericMessage ar
}
CloseHandle(thread_handle); /* detach from thread */
#else
- init->write_pipe = janet_vm_selfpipe[1];
+ init->write_pipe = janet_vm.selfpipe[1];
pthread_t waiter_thread;
int err = pthread_create(&waiter_thread, NULL, janet_thread_body, init);
if (err) {
@@ -2040,7 +2002,7 @@ static Janet cfun_ev_go(int32_t argc, Janet *argv) {
JanetFiber *fiber = janet_getfiber(argv, 0);
Janet value = argc >= 2 ? argv[1] : janet_wrap_nil();
JanetChannel *supervisor_channel = janet_optabstract(argv, argc, 2, &ChannelAT,
- janet_vm_root_fiber->supervisor_channel);
+ janet_vm.root_fiber->supervisor_channel);
fiber->supervisor_channel = supervisor_channel;
janet_schedule(fiber, value);
return argv[0];
@@ -2058,11 +2020,11 @@ static JanetEVGenericMessage janet_go_thread_subr(JanetEVGenericMessage args) {
Janet aregv = janet_unmarshal(nextbytes, endbytes - nextbytes,
JANET_MARSHAL_UNSAFE, NULL, &nextbytes);
if (!janet_checktype(aregv, JANET_TABLE)) janet_panic("expected table for abstract registry");
- janet_vm_abstract_registry = janet_unwrap_table(aregv);
+ janet_vm.abstract_registry = janet_unwrap_table(aregv);
Janet regv = janet_unmarshal(nextbytes, endbytes - nextbytes,
JANET_MARSHAL_UNSAFE, NULL, &nextbytes);
if (!janet_checktype(regv, JANET_TABLE)) janet_panic("expected table for cfunction registry");
- janet_vm_registry = janet_unwrap_table(regv);
+ janet_vm.registry = janet_unwrap_table(regv);
Janet fiberv = janet_unmarshal(nextbytes, endbytes - nextbytes,
JANET_MARSHAL_UNSAFE, NULL, &nextbytes);
Janet value = janet_unmarshal(nextbytes, endbytes - nextbytes,
@@ -2097,8 +2059,8 @@ static Janet cfun_ev_thread(int32_t argc, Janet *argv) {
JANET_OUT_OF_MEMORY;
}
janet_buffer_init(buffer, 0);
- janet_marshal(buffer, janet_wrap_table(janet_vm_abstract_registry), NULL, JANET_MARSHAL_UNSAFE);
- janet_marshal(buffer, janet_wrap_table(janet_vm_registry), NULL, JANET_MARSHAL_UNSAFE);
+ janet_marshal(buffer, janet_wrap_table(janet_vm.abstract_registry), NULL, JANET_MARSHAL_UNSAFE);
+ janet_marshal(buffer, janet_wrap_table(janet_vm.registry), NULL, JANET_MARSHAL_UNSAFE);
janet_marshal(buffer, argv[0], NULL, JANET_MARSHAL_UNSAFE);
janet_marshal(buffer, value, NULL, JANET_MARSHAL_UNSAFE);
janet_ev_threaded_await(janet_go_thread_subr, 0, argc, buffer);
@@ -2106,7 +2068,7 @@ static Janet cfun_ev_thread(int32_t argc, Janet *argv) {
static Janet cfun_ev_give_supervisor(int32_t argc, Janet *argv) {
janet_arity(argc, 1, -1);
- JanetChannel *chan = janet_vm_root_fiber->supervisor_channel;
+ JanetChannel *chan = janet_vm.root_fiber->supervisor_channel;
if (NULL != chan) {
if (janet_channel_push(chan, janet_wrap_tuple(janet_tuple_n(argv, argc)), 0)) {
janet_await();
@@ -2118,7 +2080,7 @@ static Janet cfun_ev_give_supervisor(int32_t argc, Janet *argv) {
JANET_NO_RETURN void janet_sleep_await(double sec) {
JanetTimeout to;
to.when = ts_delta(ts_now(), sec);
- to.fiber = janet_vm_root_fiber;
+ to.fiber = janet_vm.root_fiber;
to.is_error = 0;
to.sched_id = to.fiber->sched_id;
to.curr_fiber = NULL;
@@ -2135,8 +2097,8 @@ static Janet cfun_ev_sleep(int32_t argc, Janet *argv) {
static Janet cfun_ev_deadline(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 3);
double sec = janet_getnumber(argv, 0);
- JanetFiber *tocancel = janet_optfiber(argv, argc, 1, janet_vm_root_fiber);
- JanetFiber *tocheck = janet_optfiber(argv, argc, 2, janet_vm_fiber);
+ JanetFiber *tocancel = janet_optfiber(argv, argc, 1, janet_vm.root_fiber);
+ JanetFiber *tocheck = janet_optfiber(argv, argc, 2, janet_vm.fiber);
JanetTimeout to;
to.when = ts_delta(ts_now(), sec);
to.fiber = tocancel;
diff --git a/src/core/fiber.c b/src/core/fiber.c
index 88a77804..a7fa855f 100644
--- a/src/core/fiber.c
+++ b/src/core/fiber.c
@@ -57,7 +57,7 @@ static JanetFiber *fiber_alloc(int32_t capacity) {
if (NULL == data) {
JANET_OUT_OF_MEMORY;
}
- janet_vm_next_collection += sizeof(Janet) * capacity;
+ janet_vm.next_collection += sizeof(Janet) * capacity;
fiber->data = data;
return fiber;
}
@@ -121,7 +121,7 @@ void janet_fiber_setcapacity(JanetFiber *fiber, int32_t n) {
}
fiber->data = newData;
fiber->capacity = n;
- janet_vm_next_collection += sizeof(Janet) * diff;
+ janet_vm.next_collection += sizeof(Janet) * diff;
}
/* Grow fiber if needed */
@@ -255,7 +255,7 @@ static void janet_env_detach(JanetFuncEnv *env) {
int32_t len = env->length;
size_t s = sizeof(Janet) * (size_t) len;
Janet *vmem = janet_malloc(s);
- janet_vm_next_collection += (uint32_t) s;
+ janet_vm.next_collection += (uint32_t) s;
if (NULL == vmem) {
JANET_OUT_OF_MEMORY;
}
@@ -442,11 +442,11 @@ JanetFiberStatus janet_fiber_status(JanetFiber *f) {
}
JanetFiber *janet_current_fiber(void) {
- return janet_vm_fiber;
+ return janet_vm.fiber;
}
JanetFiber *janet_root_fiber(void) {
- return janet_vm_root_fiber;
+ return janet_vm.root_fiber;
}
/* CFuns */
@@ -520,17 +520,17 @@ static Janet cfun_fiber_new(int32_t argc, Janet *argv) {
fiber->flags |= JANET_FIBER_MASK_YIELD;
break;
case 'i':
- if (!janet_vm_fiber->env) {
- janet_vm_fiber->env = janet_table(0);
+ if (!janet_vm.fiber->env) {
+ janet_vm.fiber->env = janet_table(0);
}
- fiber->env = janet_vm_fiber->env;
+ fiber->env = janet_vm.fiber->env;
break;
case 'p':
- if (!janet_vm_fiber->env) {
- janet_vm_fiber->env = janet_table(0);
+ if (!janet_vm.fiber->env) {
+ janet_vm.fiber->env = janet_table(0);
}
fiber->env = janet_table(0);
- fiber->env->proto = janet_vm_fiber->env;
+ fiber->env->proto = janet_vm.fiber->env;
break;
}
}
@@ -549,13 +549,13 @@ static Janet cfun_fiber_status(int32_t argc, Janet *argv) {
static Janet cfun_fiber_current(int32_t argc, Janet *argv) {
(void) argv;
janet_fixarity(argc, 0);
- return janet_wrap_fiber(janet_vm_fiber);
+ return janet_wrap_fiber(janet_vm.fiber);
}
static Janet cfun_fiber_root(int32_t argc, Janet *argv) {
(void) argv;
janet_fixarity(argc, 0);
- return janet_wrap_fiber(janet_vm_root_fiber);
+ return janet_wrap_fiber(janet_vm.root_fiber);
}
static Janet cfun_fiber_maxstack(int32_t argc, Janet *argv) {
diff --git a/src/core/fiber.h b/src/core/fiber.h
index 555c2750..5c46f4da 100644
--- a/src/core/fiber.h
+++ b/src/core/fiber.h
@@ -57,8 +57,6 @@
#define JANET_FIBER_DID_LONGJUMP 0x8000000
#define JANET_FIBER_FLAG_MASK 0xF000000
-extern JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber;
-
#define janet_fiber_set_status(f, s) do {\
(f)->flags &= ~JANET_FIBER_STATUS_MASK;\
(f)->flags |= (s) << JANET_FIBER_STATUS_OFFSET;\
diff --git a/src/core/gc.c b/src/core/gc.c
index 4b119af5..3c36bad3 100644
--- a/src/core/gc.c
+++ b/src/core/gc.c
@@ -31,28 +31,6 @@
#include "vector.h"
#endif
-struct JanetScratch {
- JanetScratchFinalizer finalize;
- long long mem[]; /* for proper alignment */
-};
-
-/* GC State */
-JANET_THREAD_LOCAL void *janet_vm_blocks;
-JANET_THREAD_LOCAL size_t janet_vm_gc_interval;
-JANET_THREAD_LOCAL size_t janet_vm_next_collection;
-JANET_THREAD_LOCAL size_t janet_vm_block_count;
-JANET_THREAD_LOCAL int janet_vm_gc_suspend = 0;
-
-/* Roots */
-JANET_THREAD_LOCAL Janet *janet_vm_roots;
-JANET_THREAD_LOCAL size_t janet_vm_root_count;
-JANET_THREAD_LOCAL size_t janet_vm_root_capacity;
-
-/* Scratch Memory */
-JANET_THREAD_LOCAL JanetScratch **janet_scratch_mem;
-JANET_THREAD_LOCAL size_t janet_scratch_cap;
-JANET_THREAD_LOCAL size_t janet_scratch_len;
-
/* Helpers for marking the various gc types */
static void janet_mark_funcenv(JanetFuncEnv *env);
static void janet_mark_funcdef(JanetFuncDef *def);
@@ -72,7 +50,7 @@ static JANET_THREAD_LOCAL size_t orig_rootcount;
/* Hint to the GC that we may need to collect */
void janet_gcpressure(size_t s) {
- janet_vm_next_collection += s;
+ janet_vm.next_collection += s;
}
/* Mark a value */
@@ -332,7 +310,7 @@ static void janet_deinit_block(JanetGCObject *mem) {
* marked as reachable. Flip the gc color flag for next sweep. */
void janet_sweep() {
JanetGCObject *previous = NULL;
- JanetGCObject *current = janet_vm_blocks;
+ JanetGCObject *current = janet_vm.blocks;
JanetGCObject *next;
while (NULL != current) {
next = current->next;
@@ -340,12 +318,12 @@ void janet_sweep() {
previous = current;
current->flags &= ~JANET_MEM_REACHABLE;
} else {
- janet_vm_block_count--;
+ janet_vm.block_count--;
janet_deinit_block(current);
if (NULL != previous) {
previous->next = next;
} else {
- janet_vm_blocks = next;
+ janet_vm.blocks = next;
}
janet_free(current);
}
@@ -358,7 +336,7 @@ void *janet_gcalloc(enum JanetMemoryType type, size_t size) {
JanetGCObject *mem;
/* Make sure everything is inited */
- janet_assert(NULL != janet_vm_cache, "please initialize janet before use");
+ janet_assert(NULL != janet_vm.cache, "please initialize janet before use");
mem = janet_malloc(size);
/* Check for bad malloc */
@@ -370,10 +348,10 @@ void *janet_gcalloc(enum JanetMemoryType type, size_t size) {
mem->flags = type;
/* Prepend block to heap list */
- janet_vm_next_collection += size;
- mem->next = janet_vm_blocks;
- janet_vm_blocks = mem;
- janet_vm_block_count++;
+ janet_vm.next_collection += size;
+ mem->next = janet_vm.blocks;
+ janet_vm.blocks = mem;
+ janet_vm.block_count++;
return (void *)mem;
}
@@ -387,10 +365,10 @@ static void free_one_scratch(JanetScratch *s) {
/* Free all allocated scratch memory */
static void janet_free_all_scratch(void) {
- for (size_t i = 0; i < janet_scratch_len; i++) {
- free_one_scratch(janet_scratch_mem[i]);
+ for (size_t i = 0; i < janet_vm.scratch_len; i++) {
+ free_one_scratch(janet_vm.scratch_mem[i]);
}
- janet_scratch_len = 0;
+ janet_vm.scratch_len = 0;
}
static JanetScratch *janet_mem2scratch(void *mem) {
@@ -401,29 +379,29 @@ static JanetScratch *janet_mem2scratch(void *mem) {
/* Run garbage collection */
void janet_collect(void) {
uint32_t i;
- if (janet_vm_gc_suspend) return;
+ if (janet_vm.gc_suspend) return;
depth = JANET_RECURSION_GUARD;
/* Try and prevent many major collections back to back.
- * A full collection will take O(janet_vm_block_count) time.
+ * A full collection will take O(janet_vm.block_count) time.
* If we have a large heap, make sure our interval is not too
* small so we won't make many collections over it. This is just a
* heuristic for automatically changing the gc interval */
- if (janet_vm_block_count * 8 > janet_vm_gc_interval) {
- janet_vm_gc_interval = janet_vm_block_count * sizeof(JanetGCObject);
+ if (janet_vm.block_count * 8 > janet_vm.gc_interval) {
+ janet_vm.gc_interval = janet_vm.block_count * sizeof(JanetGCObject);
}
- orig_rootcount = janet_vm_root_count;
+ orig_rootcount = janet_vm.root_count;
#ifdef JANET_EV
janet_ev_mark();
#endif
- janet_mark_fiber(janet_vm_root_fiber);
+ janet_mark_fiber(janet_vm.root_fiber);
for (i = 0; i < orig_rootcount; i++)
- janet_mark(janet_vm_roots[i]);
- while (orig_rootcount < janet_vm_root_count) {
- Janet x = janet_vm_roots[--janet_vm_root_count];
+ janet_mark(janet_vm.roots[i]);
+ while (orig_rootcount < janet_vm.root_count) {
+ Janet x = janet_vm.roots[--janet_vm.root_count];
janet_mark(x);
}
janet_sweep();
- janet_vm_next_collection = 0;
+ janet_vm.next_collection = 0;
janet_free_all_scratch();
}
@@ -431,17 +409,17 @@ void janet_collect(void) {
* and all of its children. If gcroot is called on a value n times, unroot
* must also be called n times to remove it as a gc root. */
void janet_gcroot(Janet root) {
- size_t newcount = janet_vm_root_count + 1;
- if (newcount > janet_vm_root_capacity) {
+ size_t newcount = janet_vm.root_count + 1;
+ if (newcount > janet_vm.root_capacity) {
size_t newcap = 2 * newcount;
- janet_vm_roots = janet_realloc(janet_vm_roots, sizeof(Janet) * newcap);
- if (NULL == janet_vm_roots) {
+ janet_vm.roots = janet_realloc(janet_vm.roots, sizeof(Janet) * newcap);
+ if (NULL == janet_vm.roots) {
JANET_OUT_OF_MEMORY;
}
- janet_vm_root_capacity = newcap;
+ janet_vm.root_capacity = newcap;
}
- janet_vm_roots[janet_vm_root_count] = root;
- janet_vm_root_count = newcount;
+ janet_vm.roots[janet_vm.root_count] = root;
+ janet_vm.root_count = newcount;
}
/* Identity equality for GC purposes */
@@ -462,11 +440,11 @@ static int janet_gc_idequals(Janet lhs, Janet rhs) {
/* Remove a root value from the GC. This allows the gc to potentially reclaim
* a value and all its children. */
int janet_gcunroot(Janet root) {
- Janet *vtop = janet_vm_roots + janet_vm_root_count;
+ Janet *vtop = janet_vm.roots + janet_vm.root_count;
/* Search from top to bottom as access is most likely LIFO */
- for (Janet *v = janet_vm_roots; v < vtop; v++) {
+ for (Janet *v = janet_vm.roots; v < vtop; v++) {
if (janet_gc_idequals(root, *v)) {
- *v = janet_vm_roots[--janet_vm_root_count];
+ *v = janet_vm.roots[--janet_vm.root_count];
return 1;
}
}
@@ -475,12 +453,12 @@ int janet_gcunroot(Janet root) {
/* Remove a root value from the GC. This sets the effective reference count to 0. */
int janet_gcunrootall(Janet root) {
- Janet *vtop = janet_vm_roots + janet_vm_root_count;
+ Janet *vtop = janet_vm.roots + janet_vm.root_count;
int ret = 0;
/* Search from top to bottom as access is most likely LIFO */
- for (Janet *v = janet_vm_roots; v < vtop; v++) {
+ for (Janet *v = janet_vm.roots; v < vtop; v++) {
if (janet_gc_idequals(root, *v)) {
- *v = janet_vm_roots[--janet_vm_root_count];
+ *v = janet_vm.roots[--janet_vm.root_count];
vtop--;
ret = 1;
}
@@ -490,24 +468,24 @@ int janet_gcunrootall(Janet root) {
/* Free all allocated memory */
void janet_clear_memory(void) {
- JanetGCObject *current = janet_vm_blocks;
+ JanetGCObject *current = janet_vm.blocks;
while (NULL != current) {
janet_deinit_block(current);
JanetGCObject *next = current->next;
janet_free(current);
current = next;
}
- janet_vm_blocks = NULL;
+ janet_vm.blocks = NULL;
janet_free_all_scratch();
- janet_free(janet_scratch_mem);
+ janet_free(janet_vm.scratch_mem);
}
/* Primitives for suspending GC. */
int janet_gclock(void) {
- return janet_vm_gc_suspend++;
+ return janet_vm.gc_suspend++;
}
void janet_gcunlock(int handle) {
- janet_vm_gc_suspend = handle;
+ janet_vm.gc_suspend = handle;
}
/* Scratch memory API */
@@ -518,16 +496,16 @@ void *janet_smalloc(size_t size) {
JANET_OUT_OF_MEMORY;
}
s->finalize = NULL;
- if (janet_scratch_len == janet_scratch_cap) {
- size_t newcap = 2 * janet_scratch_cap + 2;
- JanetScratch **newmem = (JanetScratch **) janet_realloc(janet_scratch_mem, newcap * sizeof(JanetScratch));
+ if (janet_vm.scratch_len == janet_vm.scratch_cap) {
+ size_t newcap = 2 * janet_vm.scratch_cap + 2;
+ JanetScratch **newmem = (JanetScratch **) janet_realloc(janet_vm.scratch_mem, newcap * sizeof(JanetScratch));
if (NULL == newmem) {
JANET_OUT_OF_MEMORY;
}
- janet_scratch_cap = newcap;
- janet_scratch_mem = newmem;
+ janet_vm.scratch_cap = newcap;
+ janet_vm.scratch_mem = newmem;
}
- janet_scratch_mem[janet_scratch_len++] = s;
+ janet_vm.scratch_mem[janet_vm.scratch_len++] = s;
return (char *)(s->mem);
}
@@ -544,14 +522,14 @@ void *janet_scalloc(size_t nmemb, size_t size) {
void *janet_srealloc(void *mem, size_t size) {
if (NULL == mem) return janet_smalloc(size);
JanetScratch *s = janet_mem2scratch(mem);
- if (janet_scratch_len) {
- for (size_t i = janet_scratch_len - 1; ; i--) {
- if (janet_scratch_mem[i] == s) {
+ if (janet_vm.scratch_len) {
+ for (size_t i = janet_vm.scratch_len - 1; ; i--) {
+ if (janet_vm.scratch_mem[i] == s) {
JanetScratch *news = janet_realloc(s, size + sizeof(JanetScratch));
if (NULL == news) {
JANET_OUT_OF_MEMORY;
}
- janet_scratch_mem[i] = news;
+ janet_vm.scratch_mem[i] = news;
return (char *)(news->mem);
}
if (i == 0) break;
@@ -568,10 +546,10 @@ void janet_sfinalizer(void *mem, JanetScratchFinalizer finalizer) {
void janet_sfree(void *mem) {
if (NULL == mem) return;
JanetScratch *s = janet_mem2scratch(mem);
- if (janet_scratch_len) {
- for (size_t i = janet_scratch_len - 1; ; i--) {
- if (janet_scratch_mem[i] == s) {
- janet_scratch_mem[i] = janet_scratch_mem[--janet_scratch_len];
+ if (janet_vm.scratch_len) {
+ for (size_t i = janet_vm.scratch_len - 1; ; i--) {
+ if (janet_vm.scratch_mem[i] == s) {
+ janet_vm.scratch_mem[i] = janet_vm.scratch_mem[--janet_vm.scratch_len];
free_one_scratch(s);
return;
}
diff --git a/src/core/math.c b/src/core/math.c
index 18a4affe..1eaf7852 100644
--- a/src/core/math.c
+++ b/src/core/math.c
@@ -23,13 +23,12 @@
#ifndef JANET_AMALG
#include "features.h"
#include <janet.h>
+#include "state.h"
#include "util.h"
#endif
#include <math.h>
-static JANET_THREAD_LOCAL JanetRNG janet_vm_rng = {0, 0, 0, 0, 0};
-
static int janet_rng_get(void *p, Janet key, Janet *out);
static Janet janet_rng_next(void *p, Janet key);
@@ -69,7 +68,7 @@ const JanetAbstractType janet_rng_type = {
};
JanetRNG *janet_default_rng(void) {
- return &janet_vm_rng;
+ return &janet_vm.rng;
}
void janet_rng_seed(JanetRNG *rng, uint32_t seed) {
@@ -217,7 +216,7 @@ static Janet janet_rng_next(void *p, Janet key) {
static Janet janet_rand(int32_t argc, Janet *argv) {
(void) argv;
janet_fixarity(argc, 0);
- return janet_wrap_number(janet_rng_double(&janet_vm_rng));
+ return janet_wrap_number(janet_rng_double(&janet_vm.rng));
}
/* Seed the random number generator */
@@ -225,10 +224,10 @@ static Janet janet_srand(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
if (janet_checkint(argv[0])) {
uint32_t seed = (uint32_t)(janet_getinteger(argv, 0));
- janet_rng_seed(&janet_vm_rng, seed);
+ janet_rng_seed(&janet_vm.rng, seed);
} else {
JanetByteView bytes = janet_getbytes(argv, 0);
- janet_rng_longseed(&janet_vm_rng, bytes.bytes, bytes.len);
+ janet_rng_longseed(&janet_vm.rng, bytes.bytes, bytes.len);
}
return janet_wrap_nil();
}
diff --git a/src/core/pp.c b/src/core/pp.c
index 6eb2e1e1..6c10008a 100644
--- a/src/core/pp.c
+++ b/src/core/pp.c
@@ -227,7 +227,7 @@ void janet_to_string_b(JanetBuffer *buffer, Janet x) {
}
return;
case JANET_CFUNCTION: {
- Janet check = janet_table_get(janet_vm_registry, x);
+ Janet check = janet_table_get(janet_vm.registry, x);
if (janet_checktype(check, JANET_SYMBOL)) {
janet_buffer_push_cstring(buffer, "<cfunction ");
janet_buffer_push_bytes(buffer,
diff --git a/src/core/state.c b/src/core/state.c
new file mode 100644
index 00000000..c2d4d4bd
--- /dev/null
+++ b/src/core/state.c
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2021 Calvin Rose
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to
+* deal in the Software without restriction, including without limitation the
+* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+* sell copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+* IN THE SOFTWARE.
+*/
+
+#ifndef JANET_AMALG
+#include "features.h"
+#include <janet.h>
+#include "state.h"
+#endif
+
+JANET_THREAD_LOCAL JanetVM janet_vm;
+
+JanetVM *janet_vm_alloc(void) {
+ JanetVM *mem = janet_malloc(sizeof(JanetVM));
+ if (NULL == mem) {
+ JANET_OUT_OF_MEMORY;
+ }
+ return mem;
+}
+
+void janet_vm_free(JanetVM *vm) {
+ janet_free(vm);
+}
+
+void janet_vm_save(JanetVM *into) {
+ *into = janet_vm;
+}
+
+void janet_vm_load(JanetVM *from) {
+ janet_vm = *from;
+}
diff --git a/src/core/state.h b/src/core/state.h
index efcd4115..0d2b6d3d 100644
--- a/src/core/state.h
+++ b/src/core/state.h
@@ -25,75 +25,135 @@
#include <stdint.h>
-/* The VM state. Rather than a struct that is passed
- * around, the vm state is global for simplicity. If
- * at some point a global state object, or context,
- * is required to be passed around, this is what would
- * be in it. However, thread local global variables for interpreter
- * state should allow easy multi-threading. */
-
-typedef struct JanetScratch JanetScratch;
-
-/* Top level dynamic bindings */
-extern JANET_THREAD_LOCAL JanetTable *janet_vm_top_dyns;
-
-/* Cache the core environment */
-extern JANET_THREAD_LOCAL JanetTable *janet_vm_core_env;
-
-/* How many VM stacks have been entered */
-extern JANET_THREAD_LOCAL int janet_vm_stackn;
-
-/* The current running fiber on the current thread.
- * Set and unset by janet_run. */
-extern JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber;
-extern JANET_THREAD_LOCAL JanetFiber *janet_vm_root_fiber;
-
-/* The current pointer to the inner most jmp_buf. The current
- * return point for panics. */
-extern JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf;
-extern JANET_THREAD_LOCAL Janet *janet_vm_return_reg;
-
-/* The global registry for c functions. Used to store meta-data
- * along with otherwise bare c function pointers. */
-extern JANET_THREAD_LOCAL JanetTable *janet_vm_registry;
-
-/* Registry for abstract abstract types that can be marshalled.
- * We need this to look up the constructors when unmarshalling. */
-extern JANET_THREAD_LOCAL JanetTable *janet_vm_abstract_registry;
-
-/* Immutable value cache */
-extern JANET_THREAD_LOCAL const uint8_t **janet_vm_cache;
-extern JANET_THREAD_LOCAL uint32_t janet_vm_cache_capacity;
-extern JANET_THREAD_LOCAL uint32_t janet_vm_cache_count;
-extern JANET_THREAD_LOCAL uint32_t janet_vm_cache_deleted;
-
-/* Garbage collection */
-extern JANET_THREAD_LOCAL void *janet_vm_blocks;
-extern JANET_THREAD_LOCAL size_t janet_vm_gc_interval;
-extern JANET_THREAD_LOCAL size_t janet_vm_next_collection;
-extern JANET_THREAD_LOCAL size_t janet_vm_block_count;
-extern JANET_THREAD_LOCAL int janet_vm_gc_suspend;
-
-/* GC roots */
-extern JANET_THREAD_LOCAL Janet *janet_vm_roots;
-extern JANET_THREAD_LOCAL size_t janet_vm_root_count;
-extern JANET_THREAD_LOCAL size_t janet_vm_root_capacity;
-
-/* Scratch memory */
-extern JANET_THREAD_LOCAL JanetScratch **janet_scratch_mem;
-extern JANET_THREAD_LOCAL size_t janet_scratch_cap;
-extern JANET_THREAD_LOCAL size_t janet_scratch_len;
-
-/* Recursionless traversal of data structures */
+typedef int64_t JanetTimestamp;
+
+typedef struct JanetScratch {
+ JanetScratchFinalizer finalize;
+ long long mem[]; /* for proper alignment */
+} JanetScratch;
+
typedef struct {
JanetGCObject *self;
JanetGCObject *other;
int32_t index;
int32_t index2;
} JanetTraversalNode;
-extern JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal;
-extern JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal_top;
-extern JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal_base;
+
+typedef struct {
+ int32_t capacity;
+ int32_t head;
+ int32_t tail;
+ void *data;
+} JanetQueue;
+
+typedef struct {
+ JanetTimestamp when;
+ JanetFiber *fiber;
+ JanetFiber *curr_fiber;
+ uint32_t sched_id;
+ int is_error;
+} JanetTimeout;
+
+typedef struct {
+ JanetMailbox *original;
+ JanetMailbox *newbox;
+ uint64_t flags;
+} JanetMailboxPair;
+
+struct JanetVM {
+ /* Top level dynamic bindings */
+ JanetTable *top_dyns;
+
+ /* Cache the core environment */
+ JanetTable *core_env;
+
+ /* How many VM stacks have been entered */
+ int stackn;
+
+ /* The current running fiber on the current thread.
+ * Set and unset by janet_run. */
+ JanetFiber *fiber;
+ JanetFiber *root_fiber;
+
+ /* The current pointer to the inner most jmp_buf. The current
+ * return point for panics. */
+ jmp_buf *signal_buf;
+ Janet *return_reg;
+
+ /* The global registry for c functions. Used to store meta-data
+ * along with otherwise bare c function pointers. */
+ JanetTable *registry;
+
+ /* Registry for abstract abstract types that can be marshalled.
+ * We need this to look up the constructors when unmarshalling. */
+ JanetTable *abstract_registry;
+
+ /* Immutable value cache */
+ const uint8_t **cache;
+ uint32_t cache_capacity;
+ uint32_t cache_count;
+ uint32_t cache_deleted;
+ uint8_t gensym_counter[8];
+
+ /* Garbage collection */
+ void *blocks;
+ size_t gc_interval;
+ size_t next_collection;
+ size_t block_count;
+ int gc_suspend;
+
+ /* GC roots */
+ Janet *roots;
+ size_t root_count;
+ size_t root_capacity;
+
+ /* Scratch memory */
+ JanetScratch **scratch_mem;
+ size_t scratch_cap;
+ size_t scratch_len;
+
+ /* Random number generator */
+ JanetRNG rng;
+
+ /* Traversal pointers */
+ JanetTraversalNode *traversal;
+ JanetTraversalNode *traversal_top;
+ JanetTraversalNode *traversal_base;
+
+ /* Threading */
+#ifndef JANET_SINGLE_THREADED
+ JanetMailbox *mailbox;
+ JanetThread *thread_current;
+ JanetTable *thread_decode;
+#endif
+
+ /* Event loop and scheduler globals */
+#ifdef JANET_EV
+ size_t tq_count;
+ size_t tq_capacity;
+ JanetQueue spawn;
+ JanetTimeout *tq;
+ JanetRNG ev_rng;
+ JanetListenerState **listeners;
+ size_t listener_count;
+ size_t listener_cap;
+ size_t extra_listeners;
+#ifdef JANET_WINDOWS
+ HANDLE iocp;
+#elif defined(JANET_EV_EPOLL)
+ JanetHandle selfpipe[2];
+ int epoll;
+ int timerfd;
+ int timer_enabled;
+#else
+ JanetHandle selfpipe[2];
+ struct pollfd *fds;
+#endif
+#endif
+
+};
+
+extern JANET_THREAD_LOCAL JanetVM janet_vm;
/* Setup / teardown */
#ifdef JANET_THREADS
diff --git a/src/core/symcache.c b/src/core/symcache.c
index 1977067a..4c30238c 100644
--- a/src/core/symcache.c
+++ b/src/core/symcache.c
@@ -36,30 +36,25 @@
#include <string.h>
-/* Cache state */
-JANET_THREAD_LOCAL const uint8_t **janet_vm_cache = NULL;
-JANET_THREAD_LOCAL uint32_t janet_vm_cache_capacity = 0;
-JANET_THREAD_LOCAL uint32_t janet_vm_cache_count = 0;
-JANET_THREAD_LOCAL uint32_t janet_vm_cache_deleted = 0;
-
/* Initialize the cache (allocate cache memory) */
void janet_symcache_init() {
- janet_vm_cache_capacity = 1024;
- janet_vm_cache = janet_calloc(1, (size_t) janet_vm_cache_capacity * sizeof(const uint8_t *));
- if (NULL == janet_vm_cache) {
+ janet_vm.cache_capacity = 1024;
+ janet_vm.cache = janet_calloc(1, (size_t) janet_vm.cache_capacity * sizeof(const uint8_t *));
+ if (NULL == janet_vm.cache) {
JANET_OUT_OF_MEMORY;
}
- janet_vm_cache_count = 0;
- janet_vm_cache_deleted = 0;
+ memset(&janet_vm.gensym_counter, 0, sizeof(janet_vm.gensym_counter));
+ janet_vm.cache_count = 0;
+ janet_vm.cache_deleted = 0;
}
/* Deinitialize the cache (free the cache memory) */
void janet_symcache_deinit() {
- janet_free((void *)janet_vm_cache);
- janet_vm_cache = NULL;
- janet_vm_cache_capacity = 0;
- janet_vm_cache_count = 0;
- janet_vm_cache_deleted = 0;
+ janet_free((void *)janet_vm.cache);
+ janet_vm.cache = NULL;
+ janet_vm.cache_capacity = 0;
+ janet_vm.cache_count = 0;
+ janet_vm.cache_deleted = 0;
}
/* Mark an entry in the table as deleted. */
@@ -79,24 +74,24 @@ static const uint8_t **janet_symcache_findmem(
/* We will search two ranges - index to the end,
* and 0 to the index. */
- index = (uint32_t)hash & (janet_vm_cache_capacity - 1);
+ index = (uint32_t)hash & (janet_vm.cache_capacity - 1);
bounds[0] = index;
- bounds[1] = janet_vm_cache_capacity;
+ bounds[1] = janet_vm.cache_capacity;
bounds[2] = 0;
bounds[3] = index;
for (j = 0; j < 4; j += 2)
for (i = bounds[j]; i < bounds[j + 1]; ++i) {
- const uint8_t *test = janet_vm_cache[i];
+ const uint8_t *test = janet_vm.cache[i];
/* Check empty spots */
if (NULL == test) {
if (NULL == firstEmpty)
- firstEmpty = janet_vm_cache + i;
+ firstEmpty = janet_vm.cache + i;
goto notfound;
}
/* Check for marked deleted */
if (JANET_SYMCACHE_DELETED == test) {
if (firstEmpty == NULL)
- firstEmpty = janet_vm_cache + i;
+ firstEmpty = janet_vm.cache + i;
continue;
}
if (janet_string_equalconst(test, str, len, hash)) {
@@ -104,10 +99,10 @@ static const uint8_t **janet_symcache_findmem(
*success = 1;
if (firstEmpty != NULL) {
*firstEmpty = test;
- janet_vm_cache[i] = JANET_SYMCACHE_DELETED;
+ janet_vm.cache[i] = JANET_SYMCACHE_DELETED;
return firstEmpty;
}
- return janet_vm_cache + i;
+ return janet_vm.cache + i;
}
}
notfound:
@@ -121,15 +116,15 @@ notfound:
/* Resize the cache. */
static void janet_cache_resize(uint32_t newCapacity) {
uint32_t i, oldCapacity;
- const uint8_t **oldCache = janet_vm_cache;
+ const uint8_t **oldCache = janet_vm.cache;
const uint8_t **newCache = janet_calloc(1, (size_t) newCapacity * sizeof(const uint8_t *));
if (newCache == NULL) {
JANET_OUT_OF_MEMORY;
}
- oldCapacity = janet_vm_cache_capacity;
- janet_vm_cache = newCache;
- janet_vm_cache_capacity = newCapacity;
- janet_vm_cache_deleted = 0;
+ oldCapacity = janet_vm.cache_capacity;
+ janet_vm.cache = newCache;
+ janet_vm.cache_capacity = newCapacity;
+ janet_vm.cache_deleted = 0;
/* Add all of the old cache entries back */
for (i = 0; i < oldCapacity; ++i) {
int status;
@@ -150,13 +145,13 @@ static void janet_cache_resize(uint32_t newCapacity) {
/* Add an item to the cache */
static void janet_symcache_put(const uint8_t *x, const uint8_t **bucket) {
- if ((janet_vm_cache_count + janet_vm_cache_deleted) * 2 > janet_vm_cache_capacity) {
+ if ((janet_vm.cache_count + janet_vm.cache_deleted) * 2 > janet_vm.cache_capacity) {
int status;
- janet_cache_resize(janet_tablen((2 * janet_vm_cache_count + 1)));
+ janet_cache_resize(janet_tablen((2 * janet_vm.cache_count + 1)));
bucket = janet_symcache_find(x, &status);
}
/* Add x to the cache */
- janet_vm_cache_count++;
+ janet_vm.cache_count++;
*bucket = x;
}
@@ -165,8 +160,8 @@ void janet_symbol_deinit(const uint8_t *sym) {
int status = 0;
const uint8_t **bucket = janet_symcache_find(sym, &status);
if (status) {
- janet_vm_cache_count--;
- janet_vm_cache_deleted++;
+ janet_vm.cache_count--;
+ janet_vm.cache_deleted++;
*bucket = JANET_SYMCACHE_DELETED;
}
}
@@ -194,22 +189,19 @@ const uint8_t *janet_csymbol(const char *cstr) {
return janet_symbol((const uint8_t *)cstr, (int32_t) strlen(cstr));
}
-/* Store counter for genysm to avoid quadratic behavior */
-JANET_THREAD_LOCAL uint8_t gensym_counter[8] = {'_', '0', '0', '0', '0', '0', '0', 0};
-
/* Increment the gensym buffer */
static void inc_gensym(void) {
- for (int i = sizeof(gensym_counter) - 2; i; i--) {
- if (gensym_counter[i] == '9') {
- gensym_counter[i] = 'a';
+ for (int i = sizeof(janet_vm.gensym_counter) - 2; i; i--) {
+ if (janet_vm.gensym_counter[i] == '9') {
+ janet_vm.gensym_counter[i] = 'a';
break;
- } else if (gensym_counter[i] == 'z') {
- gensym_counter[i] = 'A';
+ } else if (janet_vm.gensym_counter[i] == 'z') {
+ janet_vm.gensym_counter[i] = 'A';
break;
- } else if (gensym_counter[i] == 'Z') {
- gensym_counter[i] = '0';
+ } else if (janet_vm.gensym_counter[i] == 'Z') {
+ janet_vm.gensym_counter[i] = '0';
} else {
- gensym_counter[i]++;
+ janet_vm.gensym_counter[i]++;
break;
}
}
@@ -227,19 +219,19 @@ const uint8_t *janet_symbol_gen(void) {
* is enough for resolving collisions. */
do {
hash = janet_string_calchash(
- gensym_counter,
- sizeof(gensym_counter) - 1);
+ janet_vm.gensym_counter,
+ sizeof(janet_vm.gensym_counter) - 1);
bucket = janet_symcache_findmem(
- gensym_counter,
- sizeof(gensym_counter) - 1,
+ janet_vm.gensym_counter,
+ sizeof(janet_vm.gensym_counter) - 1,
hash,
&status);
} while (status && (inc_gensym(), 1));
- JanetStringHead *head = janet_gcalloc(JANET_MEMORY_SYMBOL, sizeof(JanetStringHead) + sizeof(gensym_counter));
- head->length = sizeof(gensym_counter) - 1;
+ JanetStringHead *head = janet_gcalloc(JANET_MEMORY_SYMBOL, sizeof(JanetStringHead) + sizeof(janet_vm.gensym_counter));
+ head->length = sizeof(janet_vm.gensym_counter) - 1;
head->hash = hash;
sym = (uint8_t *)(head->data);
- memcpy(sym, gensym_counter, sizeof(gensym_counter));
+ memcpy(sym, janet_vm.gensym_counter, sizeof(janet_vm.gensym_counter));
janet_symcache_put((const uint8_t *)sym, bucket);
return (const uint8_t *)sym;
}
diff --git a/src/core/thread.c b/src/core/thread.c
index 33fa9977..e6de8b06 100644
--- a/src/core/thread.c
+++ b/src/core/thread.c
@@ -71,25 +71,15 @@ struct JanetMailbox {
#define JANET_THREAD_CFUNCTIONS 0x4
static const char janet_thread_flags[] = "hac";
-typedef struct {
- JanetMailbox *original;
- JanetMailbox *newbox;
- uint64_t flags;
-} JanetMailboxPair;
-
-static JANET_THREAD_LOCAL JanetMailbox *janet_vm_mailbox = NULL;
-static JANET_THREAD_LOCAL JanetThread *janet_vm_thread_current = NULL;
-static JANET_THREAD_LOCAL JanetTable *janet_vm_thread_decode = NULL;
-
static JanetTable *janet_thread_get_decode(void) {
- if (janet_vm_thread_decode == NULL) {
- janet_vm_thread_decode = janet_get_core_table("load-image-dict");
- if (NULL == janet_vm_thread_decode) {
- janet_vm_thread_decode = janet_table(0);
+ if (janet_vm.thread_decode == NULL) {
+ janet_vm.thread_decode = janet_get_core_table("load-image-dict");
+ if (NULL == janet_vm.thread_decode) {
+ janet_vm.thread_decode = janet_table(0);
}
- janet_gcroot(janet_wrap_table(janet_vm_thread_decode));
+ janet_gcroot(janet_wrap_table(janet_vm.thread_decode));
}
- return janet_vm_thread_decode;
+ return janet_vm.thread_decode;
}
static JanetMailbox *janet_mailbox_create(int refCount, uint16_t capacity) {
@@ -326,8 +316,8 @@ int janet_thread_send(JanetThread *thread, Janet msg, double timeout) {
/* Hack to capture all panics from marshalling. This works because
* we know janet_marshal won't mess with other essential global state. */
jmp_buf buf;
- jmp_buf *old_buf = janet_vm_jmp_buf;
- janet_vm_jmp_buf = &buf;
+ jmp_buf *old_buf = janet_vm.signal_buf;
+ janet_vm.signal_buf = &buf;
int32_t oldmcount = mailbox->messageCount;
int ret = 0;
@@ -347,7 +337,7 @@ int janet_thread_send(JanetThread *thread, Janet msg, double timeout) {
}
/* Cleanup */
- janet_vm_jmp_buf = old_buf;
+ janet_vm.signal_buf = old_buf;
janet_mailbox_unlock(mailbox);
/* Potentially wake up a blocked thread */
@@ -358,7 +348,7 @@ int janet_thread_send(JanetThread *thread, Janet msg, double timeout) {
/* Returns 0 on successful message. Returns 1 if timedout */
int janet_thread_receive(Janet *msg_out, double timeout) {
- JanetMailbox *mailbox = janet_vm_mailbox;
+ JanetMailbox *mailbox = janet_vm.mailbox;
janet_mailbox_lock(mailbox);
/* For timeouts */
@@ -373,15 +363,15 @@ int janet_thread_receive(Janet *msg_out, double timeout) {
/* Hack to capture all panics from marshalling. This works because
* we know janet_marshal won't mess with other essential global state. */
jmp_buf buf;
- jmp_buf *old_buf = janet_vm_jmp_buf;
- janet_vm_jmp_buf = &buf;
+ jmp_buf *old_buf = janet_vm.signal_buf;
+ janet_vm.signal_buf = &buf;
/* Handle errors */
if (setjmp(buf)) {
/* Cleanup jmp_buf, return error.
* Do not ignore bad messages as before. */
- janet_vm_jmp_buf = old_buf;
- *msg_out = *janet_vm_return_reg;
+ janet_vm.signal_buf = old_buf;
+ *msg_out = *janet_vm.return_reg;
janet_mailbox_unlock(mailbox);
return 2;
} else {
@@ -397,7 +387,7 @@ int janet_thread_receive(Janet *msg_out, double timeout) {
*msg_out = item;
/* Cleanup */
- janet_vm_jmp_buf = old_buf;
+ janet_vm.signal_buf = old_buf;
janet_mailbox_unlock(mailbox);
/* Potentially wake up pending threads */
@@ -455,21 +445,21 @@ static int thread_worker(JanetMailboxPair *pair) {
JanetFiber *fiber = NULL;
Janet out;
- /* Use the mailbox we were given */
- janet_vm_mailbox = pair->newbox;
- janet_mailbox_ref(pair->newbox, 1);
-
/* Init VM */
janet_init();
+ /* Use the mailbox we were given */
+ janet_vm.mailbox = pair->newbox;
+ janet_mailbox_ref(pair->newbox, 1);
+
/* Get dictionaries for default encode/decode */
JanetTable *encode;
if (pair->flags & JANET_THREAD_HEAVYWEIGHT) {
encode = janet_get_core_table("make-image-dict");
} else {
encode = NULL;
- janet_vm_thread_decode = janet_table(0);
- janet_gcroot(janet_wrap_table(janet_vm_thread_decode));
+ janet_vm.thread_decode = janet_table(0);
+ janet_gcroot(janet_wrap_table(janet_vm.thread_decode));
}
/* Create parent thread */
@@ -482,9 +472,9 @@ static int thread_worker(JanetMailboxPair *pair) {
int status = janet_thread_receive(&reg, INFINITY);
if (status) goto error;
if (!janet_checktype(reg, JANET_TABLE)) goto error;
- janet_gcunroot(janet_wrap_table(janet_vm_abstract_registry));
- janet_vm_abstract_registry = janet_unwrap_table(reg);
- janet_gcroot(janet_wrap_table(janet_vm_abstract_registry));
+ janet_gcunroot(janet_wrap_table(janet_vm.abstract_registry));
+ janet_vm.abstract_registry = janet_unwrap_table(reg);
+ janet_gcroot(janet_wrap_table(janet_vm.abstract_registry));
}
/* Unmarshal the normal registry */
@@ -493,9 +483,9 @@ static int thread_worker(JanetMailboxPair *pair) {
int status = janet_thread_receive(&reg, INFINITY);
if (status) goto error;
if (!janet_checktype(reg, JANET_TABLE)) goto error;
- janet_gcunroot(janet_wrap_table(janet_vm_registry));
- janet_vm_registry = janet_unwrap_table(reg);
- janet_gcroot(janet_wrap_table(janet_vm_registry));
+ janet_gcunroot(janet_wrap_table(janet_vm.registry));
+ janet_vm.registry = janet_unwrap_table(reg);
+ janet_gcroot(janet_wrap_table(janet_vm.registry));
}
/* Unmarshal the function */
@@ -580,28 +570,26 @@ static int janet_thread_start_child(JanetMailboxPair *pair) {
*/
void janet_threads_init(void) {
- if (NULL == janet_vm_mailbox) {
- janet_vm_mailbox = janet_mailbox_create(1, 10);
- }
- janet_vm_thread_decode = NULL;
- janet_vm_thread_current = NULL;
+ janet_vm.mailbox = janet_mailbox_create(1, 10);
+ janet_vm.thread_decode = NULL;
+ janet_vm.thread_current = NULL;
}
void janet_threads_deinit(void) {
- janet_mailbox_lock(janet_vm_mailbox);
- janet_vm_mailbox->closed = 1;
- janet_mailbox_ref_with_lock(janet_vm_mailbox, -1);
- janet_vm_mailbox = NULL;
- janet_vm_thread_current = NULL;
- janet_vm_thread_decode = NULL;
+ janet_mailbox_lock(janet_vm.mailbox);
+ janet_vm.mailbox->closed = 1;
+ janet_mailbox_ref_with_lock(janet_vm.mailbox, -1);
+ janet_vm.mailbox = NULL;
+ janet_vm.thread_current = NULL;
+ janet_vm.thread_decode = NULL;
}
JanetThread *janet_thread_current(void) {
- if (NULL == janet_vm_thread_current) {
- janet_vm_thread_current = janet_make_thread(janet_vm_mailbox, janet_get_core_table("make-image-dict"));
- janet_gcroot(janet_wrap_abstract(janet_vm_thread_current));
+ if (NULL == janet_vm.thread_current) {
+ janet_vm.thread_current = janet_make_thread(janet_vm.mailbox, janet_get_core_table("make-image-dict"));
+ janet_gcroot(janet_wrap_abstract(janet_vm.thread_current));
}
- return janet_vm_thread_current;
+ return janet_vm.thread_current;
}
/*
@@ -630,7 +618,7 @@ static Janet cfun_thread_new(int32_t argc, Janet *argv) {
encode = NULL;
}
- JanetMailboxPair *pair = make_mailbox_pair(janet_vm_mailbox, flags);
+ JanetMailboxPair *pair = make_mailbox_pair(janet_vm.mailbox, flags);
JanetThread *thread = janet_make_thread(pair->newbox, encode);
if (janet_thread_start_child(pair)) {
destroy_mailbox_pair(pair);
@@ -638,13 +626,13 @@ static Janet cfun_thread_new(int32_t argc, Janet *argv) {
}
if (flags & JANET_THREAD_ABSTRACTS) {
- if (janet_thread_send(thread, janet_wrap_table(janet_vm_abstract_registry), INFINITY)) {
+ if (janet_thread_send(thread, janet_wrap_table(janet_vm.abstract_registry), INFINITY)) {
janet_panic("could not send abstract registry to thread");
}
}
if (flags & JANET_THREAD_CFUNCTIONS) {
- if (janet_thread_send(thread, janet_wrap_table(janet_vm_registry), INFINITY)) {
+ if (janet_thread_send(thread, janet_wrap_table(janet_vm.registry), INFINITY)) {
janet_panic("could not send registry to thread");
}
}
diff --git a/src/core/util.c b/src/core/util.c
index 5370772d..adcebcf2 100644
--- a/src/core/util.c
+++ b/src/core/util.c
@@ -366,7 +366,7 @@ const void *janet_strbinsearch(
void janet_register(const char *name, JanetCFunction cfun) {
Janet key = janet_wrap_cfunction(cfun);
Janet value = janet_csymbolv(name);
- janet_table_put(janet_vm_registry, key, value);
+ janet_table_put(janet_vm.registry, key, value);
}
/* Add a def to an environment */
@@ -433,7 +433,7 @@ static void _janet_cfuns_prefix(JanetTable *env, const char *regprefix, const Ja
} else {
janet_def(env, cfuns->name, fun, cfuns->documentation);
}
- janet_table_put(janet_vm_registry, fun, name);
+ janet_table_put(janet_vm.registry, fun, name);
cfuns++;
}
(janet_free)(longname_buffer);
@@ -451,16 +451,16 @@ void janet_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns)
void janet_register_abstract_type(const JanetAbstractType *at) {
Janet sym = janet_csymbolv(at->name);
- Janet check = janet_table_get(janet_vm_abstract_registry, sym);
+ Janet check = janet_table_get(janet_vm.abstract_registry, sym);
if (!janet_checktype(check, JANET_NIL) && at != janet_unwrap_pointer(check)) {
janet_panicf("cannot register abstract type %s, "
"a type with the same name exists", at->name);
}
- janet_table_put(janet_vm_abstract_registry, sym, janet_wrap_pointer((void *) at));
+ janet_table_put(janet_vm.abstract_registry, sym, janet_wrap_pointer((void *) at));
}
const JanetAbstractType *janet_get_abstract_type(Janet key) {
- Janet wrapped = janet_table_get(janet_vm_abstract_registry, key);
+ Janet wrapped = janet_table_get(janet_vm.abstract_registry, key);
if (janet_checktype(wrapped, JANET_NIL)) {
return NULL;
}
@@ -473,7 +473,7 @@ void janet_core_def(JanetTable *env, const char *name, Janet x, const void *p) {
Janet key = janet_csymbolv(name);
janet_table_put(env, key, x);
if (janet_checktype(x, JANET_CFUNCTION)) {
- janet_table_put(janet_vm_registry, x, key);
+ janet_table_put(janet_vm.registry, x, key);
}
}
diff --git a/src/core/value.c b/src/core/value.c
index ce43a11c..9ca0f666 100644
--- a/src/core/value.c
+++ b/src/core/value.c
@@ -31,31 +31,27 @@
#include <math.h>
-JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal = NULL;
-JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal_top = NULL;
-JANET_THREAD_LOCAL JanetTraversalNode *janet_vm_traversal_base = NULL;
-
static void push_traversal_node(void *lhs, void *rhs, int32_t index2) {
JanetTraversalNode node;
node.self = (JanetGCObject *) lhs;
node.other = (JanetGCObject *) rhs;
node.index = 0;
node.index2 = index2;
- if (janet_vm_traversal + 1 >= janet_vm_traversal_top) {
- size_t oldsize = janet_vm_traversal - janet_vm_traversal_base;
+ if (janet_vm.traversal + 1 >= janet_vm.traversal_top) {
+ size_t oldsize = janet_vm.traversal - janet_vm.traversal_base;
size_t newsize = 2 * oldsize + 1;
if (newsize < 128) {
newsize = 128;
}
- JanetTraversalNode *tn = janet_realloc(janet_vm_traversal_base, newsize * sizeof(JanetTraversalNode));
+ JanetTraversalNode *tn = janet_realloc(janet_vm.traversal_base, newsize * sizeof(JanetTraversalNode));
if (tn == NULL) {
JANET_OUT_OF_MEMORY;
}
- janet_vm_traversal_base = tn;
- janet_vm_traversal_top = janet_vm_traversal_base + newsize;
- janet_vm_traversal = janet_vm_traversal_base + oldsize;
+ janet_vm.traversal_base = tn;
+ janet_vm.traversal_top = janet_vm.traversal_base + newsize;
+ janet_vm.traversal = janet_vm.traversal_base + oldsize;
}
- *(++janet_vm_traversal) = node;
+ *(++janet_vm.traversal) = node;
}
/*
@@ -67,8 +63,8 @@ static void push_traversal_node(void *lhs, void *rhs, int32_t index2) {
* 3 - early stop - lhs > rhs
*/
static int traversal_next(Janet *x, Janet *y) {
- JanetTraversalNode *t = janet_vm_traversal;
- while (t && t > janet_vm_traversal_base) {
+ JanetTraversalNode *t = janet_vm.traversal;
+ while (t && t > janet_vm.traversal_base) {
JanetGCObject *self = t->self;
JanetTupleHead *tself = (JanetTupleHead *)self;
JanetStructHead *sself = (JanetStructHead *)self;
@@ -81,7 +77,7 @@ static int traversal_next(Janet *x, Janet *y) {
int32_t index = t->index++;
*x = tself->data[index];
*y = tother->data[index];
- janet_vm_traversal = t;
+ janet_vm.traversal = t;
return 0;
}
if (t->index2 && tself->length != tother->length) {
@@ -94,20 +90,20 @@ static int traversal_next(Janet *x, Janet *y) {
int32_t index = t->index++;
*x = sself->data[index].value;
*y = sother->data[index].value;
- janet_vm_traversal = t;
+ janet_vm.traversal = t;
return 0;
}
for (int32_t i = t->index; i < sself->capacity; i++) {
t->index2 = 1;
*x = sself->data[t->index].key;
*y = sother->data[t->index].key;
- janet_vm_traversal = t;
+ janet_vm.traversal = t;
return 0;
}
}
t--;
}
- janet_vm_traversal = t;
+ janet_vm.traversal = t;
return 2;
}
@@ -196,17 +192,17 @@ Janet janet_next_impl(Janet ds, Janet key, int is_interpreter) {
status == JANET_STATUS_USER4) {
return janet_wrap_nil();
}
- janet_vm_fiber->child = child;
+ janet_vm.fiber->child = child;
JanetSignal sig = janet_continue(child, janet_wrap_nil(), &retreg);
if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig))) {
if (is_interpreter) {
janet_signalv(sig, retreg);
} else {
- janet_vm_fiber->child = NULL;
+ janet_vm.fiber->child = NULL;
janet_panicv(retreg);
}
}
- janet_vm_fiber->child = NULL;
+ janet_vm.fiber->child = NULL;
if (sig == JANET_SIGNAL_OK ||
sig == JANET_SIGNAL_ERROR ||
sig == JANET_SIGNAL_USER0 ||
@@ -239,7 +235,7 @@ static int janet_compare_abstract(JanetAbstract xx, JanetAbstract yy) {
}
int janet_equals(Janet x, Janet y) {
- janet_vm_traversal = janet_vm_traversal_base;
+ janet_vm.traversal = janet_vm.traversal_base;
do {
if (janet_type(x) != janet_type(y)) return 0;
switch (janet_type(x)) {
@@ -347,7 +343,7 @@ int32_t janet_hash(Janet x) {
* If y is less, returns 1. All types are comparable
* and should have strict ordering, excepts NaNs. */
int janet_compare(Janet x, Janet y) {
- janet_vm_traversal = janet_vm_traversal_base;
+ janet_vm.traversal = janet_vm.traversal_base;
int status;
do {
JanetType tx = janet_type(x);
diff --git a/src/core/vm.c b/src/core/vm.c
index ceb682a3..f624b9e2 100644
--- a/src/core/vm.c
+++ b/src/core/vm.c
@@ -32,17 +32,6 @@
#include <math.h>
-/* VM state */
-JANET_THREAD_LOCAL JanetTable *janet_vm_top_dyns;
-JANET_THREAD_LOCAL JanetTable *janet_vm_core_env;
-JANET_THREAD_LOCAL JanetTable *janet_vm_registry;
-JANET_THREAD_LOCAL JanetTable *janet_vm_abstract_registry;
-JANET_THREAD_LOCAL int janet_vm_stackn = 0;
-JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber = NULL;
-JANET_THREAD_LOCAL JanetFiber *janet_vm_root_fiber = NULL;
-JANET_THREAD_LOCAL Janet *janet_vm_return_reg = NULL;
-JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
-
/* Virtual registers
*
* One instruction word
@@ -91,18 +80,18 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
func = janet_stack_frame(stack)->func; \
} while (0)
#define vm_return(sig, val) do { \
- janet_vm_return_reg[0] = (val); \
+ janet_vm.return_reg[0] = (val); \
vm_commit(); \
return (sig); \
} while (0)
#define vm_return_no_restore(sig, val) do { \
- janet_vm_return_reg[0] = (val); \
+ janet_vm.return_reg[0] = (val); \
return (sig); \
} while (0)
/* Next instruction variations */
#define maybe_collect() do {\
- if (janet_vm_next_collection >= janet_vm_gc_interval) janet_collect(); } while (0)
+ if (janet_vm.next_collection >= janet_vm.gc_interval) janet_collect(); } while (0)
#define vm_checkgc_next() maybe_collect(); vm_next()
#define vm_pcnext() pc++; vm_next()
#define vm_checkgc_pcnext() maybe_collect(); vm_pcnext()
@@ -591,7 +580,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
JanetSignal sig = (fiber->gc.flags & JANET_FIBER_STATUS_MASK) >> JANET_FIBER_STATUS_OFFSET;
fiber->gc.flags &= ~JANET_FIBER_STATUS_MASK;
fiber->flags &= ~(JANET_FIBER_RESUME_SIGNAL | JANET_FIBER_FLAG_MASK);
- janet_vm_return_reg[0] = in;
+ janet_vm.return_reg[0] = in;
return sig;
}
@@ -1279,9 +1268,9 @@ JanetSignal janet_step(JanetFiber *fiber, Janet in, Janet *out) {
Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
/* Check entry conditions */
- if (!janet_vm_fiber)
+ if (!janet_vm.fiber)
janet_panic("janet_call failed because there is no current fiber");
- if (janet_vm_stackn >= JANET_RECURSION_GUARD)
+ if (janet_vm.stackn >= JANET_RECURSION_GUARD)
janet_panic("C stack recursed too deeply");
/* Tracing */
@@ -1290,8 +1279,8 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
}
/* Push frame */
- janet_fiber_pushn(janet_vm_fiber, argv, argc);
- if (janet_fiber_funcframe(janet_vm_fiber, fun)) {
+ janet_fiber_pushn(janet_vm.fiber, argv, argc);
+ if (janet_fiber_funcframe(janet_vm.fiber, fun)) {
int32_t min = fun->def->min_arity;
int32_t max = fun->def->max_arity;
Janet funv = janet_wrap_function(fun);
@@ -1301,31 +1290,31 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
janet_panicf("arity mismatch in %v, expected at least %d, got %d", funv, min, argc);
janet_panicf("arity mismatch in %v, expected at most %d, got %d", funv, max, argc);
}
- janet_fiber_frame(janet_vm_fiber)->flags |= JANET_STACKFRAME_ENTRANCE;
+ janet_fiber_frame(janet_vm.fiber)->flags |= JANET_STACKFRAME_ENTRANCE;
/* Set up */
- int32_t oldn = janet_vm_stackn++;
+ int32_t oldn = janet_vm.stackn++;
int handle = janet_gclock();
/* Run vm */
- janet_vm_fiber->flags |= JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP;
- JanetSignal signal = run_vm(janet_vm_fiber, janet_wrap_nil());
+ janet_vm.fiber->flags |= JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP;
+ JanetSignal signal = run_vm(janet_vm.fiber, janet_wrap_nil());
/* Teardown */
- janet_vm_stackn = oldn;
+ janet_vm.stackn = oldn;
janet_gcunlock(handle);
if (signal != JANET_SIGNAL_OK) {
- janet_panicv(*janet_vm_return_reg);
+ janet_panicv(*janet_vm.return_reg);
}
- return *janet_vm_return_reg;
+ return *janet_vm.return_reg;
}
static JanetSignal janet_check_can_resume(JanetFiber *fiber, Janet *out) {
/* Check conditions */
JanetFiberStatus old_status = janet_fiber_status(fiber);
- if (janet_vm_stackn >= JANET_RECURSION_GUARD) {
+ if (janet_vm.stackn >= JANET_RECURSION_GUARD) {
janet_fiber_set_status(fiber, JANET_STATUS_ERROR);
*out = janet_cstringv("C stack recursed too deeply");
return JANET_SIGNAL_ERROR;
@@ -1343,21 +1332,21 @@ static JanetSignal janet_check_can_resume(JanetFiber *fiber, Janet *out) {
}
void janet_try_init(JanetTryState *state) {
- state->stackn = janet_vm_stackn++;
- state->gc_handle = janet_vm_gc_suspend;
- state->vm_fiber = janet_vm_fiber;
- state->vm_jmp_buf = janet_vm_jmp_buf;
- state->vm_return_reg = janet_vm_return_reg;
- janet_vm_return_reg = &(state->payload);
- janet_vm_jmp_buf = &(state->buf);
+ state->stackn = janet_vm.stackn++;
+ state->gc_handle = janet_vm.gc_suspend;
+ state->vm_fiber = janet_vm.fiber;
+ state->vm_jmp_buf = janet_vm.signal_buf;
+ state->vm_return_reg = janet_vm.return_reg;
+ janet_vm.return_reg = &(state->payload);
+ janet_vm.signal_buf = &(state->buf);
}
void janet_restore(JanetTryState *state) {
- janet_vm_stackn = state->stackn;
- janet_vm_gc_suspend = state->gc_handle;
- janet_vm_fiber = state->vm_fiber;
- janet_vm_jmp_buf = state->vm_jmp_buf;
- janet_vm_return_reg = state->vm_return_reg;
+ janet_vm.stackn = state->stackn;
+ janet_vm.gc_suspend = state->gc_handle;
+ janet_vm.fiber = state->vm_fiber;
+ janet_vm.signal_buf = state->vm_jmp_buf;
+ janet_vm.return_reg = state->vm_return_reg;
}
static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *out) {
@@ -1373,13 +1362,13 @@ static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *o
/* Continue child fiber if it exists */
if (fiber->child) {
- if (janet_vm_root_fiber == NULL) janet_vm_root_fiber = fiber;
+ if (janet_vm.root_fiber == NULL) janet_vm.root_fiber = fiber;
JanetFiber *child = fiber->child;
uint32_t instr = (janet_stack_frame(fiber->data + fiber->frame)->pc)[0];
- janet_vm_stackn++;
+ janet_vm.stackn++;
JanetSignal sig = janet_continue(child, in, &in);
- janet_vm_stackn--;
- if (janet_vm_root_fiber == fiber) janet_vm_root_fiber = NULL;
+ janet_vm.stackn--;
+ if (janet_vm.root_fiber == fiber) janet_vm.root_fiber = NULL;
if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig))) {
*out = in;
janet_fiber_set_status(fiber, sig);
@@ -1425,14 +1414,14 @@ static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *o
JanetSignal sig = janet_try(&tstate);
if (!sig) {
/* Normal setup */
- if (janet_vm_root_fiber == NULL) janet_vm_root_fiber = fiber;
- janet_vm_fiber = fiber;
+ if (janet_vm.root_fiber == NULL) janet_vm.root_fiber = fiber;
+ janet_vm.fiber = fiber;
janet_fiber_set_status(fiber, JANET_STATUS_ALIVE);
sig = run_vm(fiber, in);
}
/* Restore */
- if (janet_vm_root_fiber == fiber) janet_vm_root_fiber = NULL;
+ if (janet_vm.root_fiber == fiber) janet_vm.root_fiber = NULL;
janet_fiber_set_status(fiber, sig);
janet_restore(&tstate);
fiber->last_value = tstate.payload;
@@ -1497,39 +1486,50 @@ Janet janet_mcall(const char *name, int32_t argc, Janet *argv) {
/* Setup VM */
int janet_init(void) {
+
/* Garbage collection */
- janet_vm_blocks = NULL;
- janet_vm_next_collection = 0;
- janet_vm_gc_interval = 0x400000;
- janet_vm_block_count = 0;
+ janet_vm.blocks = NULL;
+ janet_vm.next_collection = 0;
+ janet_vm.gc_interval = 0x400000;
+ janet_vm.block_count = 0;
+
janet_symcache_init();
+
/* Initialize gc roots */
- janet_vm_roots = NULL;
- janet_vm_root_count = 0;
- janet_vm_root_capacity = 0;
+ janet_vm.roots = NULL;
+ janet_vm.root_count = 0;
+ janet_vm.root_capacity = 0;
+
/* Scratch memory */
- janet_scratch_mem = NULL;
- janet_scratch_len = 0;
- janet_scratch_cap = 0;
+ janet_vm.scratch_mem = NULL;
+ janet_vm.scratch_len = 0;
+ janet_vm.scratch_cap = 0;
+
/* Initialize registry */
- janet_vm_registry = janet_table(0);
- janet_vm_abstract_registry = janet_table(0);
- janet_gcroot(janet_wrap_table(janet_vm_registry));
- janet_gcroot(janet_wrap_table(janet_vm_abstract_registry));
+ janet_vm.registry = janet_table(0);
+ janet_vm.abstract_registry = janet_table(0);
+ janet_gcroot(janet_wrap_table(janet_vm.registry));
+ janet_gcroot(janet_wrap_table(janet_vm.abstract_registry));
+
/* Traversal */
- janet_vm_traversal = NULL;
- janet_vm_traversal_base = NULL;
- janet_vm_traversal_top = NULL;
+ janet_vm.traversal = NULL;
+ janet_vm.traversal_base = NULL;
+ janet_vm.traversal_top = NULL;
+
/* Core env */
- janet_vm_core_env = NULL;
+ janet_vm.core_env = NULL;
+
/* Dynamic bindings */
- janet_vm_top_dyns = NULL;
+ janet_vm.top_dyns = NULL;
+
/* Seed RNG */
janet_rng_seed(janet_default_rng(), 0);
+
/* Fibers */
- janet_vm_fiber = NULL;
- janet_vm_root_fiber = NULL;
- janet_vm_stackn = 0;
+ janet_vm.fiber = NULL;
+ janet_vm.root_fiber = NULL;
+ janet_vm.stackn = 0;
+
#ifdef JANET_THREADS
janet_threads_init();
#endif
@@ -1546,17 +1546,17 @@ int janet_init(void) {
void janet_deinit(void) {
janet_clear_memory();
janet_symcache_deinit();
- janet_free(janet_vm_roots);
- janet_vm_roots = NULL;
- janet_vm_root_count = 0;
- janet_vm_root_capacity = 0;
- janet_vm_registry = NULL;
- janet_vm_abstract_registry = NULL;
- janet_vm_core_env = NULL;
- janet_vm_top_dyns = NULL;
- janet_free(janet_vm_traversal_base);
- janet_vm_fiber = NULL;
- janet_vm_root_fiber = NULL;
+ janet_free(janet_vm.roots);
+ janet_vm.roots = NULL;
+ janet_vm.root_count = 0;
+ janet_vm.root_capacity = 0;
+ janet_vm.registry = NULL;
+ janet_vm.abstract_registry = NULL;
+ janet_vm.core_env = NULL;
+ janet_vm.top_dyns = NULL;
+ janet_free(janet_vm.traversal_base);
+ janet_vm.fiber = NULL;
+ janet_vm.root_fiber = NULL;
#ifdef JANET_THREADS
janet_threads_deinit();
#endif
diff --git a/src/core/wrap.c b/src/core/wrap.c
index d040e6b6..3025c332 100644
--- a/src/core/wrap.c
+++ b/src/core/wrap.c
@@ -163,7 +163,7 @@ Janet(janet_wrap_number)(double x) {
void *janet_memalloc_empty(int32_t count) {
int32_t i;
void *mem = janet_malloc((size_t) count * sizeof(JanetKV));
- janet_vm_next_collection += (size_t) count * sizeof(JanetKV);
+ janet_vm.next_collection += (size_t) count * sizeof(JanetKV);
if (NULL == mem) {
JANET_OUT_OF_MEMORY;
}
diff --git a/src/include/janet.h b/src/include/janet.h
index 296df0e6..f07074dd 100644
--- a/src/include/janet.h
+++ b/src/include/janet.h
@@ -365,6 +365,9 @@ typedef enum {
JANET_STATUS_ALIVE
} JanetFiberStatus;
+/* For encapsulating all thread-local Janet state (except natives) */
+typedef struct JanetVM JanetVM;
+
/* Use type punning for GC objects */
typedef struct JanetGCObject JanetGCObject;
@@ -1641,6 +1644,10 @@ JANET_API int32_t janet_sorted_keys(const JanetKV *dict, int32_t cap, int32_t *i
/* VM functions */
JANET_API int janet_init(void);
JANET_API void janet_deinit(void);
+JANET_API JanetVM *janet_vm_alloc(void);
+JANET_API void janet_vm_free(JanetVM *vm);
+JANET_API void janet_vm_save(JanetVM *into);
+JANET_API void janet_vm_load(JanetVM *from);
JANET_API JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out);
JANET_API JanetSignal janet_continue_signal(JanetFiber *fiber, Janet in, Janet *out, JanetSignal sig);
JANET_API JanetSignal janet_pcall(JanetFunction *fun, int32_t argn, const Janet *argv, Janet *out, JanetFiber **f);