diff options
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | meson.build | 1 | ||||
| -rw-r--r-- | src/boot/boot.janet | 1 | ||||
| -rw-r--r-- | src/core/array.c | 4 | ||||
| -rw-r--r-- | src/core/capi.c | 34 | ||||
| -rw-r--r-- | src/core/compile.c | 4 | ||||
| -rw-r--r-- | src/core/corelib.c | 22 | ||||
| -rw-r--r-- | src/core/debug.c | 6 | ||||
| -rw-r--r-- | src/core/ev.c | 300 | ||||
| -rw-r--r-- | src/core/fiber.c | 26 | ||||
| -rw-r--r-- | src/core/fiber.h | 2 | ||||
| -rw-r--r-- | src/core/gc.c | 130 | ||||
| -rw-r--r-- | src/core/math.c | 11 | ||||
| -rw-r--r-- | src/core/pp.c | 2 | ||||
| -rw-r--r-- | src/core/state.c | 49 | ||||
| -rw-r--r-- | src/core/state.h | 186 | ||||
| -rw-r--r-- | src/core/symcache.c | 94 | ||||
| -rw-r--r-- | src/core/thread.c | 98 | ||||
| -rw-r--r-- | src/core/util.c | 12 | ||||
| -rw-r--r-- | src/core/value.c | 40 | ||||
| -rw-r--r-- | src/core/vm.c | 158 | ||||
| -rw-r--r-- | src/core/wrap.c | 2 | ||||
| -rw-r--r-- | src/include/janet.h | 7 |
23 files changed, 611 insertions, 579 deletions
@@ -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(®, 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(®, 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); |
