1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-18 11:19:56 +00:00

Use make-image-dict and load-image-dict in thread/new

Rather than messing with janet_core_dictionary, we
instead cache the core enevironment, and pull out the
needed tables from there. This is more flexible, more correct, and
also exposes janet_resolve_core, which can be easily used from the C
API.
This commit is contained in:
Calvin Rose 2019-12-02 04:15:22 -06:00
parent 212479188a
commit 70c8b6838d
7 changed files with 63 additions and 64 deletions

View File

@ -2068,17 +2068,6 @@
[& modules]
~(do ,;(map (fn [x] ~(,import* ,(string x) :prefix "")) modules)))
###
###
### Thread Extras
###
###
(defn thread/new
"Create a new thread. Same as (thread/new-ext make-image-dict load-image-dict)."
[]
(thread/new-ext make-image-dict load-image-dict))
###
###
### REPL

View File

@ -983,12 +983,6 @@ static void janet_load_libs(JanetTable *env) {
#ifdef JANET_BOOTSTRAP
JanetTable *janet_core_dictionary(JanetTable *replacements) {
(void) replacements;
janet_panic("not defined in bootstrap");
return NULL;
}
JanetTable *janet_core_env(JanetTable *replacements) {
JanetTable *env = (NULL != replacements) ? replacements : janet_table(0);
janet_quick_asm(env, JANET_FUN_PROP,
@ -1147,41 +1141,43 @@ JanetTable *janet_core_env(JanetTable *replacements) {
#else
JanetTable *janet_core_dictionary(JanetTable *replacements) {
JanetTable *dict;
if (NULL == janet_vm_core_dictionary) {
dict = janet_table(0);
janet_load_libs(dict);
janet_vm_core_dictionary = dict;
janet_gcroot(janet_wrap_table(dict));
/* do replacements */
if (NULL != replacements) {
for (int32_t i = 0; i < replacements->capacity; i++) {
if (!janet_checktype(replacements->data[i].key, JANET_NIL)) {
const JanetKV *kv = replacements->data + i;
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);
}
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;
}
/* Load core cfunctions (and some built in janet assembly functions) */
JanetTable *dict = janet_table(300);
janet_load_libs(dict);
/* Add replacements */
if (replacements != NULL) {
for (int32_t i = 0; i < replacements->capacity; i++) {
JanetKV kv = replacements->data[i];
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);
}
}
}
} else {
dict = janet_vm_core_dictionary;
}
return dict;
}
JanetTable *janet_core_env(JanetTable *replacements) {
JanetTable *dict = janet_core_dictionary(replacements);
/* Unmarshal bytecode */
Janet marsh_out = janet_unmarshal(
janet_core_image,
janet_core_image_size,
0,
dict,
NULL);
/* Memoize */
janet_gcroot(marsh_out);
return janet_unwrap_table(marsh_out);
JanetTable *env = janet_unwrap_table(marsh_out);
janet_vm_core_env = env;
return env;
}
#endif

View File

@ -32,8 +32,8 @@
* be in it. However, thread local global variables for interpreter
* state should allow easy multi-threading. */
/* The core dictionary is memoized */
extern JANET_THREAD_LOCAL JanetTable *janet_vm_core_dictionary;
/* 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;

View File

@ -32,6 +32,15 @@
#include <pthread.h>
#include <setjmp.h>
static JanetTable *janet_get_core_table(const char *name) {
JanetTable *env = janet_core_env(NULL);
Janet out = janet_wrap_nil();
JanetBindingType bt = janet_resolve(env, janet_csymbol(name), &out);
if (bt == JANET_BINDING_NONE) return NULL;
if (!janet_checktype(out, JANET_TABLE)) return NULL;
return janet_unwrap_table(out);
}
static void janet_channel_init(JanetChannel *channel, size_t initialSize) {
janet_buffer_init(&channel->buf, (int32_t) initialSize);
pthread_mutex_init(&channel->lock, NULL);
@ -212,20 +221,11 @@ static int thread_worker(JanetThreadShared *shared) {
janet_init();
/* Get dictionaries */
JanetTable *decode = janet_core_dictionary(NULL);
JanetTable *encode = janet_table(decode->count);
for (int32_t i = 0; i < decode->capacity; i++) {
JanetKV *kv = decode->data + i;
if (!janet_checktype(kv->key, JANET_NIL)) {
janet_table_put(encode, kv->value, kv->key);
}
}
janet_gcroot(janet_wrap_table(encode));
JanetTable *decode = janet_get_core_table("load-image-dict");
JanetTable *encode = janet_get_core_table("make-image-dict");
/* Create self thread */
JanetThread *thread = janet_make_thread(shared, encode, decode, JANET_THREAD_SELF);
thread->encode = encode;
thread->decode = decode;
Janet threadv = janet_wrap_abstract(thread);
/* Unmarshal the function */
@ -275,10 +275,14 @@ static void janet_thread_start_child(JanetThread *thread) {
* Cfuns
*/
static Janet cfun_thread_new_ext(int32_t argc, Janet *argv) {
janet_fixarity(argc, 2);
JanetTable *encode = janet_gettable(argv, 0);
JanetTable *decode = janet_gettable(argv, 1);
static Janet cfun_thread_new(int32_t argc, Janet *argv) {
janet_arity(argc, 0, 2);
JanetTable *encode = (argc < 1 || janet_checktype(argv[0], JANET_NIL))
? janet_get_core_table("make-image-dict")
: janet_gettable(argv, 0);
JanetTable *decode = (argc < 2 || janet_checktype(argv[1], JANET_NIL))
? janet_get_core_table("load-image-dict")
: janet_gettable(argv, 1);
JanetThreadShared *shared = janet_shared_create(0);
JanetThread *thread = janet_make_thread(shared, encode, decode, JANET_THREAD_OTHER);
janet_thread_start_child(thread);
@ -316,8 +320,8 @@ static Janet cfun_thread_receive(int32_t argc, Janet *argv) {
static const JanetReg threadlib_cfuns[] = {
{
"thread/new-ext", cfun_thread_new_ext,
JDOC("(thread/new-ext encode-book decode-book)\n\n"
"thread/new", cfun_thread_new,
JDOC("(thread/new &opt encode-book decode-book)\n\n"
"Start a new thread. The thread will wait for a message containing the function used to start the thread, which should be subsequently "
"sent over after thread creation.")
},

View File

@ -370,6 +370,14 @@ JanetBindingType janet_resolve(JanetTable *env, const uint8_t *sym, Janet *out)
return JANET_BINDING_DEF;
}
/* Resolve a symbol in the core environment. */
Janet janet_resolve_core(const char *name) {
JanetTable *env = janet_core_env(NULL);
Janet out = janet_wrap_nil();
janet_resolve(env, janet_csymbol(name), &out);
return out;
}
/* Read both tuples and arrays as c pointers + int32_t length. Return 1 if the
* view can be constructed, 0 if an invalid type. */
int janet_indexed_view(Janet seq, const Janet **data, int32_t *len) {

View File

@ -30,7 +30,7 @@
#endif
/* VM state */
JANET_THREAD_LOCAL JanetTable *janet_vm_core_dictionary;
JANET_THREAD_LOCAL JanetTable *janet_vm_core_env;
JANET_THREAD_LOCAL JanetTable *janet_vm_registry;
JANET_THREAD_LOCAL int janet_vm_stackn = 0;
JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber = NULL;
@ -1241,8 +1241,8 @@ int janet_init(void) {
/* Initialize registry */
janet_vm_registry = janet_table(0);
janet_gcroot(janet_wrap_table(janet_vm_registry));
/* Core env and dictionary */
janet_vm_core_dictionary = NULL;
/* Core env */
janet_vm_core_env = NULL;
/* Seed RNG */
janet_rng_seed(janet_default_rng(), 0);
return 0;
@ -1257,5 +1257,5 @@ void janet_deinit(void) {
janet_vm_root_count = 0;
janet_vm_root_capacity = 0;
janet_vm_registry = NULL;
janet_vm_core_dictionary = NULL;
janet_vm_core_env = NULL;
}

View File

@ -1126,7 +1126,6 @@ struct JanetCompileResult {
JANET_API JanetCompileResult janet_compile(Janet source, JanetTable *env, const uint8_t *where);
/* Get the default environment for janet */
JANET_API JanetTable *janet_core_dictionary(JanetTable *replacements); /* Used for unmarshaling images */
JANET_API JanetTable *janet_core_env(JanetTable *replacements);
JANET_API int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath, Janet *out);
@ -1359,6 +1358,9 @@ JANET_API void janet_cfuns(JanetTable *env, const char *regprefix, const JanetRe
JANET_API JanetBindingType janet_resolve(JanetTable *env, const uint8_t *sym, Janet *out);
JANET_API void janet_register(const char *name, JanetCFunction cfun);
/* Get values from the core environment. */
JANET_API Janet janet_resolve_core(const char *name);
/* New C API */
/* Allow setting entry name for static libraries */