From 7b31a87b3c0d4f6620fcdb5fb2b1e8ff27c26c63 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 3 Jul 2020 14:14:59 -0500 Subject: [PATCH 1/8] Update integer limits and printing. --- CHANGELOG.md | 1 + src/core/inttypes.c | 12 ++++++------ src/core/math.c | 8 ++++++++ src/core/pp.c | 6 ++---- src/core/util.h | 12 ++++++------ src/include/janet.h | 8 ++++---- 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0ff15a6..16307c21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ All notable changes to this project will be documented in this file. ## Unreleased - ??? +- Add `math/int-min`, `math/int-max`, `math/int32-min`, and `math/int32-max` for getting integer limits. - The gc interval is now autotuned, to prevent very bad gc behavior. - Improvements to the bytecode compiler, Janet will now generate more efficient bytecode. - Add `peg/find`, `peg/find-all`, `peg/replace`, and `peg/replace-all` diff --git a/src/core/inttypes.c b/src/core/inttypes.c index e11bcdab..4d53ec70 100644 --- a/src/core/inttypes.c +++ b/src/core/inttypes.c @@ -20,18 +20,18 @@ * IN THE SOFTWARE. */ -#include -#include -#include -#include -#include - #ifndef JANET_AMALG #include "features.h" #include #include "util.h" #endif +#include +#include +#include +#include +#include + /* Conditional compilation */ #ifdef JANET_INT_TYPES diff --git a/src/core/math.c b/src/core/math.c index 5491c77d..808267cc 100644 --- a/src/core/math.c +++ b/src/core/math.c @@ -499,6 +499,14 @@ void janet_lib_math(JanetTable *env) { JDOC("The number representing positive infinity")); janet_def(env, "math/-inf", janet_wrap_number(-INFINITY), JDOC("The number representing negative infinity")); + janet_def(env, "math/int32-min", janet_wrap_number(INT32_MIN), + JDOC("The maximum contiguous integer representable by a 32 bit signed integer")); + janet_def(env, "math/int32-max", janet_wrap_number(INT32_MAX), + JDOC("The minimum contiguous integer represtenable by a 32 bit signed integer")); + janet_def(env, "math/int-min", janet_wrap_number(JANET_INTMIN_DOUBLE), + JDOC("The maximum contiguous integer representable by a double (2^53)")); + janet_def(env, "math/int-max", janet_wrap_number(JANET_INTMAX_DOUBLE), + JDOC("The minimum contiguous integer represtenable by a double (-(2^53))")); #ifdef NAN janet_def(env, "math/nan", janet_wrap_number(NAN), #else diff --git a/src/core/pp.c b/src/core/pp.c index 3a855536..13550ca9 100644 --- a/src/core/pp.c +++ b/src/core/pp.c @@ -39,11 +39,9 @@ static void number_to_string_b(JanetBuffer *buffer, double x) { janet_buffer_ensure(buffer, buffer->count + BUFSIZE, 2); - /* Use int32_t range for valid integers because that is the - * range most integer-expecting functions in the C api use. */ const char *fmt = (x == floor(x) && - x <= ((double) INT32_MAX) && - x >= ((double) INT32_MIN)) ? "%.0f" : "%g"; + x <= JANET_INTMAX_DOUBLE && + x >= JANET_INTMIN_DOUBLE) ? "%.0f" : "%g"; int count = snprintf((char *) buffer->data + buffer->count, BUFSIZE, fmt, x); buffer->count += count; } diff --git a/src/core/util.h b/src/core/util.h index e8eb9b81..10c40a70 100644 --- a/src/core/util.h +++ b/src/core/util.h @@ -31,6 +31,11 @@ #include #include +#if !defined(JANET_REDUCED_OS) || !defined(JANET_SINGLE_THREADED) +#include +#define JANET_GETTIME +#endif + /* Handle runtime errors */ #ifndef JANET_EXIT #include @@ -98,12 +103,7 @@ void janet_core_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cf #endif /* Clock gettime */ -#if !defined(JANET_REDUCED_OS) || !defined(JANET_SINGLE_THREADED) -#include -#ifndef JANET_WINDOWS -#include -#endif -#define JANET_GETTIME +#ifdef JANET_GETTIME int janet_gettime(struct timespec *spec); #endif diff --git a/src/include/janet.h b/src/include/janet.h index 38446a3a..86410d71 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -128,10 +128,10 @@ extern "C" { #endif /* Limits for converting doubles to 64 bit integers */ -#define JANET_INTMAX_DOUBLE 9007199254740991.0 -#define JANET_INTMIN_DOUBLE (-9007199254740991.0) -#define JANET_INTMAX_INT64 9007199254740991 -#define JANET_INTMIN_INT64 (-9007199254740991) +#define JANET_INTMAX_DOUBLE 9007199254740992.0 +#define JANET_INTMIN_DOUBLE (-9007199254740992.0) +#define JANET_INTMAX_INT64 9007199254740992 +#define JANET_INTMIN_INT64 (-9007199254740992) /* Check emscripten */ #ifdef __EMSCRIPTEN__ From dc259b9f8e18e2b80ebcb51c6bf1134b60c5acfa Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 3 Jul 2020 15:20:19 -0500 Subject: [PATCH 2/8] Set fiber env for heavyweight threads. Since you already incur the cost of creating the core environment, this is probably what you want anyways. This will make eval and other reflective code work as expected. --- src/core/thread.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/thread.c b/src/core/thread.c index d1d6cbab..336ce09a 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -499,6 +499,10 @@ static int thread_worker(JanetMailboxPair *pair) { /* Call function */ Janet argv[1] = { parentv }; fiber = janet_fiber(func, 64, 1, argv); + if (pair->flags & JANET_THREAD_HEAVYWEIGHT) { + fiber->env = janet_table(0); + fiber->env->proto = janet_core_env(NULL); + } JanetSignal sig = janet_continue(fiber, janet_wrap_nil(), &out); if (sig != JANET_SIGNAL_OK && sig < JANET_SIGNAL_USER0) { janet_eprintf("in thread %v: ", janet_wrap_abstract(janet_make_thread(pair->newbox, encode))); From 617ec7f5652864ef3eff100b07c2f365015db0c5 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 3 Jul 2020 16:19:05 -0500 Subject: [PATCH 3/8] Threading improvements. - Add thread/exit to kill the current thread. - Add global lock aroung custom getline and add atexit handler - to prevent any possible issues when exiting program. - Allow sending stderr, stdout, and stdin over thread. --- src/core/capi.c | 16 +++++++++- src/core/io.c | 68 +++++++++++++++++++++++++++++++++--------- src/core/thread.c | 18 +++++++++++ src/include/janet.h | 8 ++--- src/mainclient/shell.c | 43 ++++++++++++++++---------- 5 files changed, 119 insertions(+), 34 deletions(-) diff --git a/src/core/capi.c b/src/core/capi.c index ce681b49..e661b942 100644 --- a/src/core/capi.c +++ b/src/core/capi.c @@ -27,12 +27,26 @@ #include "fiber.h" #endif +#ifndef JANET_SINGLE_THREADED +#ifndef JANET_WINDOWS +#include +#else +#include +#endif +#endif + JANET_NO_RETURN static void janet_top_level_signal(const char *msg) { #ifdef JANET_TOP_LEVEL_SIGNAL JANET_TOP_LEVEL_SIGNAL(msg); #else fputs(msg, stdout); - exit(1); +# ifdef JANET_SINGLE_THREADED + exit(-1); +# elif defined(JANET_WINDOWS) + ExitThread(-1); +# else + pthread_exit(NULL); +# endif #endif } diff --git a/src/core/io.c b/src/core/io.c index 12610354..270d4f00 100644 --- a/src/core/io.c +++ b/src/core/io.c @@ -37,18 +37,23 @@ static int cfun_io_gc(void *p, size_t len); static int io_file_get(void *p, Janet key, Janet *out); +static void io_file_marshal(void *p, JanetMarshalContext *ctx); +static void *io_file_unmarshal(JanetMarshalContext *ctx); const JanetAbstractType janet_file_type = { "core/file", cfun_io_gc, NULL, io_file_get, - JANET_ATEND_GET + NULL, + io_file_marshal, + io_file_unmarshal, + JANET_ATEND_UNMARSHAL }; /* Check arguments to fopen */ -static int checkflags(const uint8_t *str) { - int flags = 0; +static int32_t checkflags(const uint8_t *str) { + int32_t flags = 0; int32_t i; int32_t len = janet_string_length(str); if (!len || len > 3) @@ -85,7 +90,7 @@ static int checkflags(const uint8_t *str) { return flags; } -static Janet makef(FILE *f, int flags) { +static void *makef(FILE *f, int32_t flags) { JanetFile *iof = (JanetFile *) janet_abstract(&janet_file_type, sizeof(JanetFile)); iof->file = f; iof->flags = flags; @@ -95,7 +100,7 @@ static Janet makef(FILE *f, int flags) { if (!(flags & JANET_FILE_NOT_CLOSEABLE)) fcntl(fileno(f), F_SETFD, FD_CLOEXEC); #endif - return janet_wrap_abstract(iof); + return iof; } /* Open a process */ @@ -104,7 +109,7 @@ static Janet cfun_io_popen(int32_t argc, Janet *argv) { janet_arity(argc, 1, 2); const uint8_t *fname = janet_getstring(argv, 0); const uint8_t *fmode = NULL; - int flags; + int32_t flags; if (argc == 2) { fmode = janet_getkeyword(argv, 1); if (janet_string_length(fmode) != 1 || @@ -123,7 +128,7 @@ static Janet cfun_io_popen(int32_t argc, Janet *argv) { if (!f) { return janet_wrap_nil(); } - return makef(f, flags); + return janet_makefile(f, flags); } #endif @@ -141,7 +146,7 @@ static Janet cfun_io_fopen(int32_t argc, Janet *argv) { janet_arity(argc, 1, 2); const uint8_t *fname = janet_getstring(argv, 0); const uint8_t *fmode; - int flags; + int32_t flags; if (argc == 2) { fmode = janet_getkeyword(argv, 1); flags = checkflags(fmode); @@ -150,7 +155,7 @@ static Janet cfun_io_fopen(int32_t argc, Janet *argv) { flags = JANET_FILE_READ; } FILE *f = fopen((const char *)fname, (const char *)fmode); - return f ? makef(f, flags) : janet_wrap_nil(); + return f ? janet_makefile(f, flags) : janet_wrap_nil(); } /* Read up to n bytes into buffer. */ @@ -331,6 +336,41 @@ static int io_file_get(void *p, Janet key, Janet *out) { return janet_getmethod(janet_unwrap_keyword(key), io_file_methods, out); } +static void io_file_marshal(void *p, JanetMarshalContext *ctx) { + JanetFile *iof = (JanetFile *)p; + if (ctx->flags & JANET_MARSHAL_UNSAFE) { + janet_marshal_int(ctx, fileno(iof->file)); + janet_marshal_int(ctx, iof->flags); + } else { + janet_panic("cannot marshal file in safe mode"); + } +} + +static void *io_file_unmarshal(JanetMarshalContext *ctx) { + if (ctx->flags & JANET_MARSHAL_UNSAFE) { + JanetFile *iof = janet_unmarshal_abstract(ctx, sizeof(JanetFile)); + int32_t fd = janet_unmarshal_int(ctx); + int32_t flags = janet_unmarshal_int(ctx); + char fmt[4] = {0}; + int index = 0; + if (flags & JANET_FILE_READ) fmt[index++] = 'r'; + if (flags & JANET_FILE_APPEND) { + fmt[index++] = 'a'; + } else if (flags & JANET_FILE_WRITE) { + fmt[index++] = 'w'; + } + iof->file = fdopen(fd, fmt); + if (iof->file == NULL) { + iof->flags = JANET_FILE_CLOSED; + } else { + iof->flags = flags; + } + return iof; + } else { + janet_panic("cannot unmarshal file in safe mode"); + } +} + FILE *janet_dynfile(const char *name, FILE *def) { Janet x = janet_dyn(name); if (!janet_checktype(x, JANET_ABSTRACT)) return def; @@ -677,7 +717,7 @@ FILE *janet_getfile(const Janet *argv, int32_t n, int *flags) { } Janet janet_makefile(FILE *f, int flags) { - return makef(f, flags); + return janet_wrap_abstract(makef(f, flags)); } JanetAbstract janet_checkfile(Janet j) { @@ -693,18 +733,18 @@ FILE *janet_unwrapfile(Janet j, int *flags) { /* Module entry point */ void janet_lib_io(JanetTable *env) { janet_core_cfuns(env, NULL, io_cfuns); - + janet_register_abstract_type(&janet_file_type); /* stdout */ janet_core_def(env, "stdout", - makef(stdout, JANET_FILE_APPEND | JANET_FILE_NOT_CLOSEABLE | JANET_FILE_SERIALIZABLE), + janet_makefile(stdout, JANET_FILE_APPEND | JANET_FILE_NOT_CLOSEABLE | JANET_FILE_SERIALIZABLE), JDOC("The standard output file.")); /* stderr */ janet_core_def(env, "stderr", - makef(stderr, JANET_FILE_APPEND | JANET_FILE_NOT_CLOSEABLE | JANET_FILE_SERIALIZABLE), + janet_makefile(stderr, JANET_FILE_APPEND | JANET_FILE_NOT_CLOSEABLE | JANET_FILE_SERIALIZABLE), JDOC("The standard error file.")); /* stdin */ janet_core_def(env, "stdin", - makef(stdin, JANET_FILE_READ | JANET_FILE_NOT_CLOSEABLE | JANET_FILE_SERIALIZABLE), + janet_makefile(stdin, JANET_FILE_READ | JANET_FILE_NOT_CLOSEABLE | JANET_FILE_SERIALIZABLE), JDOC("The standard input file.")); } diff --git a/src/core/thread.c b/src/core/thread.c index 336ce09a..dd799ad3 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -675,6 +675,18 @@ static Janet cfun_thread_close(int32_t argc, Janet *argv) { return janet_wrap_nil(); } +static Janet cfun_thread_exit(int32_t argc, Janet *argv) { + (void) argv; + janet_arity(argc, 0, 1); +#if defined(JANET_WINDOWS) + int32_t flag = janet_optinteger(argv, argc, 0, 0); + ExitThread(flag); +#else + pthread_exit(NULL); +#endif + return janet_wrap_nil(); +} + static const JanetMethod janet_thread_methods[] = { {"send", cfun_thread_send}, {"close", cfun_thread_close}, @@ -723,6 +735,12 @@ static const JanetReg threadlib_cfuns[] = { "Close a thread, unblocking it and ending communication with it. Note that closing " "a thread is idempotent and does not cancel the thread's operation. Returns nil.") }, + { + "thread/exit", cfun_thread_exit, + JDOC("(thread/exit &opt code)\n\n" + "Exit from the current thread. If no more threads are running, ends the process, but otherwise does " + "not end the current process.") + }, {NULL, NULL, NULL} }; diff --git a/src/include/janet.h b/src/include/janet.h index 86410d71..05fd8a0f 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -1002,7 +1002,7 @@ struct JanetRNG { typedef struct JanetFile JanetFile; struct JanetFile { FILE *file; - int flags; + int32_t flags; }; /* Thread types */ @@ -1534,11 +1534,11 @@ extern JANET_API const JanetAbstractType janet_file_type; #define JANET_FILE_SERIALIZABLE 128 #define JANET_FILE_PIPED 256 -JANET_API Janet janet_makefile(FILE *f, int flags); -JANET_API FILE *janet_getfile(const Janet *argv, int32_t n, int *flags); +JANET_API Janet janet_makefile(FILE *f, int32_t flags); +JANET_API FILE *janet_getfile(const Janet *argv, int32_t n, int32_t *flags); JANET_API FILE *janet_dynfile(const char *name, FILE *def); JANET_API JanetAbstract janet_checkfile(Janet j); -JANET_API FILE *janet_unwrapfile(Janet j, int *flags); +JANET_API FILE *janet_unwrapfile(Janet j, int32_t *flags); /* Marshal API */ JANET_API void janet_marshal_size(JanetMarshalContext *ctx, size_t value); diff --git a/src/mainclient/shell.c b/src/mainclient/shell.c index 3855dce3..2c28c9bb 100644 --- a/src/mainclient/shell.c +++ b/src/mainclient/shell.c @@ -126,21 +126,28 @@ https://github.com/antirez/linenoise/blob/master/linenoise.c #define JANET_LINE_MAX 1024 #define JANET_MATCH_MAX 256 #define JANET_HISTORY_MAX 100 -static JANET_THREAD_LOCAL int gbl_israwmode = 0; -static JANET_THREAD_LOCAL const char *gbl_prompt = "> "; -static JANET_THREAD_LOCAL int gbl_plen = 2; -static JANET_THREAD_LOCAL char gbl_buf[JANET_LINE_MAX]; -static JANET_THREAD_LOCAL int gbl_len = 0; -static JANET_THREAD_LOCAL int gbl_pos = 0; -static JANET_THREAD_LOCAL int gbl_cols = 80; -static JANET_THREAD_LOCAL char *gbl_history[JANET_HISTORY_MAX]; -static JANET_THREAD_LOCAL int gbl_history_count = 0; -static JANET_THREAD_LOCAL int gbl_historyi = 0; -static JANET_THREAD_LOCAL int gbl_sigint_flag = 0; -static JANET_THREAD_LOCAL struct termios gbl_termios_start; -static JANET_THREAD_LOCAL JanetByteView gbl_matches[JANET_MATCH_MAX]; -static JANET_THREAD_LOCAL int gbl_match_count = 0; -static JANET_THREAD_LOCAL int gbl_lines_below = 0; +static int gbl_israwmode = 0; +static const char *gbl_prompt = "> "; +static int gbl_plen = 2; +static char gbl_buf[JANET_LINE_MAX]; +static int gbl_len = 0; +static int gbl_pos = 0; +static int gbl_cols = 80; +static char *gbl_history[JANET_HISTORY_MAX]; +static int gbl_history_count = 0; +static int gbl_historyi = 0; +static int gbl_sigint_flag = 0; +static struct termios gbl_termios_start; +static JanetByteView gbl_matches[JANET_MATCH_MAX]; +static int gbl_match_count = 0; +static int gbl_lines_below = 0; + +/* Put a lock around this global state so we don't screw up + * the terminal in a multithreaded situation */ +#ifndef JANET_SINGLE_THREADED +#include +static pthread_mutex_t gbl_lock = PTHREAD_MUTEX_INITIALIZER; +#endif /* Unsupported terminal list from linenoise */ static const char *badterms[] = { @@ -162,6 +169,7 @@ static char *sdup(const char *s) { /* Ansi terminal raw mode */ static int rawmode(void) { struct termios t; + pthread_mutex_lock(&gbl_lock); if (!isatty(STDIN_FILENO)) goto fatal; if (tcgetattr(STDIN_FILENO, &gbl_termios_start) == -1) goto fatal; t = gbl_termios_start; @@ -175,6 +183,7 @@ static int rawmode(void) { return 0; fatal: errno = ENOTTY; + pthread_mutex_unlock(&gbl_lock); return -1; } @@ -182,6 +191,7 @@ fatal: static void norawmode(void) { if (gbl_israwmode && tcsetattr(STDIN_FILENO, TCSAFLUSH, &gbl_termios_start) != -1) gbl_israwmode = 0; + pthread_mutex_unlock(&gbl_lock); } static int curpos(void) { @@ -996,6 +1006,9 @@ int main(int argc, char **argv) { SetConsoleOutputCP(65001); #endif + /* Try and not leave the terminal in a bad state */ + atexit(norawmode); + /* Set up VM */ janet_init(); From 3bb8f1ac8dfc234dbb8d40821c70cd8d52c75968 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 3 Jul 2020 19:54:58 -0500 Subject: [PATCH 4/8] Don't use CLOCK_MONOTONIC for pthread stuff. Also fix marshalling functions without full sourcemapping information, as well as thread/receive ignoring bad messages. Instead, thread/receive will error on bad messages. --- src/core/asm.c | 3 +++ src/core/compile.c | 27 ++++++++++++++++++++++++++- src/core/corelib.c | 1 + src/core/marsh.c | 17 ++++------------- src/core/thread.c | 9 +++++++-- src/core/util.c | 2 +- src/core/util.h | 1 + 7 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/core/asm.c b/src/core/asm.c index 4793dc25..961b671d 100644 --- a/src/core/asm.c +++ b/src/core/asm.c @@ -720,6 +720,9 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int janet_asm_error(&a, "invalid assembly"); } + /* Add final flags */ + janet_def_addflags(def); + /* Finish everything and return funcdef */ janet_asm_deinit(&a); result.error = NULL; diff --git a/src/core/compile.c b/src/core/compile.c index dd802b3e..f7f8bfa0 100644 --- a/src/core/compile.c +++ b/src/core/compile.c @@ -698,6 +698,29 @@ JanetSlot janetc_value(JanetFopts opts, Janet x) { return ret; } +/* Add function flags to janet functions */ +void janet_def_addflags(JanetFuncDef *def) { + int32_t set_flags = 0; + int32_t unset_flags = 0; + /* pos checks */ + if (def->name) set_flags |= JANET_FUNCDEF_FLAG_HASNAME; + if (def->source) set_flags |= JANET_FUNCDEF_FLAG_HASSOURCE; + if (def->defs) set_flags |= JANET_FUNCDEF_FLAG_HASDEFS; + if (def->environments) set_flags |= JANET_FUNCDEF_FLAG_HASENVS; + if (def->sourcemap) set_flags |= JANET_FUNCDEF_FLAG_HASSOURCEMAP; + if (def->closure_bitset) set_flags |= JANET_FUNCDEF_FLAG_HASCLOBITSET; + /* negative checks */ + if (!def->name) unset_flags |= JANET_FUNCDEF_FLAG_HASNAME; + if (!def->source) unset_flags |= JANET_FUNCDEF_FLAG_HASSOURCE; + if (!def->defs) unset_flags |= JANET_FUNCDEF_FLAG_HASDEFS; + if (!def->environments) unset_flags |= JANET_FUNCDEF_FLAG_HASENVS; + if (!def->sourcemap) unset_flags |= JANET_FUNCDEF_FLAG_HASSOURCEMAP; + if (!def->closure_bitset) unset_flags |= JANET_FUNCDEF_FLAG_HASCLOBITSET; + /* Update flags */ + def->flags |= set_flags; + def->flags &= ~unset_flags; +} + /* Compile a funcdef */ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) { JanetScope *scope = c->scope; @@ -761,12 +784,14 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) { /* Register allocator preallocates some registers [240-255, high 16 bits of chunk index 7], we can ignore those. */ if (scope->ua.count > 7) chunks[7] &= 0xFFFFU; def->closure_bitset = chunks; - def->flags |= JANET_FUNCDEF_FLAG_HASCLOBITSET; } /* Pop the scope */ janetc_popscope(c); + /* Finalize some flags */ + janet_def_addflags(def); + return def; } diff --git a/src/core/corelib.c b/src/core/corelib.c index a488365b..da90bb2b 100644 --- a/src/core/corelib.c +++ b/src/core/corelib.c @@ -741,6 +741,7 @@ static void janet_quick_asm( JANET_OUT_OF_MEMORY; } memcpy(def->bytecode, bytecode, bytecode_size); + janet_def_addflags(def); janet_def(env, name, janet_wrap_function(janet_thunk(def)), doc); } diff --git a/src/core/marsh.c b/src/core/marsh.c index 534f1869..fac32663 100644 --- a/src/core/marsh.c +++ b/src/core/marsh.c @@ -214,15 +214,6 @@ static void marshal_one_env(MarshalState *st, JanetFuncEnv *env, int flags) { } } -/* Add function flags to janet functions */ -static void janet_func_addflags(JanetFuncDef *def) { - if (def->name) def->flags |= JANET_FUNCDEF_FLAG_HASNAME; - if (def->source) def->flags |= JANET_FUNCDEF_FLAG_HASSOURCE; - if (def->defs) def->flags |= JANET_FUNCDEF_FLAG_HASDEFS; - if (def->environments) def->flags |= JANET_FUNCDEF_FLAG_HASENVS; - if (def->sourcemap) def->flags |= JANET_FUNCDEF_FLAG_HASSOURCEMAP; -} - /* Marshal a sequence of u32s */ static void janet_marshal_u32s(MarshalState *st, const uint32_t *u32s, int32_t n) { for (int32_t i = 0; i < n; i++) { @@ -243,7 +234,6 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) { return; } } - janet_func_addflags(def); /* Add to lookup */ janet_v_push(st->seen_defs, def); pushint(st, def->flags); @@ -900,7 +890,7 @@ static const uint8_t *unmarshal_one_def( for (int32_t i = 0; i < bytecode_length; i++) { current += readint(st, &data); def->sourcemap[i].line = current; - def->sourcemap[i].column = readnat(st, &data); + def->sourcemap[i].column = readint(st, &data); } } else { def->sourcemap = NULL; @@ -908,11 +898,12 @@ static const uint8_t *unmarshal_one_def( /* Unmarshal closure bitset if needed */ if (def->flags & JANET_FUNCDEF_FLAG_HASCLOBITSET) { - def->closure_bitset = malloc(sizeof(uint32_t) * def->slotcount); + size_t n = (size_t)(def->slotcount + 31) >> 5; + def->closure_bitset = malloc(sizeof(uint32_t) * n); if (NULL == def->closure_bitset) { JANET_OUT_OF_MEMORY; } - data = janet_unmarshal_u32s(st, data, def->closure_bitset, (def->slotcount + 31) >> 5); + data = janet_unmarshal_u32s(st, data, def->closure_bitset, n); } /* Validate */ diff --git a/src/core/thread.c b/src/core/thread.c index dd799ad3..44ad4b88 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -375,8 +375,12 @@ int janet_thread_receive(Janet *msg_out, double timeout) { /* Handle errors */ if (setjmp(buf)) { - /* Cleanup jmp_buf, keep lock */ + /* 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_mailbox_unlock(mailbox); + return 2; } else { JanetBuffer *msgbuf = mailbox->messages + mailbox->messageFirst; mailbox->messageCount--; @@ -411,7 +415,6 @@ int janet_thread_receive(Janet *msg_out, double timeout) { return 1; } } - } static int janet_thread_getter(void *p, Janet key, Janet *out); @@ -664,6 +667,8 @@ static Janet cfun_thread_receive(int32_t argc, Janet *argv) { break; case 1: janet_panicf("timeout after %f seconds", wait); + case 2: + janet_panicf("failed to receive message: %v", out); } return out; } diff --git a/src/core/util.c b/src/core/util.c index 847e7471..407545f6 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -621,7 +621,7 @@ int janet_gettime(struct timespec *spec) { } #else int janet_gettime(struct timespec *spec) { - return clock_gettime(CLOCK_MONOTONIC, spec); + return clock_gettime(CLOCK_REALTIME, spec); } #endif #endif diff --git a/src/core/util.h b/src/core/util.h index 10c40a70..70090a52 100644 --- a/src/core/util.h +++ b/src/core/util.h @@ -80,6 +80,7 @@ Janet janet_dict_get(const JanetKV *buckets, int32_t cap, Janet key); void janet_memempty(JanetKV *mem, int32_t count); void *janet_memalloc_empty(int32_t count); JanetTable *janet_get_core_table(const char *name); +void janet_def_addflags(JanetFuncDef *def); const void *janet_strbinsearch( const void *tab, size_t tabcount, From 2b36ed967c7070a56f78afdb50758a7780ace09f Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 3 Jul 2020 20:13:49 -0500 Subject: [PATCH 5/8] Address some windows issues. --- src/core/io.c | 8 ++++++++ src/core/marsh.c | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/core/io.c b/src/core/io.c index 270d4f00..4dbcee58 100644 --- a/src/core/io.c +++ b/src/core/io.c @@ -339,7 +339,11 @@ static int io_file_get(void *p, Janet key, Janet *out) { static void io_file_marshal(void *p, JanetMarshalContext *ctx) { JanetFile *iof = (JanetFile *)p; if (ctx->flags & JANET_MARSHAL_UNSAFE) { +#ifdef JANET_WINDOWS + janet_marshal_int(ctx, _fileno(iof->file)); +#else janet_marshal_int(ctx, fileno(iof->file)); +#endif janet_marshal_int(ctx, iof->flags); } else { janet_panic("cannot marshal file in safe mode"); @@ -359,7 +363,11 @@ static void *io_file_unmarshal(JanetMarshalContext *ctx) { } else if (flags & JANET_FILE_WRITE) { fmt[index++] = 'w'; } +#ifdef JANET_WINDOWS + iof->file = _fdopen(fd, fmt); +#else iof->file = fdopen(fd, fmt); +#endif if (iof->file == NULL) { iof->flags = JANET_FILE_CLOSED; } else { diff --git a/src/core/marsh.c b/src/core/marsh.c index fac32663..ebef9239 100644 --- a/src/core/marsh.c +++ b/src/core/marsh.c @@ -898,8 +898,8 @@ static const uint8_t *unmarshal_one_def( /* Unmarshal closure bitset if needed */ if (def->flags & JANET_FUNCDEF_FLAG_HASCLOBITSET) { - size_t n = (size_t)(def->slotcount + 31) >> 5; - def->closure_bitset = malloc(sizeof(uint32_t) * n); + int32_t n = (def->slotcount + 31) >> 5; + def->closure_bitset = malloc(sizeof(uint32_t) * (size_t) n); if (NULL == def->closure_bitset) { JANET_OUT_OF_MEMORY; } From 4721337c7c5a82f2848571b23813ce16e3238e5a Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 3 Jul 2020 20:19:36 -0500 Subject: [PATCH 6/8] issues with gettime on mach kernel. --- src/core/util.c | 5 +++++ src/mainclient/shell.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/core/util.c b/src/core/util.c index 407545f6..d4af5667 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -596,6 +596,11 @@ JanetTable *janet_get_core_table(const char *name) { /* Clock shims for various platforms */ #ifdef JANET_GETTIME +/* For macos */ +#ifdef __MACH__ +#include +#include +#endif #ifdef JANET_WINDOWS int janet_gettime(struct timespec *spec) { FILETIME ftime; diff --git a/src/mainclient/shell.c b/src/mainclient/shell.c index 2c28c9bb..600ac8c3 100644 --- a/src/mainclient/shell.c +++ b/src/mainclient/shell.c @@ -1006,8 +1006,10 @@ int main(int argc, char **argv) { SetConsoleOutputCP(65001); #endif +#if !defined(JANET_WINDOWS) && !defined(JANET_SIMPLE_GETLINE) /* Try and not leave the terminal in a bad state */ atexit(norawmode); +#endif /* Set up VM */ janet_init(); From c97d3cf359aa2d56d2e211a490429d02a5a1d654 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 3 Jul 2020 20:30:09 -0500 Subject: [PATCH 7/8] Fix minimum meson build. --- .builds/meson_min.yml | 2 +- src/mainclient/shell.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.builds/meson_min.yml b/.builds/meson_min.yml index e8386ca8..ab4f450f 100644 --- a/.builds/meson_min.yml +++ b/.builds/meson_min.yml @@ -17,7 +17,7 @@ tasks: meson configure -Dpeg=false meson configure -Dassembler=false meson configure -Dint_types=false - meson configure -Dtyped_arrays=false + meson configure -Dtyped_array=false meson configure -Dreduced_os=true meson configure -Dprf=false ninja # will not pass tests but should build diff --git a/src/mainclient/shell.c b/src/mainclient/shell.c index 600ac8c3..e1628eac 100644 --- a/src/mainclient/shell.c +++ b/src/mainclient/shell.c @@ -169,7 +169,9 @@ static char *sdup(const char *s) { /* Ansi terminal raw mode */ static int rawmode(void) { struct termios t; +#ifndef JANET_SINGLE_THREADED pthread_mutex_lock(&gbl_lock); +#endif if (!isatty(STDIN_FILENO)) goto fatal; if (tcgetattr(STDIN_FILENO, &gbl_termios_start) == -1) goto fatal; t = gbl_termios_start; @@ -183,7 +185,9 @@ static int rawmode(void) { return 0; fatal: errno = ENOTTY; +#ifndef JANET_SINGLE_THREADED pthread_mutex_unlock(&gbl_lock); +#endif return -1; } @@ -191,7 +195,9 @@ fatal: static void norawmode(void) { if (gbl_israwmode && tcsetattr(STDIN_FILENO, TCSAFLUSH, &gbl_termios_start) != -1) gbl_israwmode = 0; +#ifndef JANET_SINGLE_THREADED pthread_mutex_unlock(&gbl_lock); +#endif } static int curpos(void) { From 68a12d1d17550716ca7b5b4876a27d6cbbd4caa3 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 3 Jul 2020 20:41:55 -0500 Subject: [PATCH 8/8] Minor fixes for meson minimum build. Also, fix regression that looses function name information. --- src/core/compile.c | 6 +++--- src/core/specials.c | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/compile.c b/src/core/compile.c index f7f8bfa0..57c9cbe2 100644 --- a/src/core/compile.c +++ b/src/core/compile.c @@ -722,6 +722,8 @@ void janet_def_addflags(JanetFuncDef *def) { } /* Compile a funcdef */ +/* Once the various other settings of the FuncDef have been tweaked, + * call janet_def_addflags to set the proper flags for the funcdef */ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) { JanetScope *scope = c->scope; JanetFuncDef *def = janet_funcdef_alloc(); @@ -789,9 +791,6 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) { /* Pop the scope */ janetc_popscope(c); - /* Finalize some flags */ - janet_def_addflags(def); - return def; } @@ -843,6 +842,7 @@ JanetCompileResult janet_compile(Janet source, JanetTable *env, const uint8_t *w if (c.result.status == JANET_COMPILE_OK) { JanetFuncDef *def = janetc_pop_funcdef(&c); def->name = janet_cstring("_thunk"); + janet_def_addflags(def); c.result.funcdef = def; } else { c.result.error_mapping = c.current_mapping; diff --git a/src/core/specials.c b/src/core/specials.c index 56b3ae17..d2940dcf 100644 --- a/src/core/specials.c +++ b/src/core/specials.c @@ -649,6 +649,7 @@ static JanetSlot janetc_while(JanetFopts opts, int32_t argn, const Janet *argv) /* Compile function */ JanetFuncDef *def = janetc_pop_funcdef(c); def->name = janet_cstring("_while"); + janet_def_addflags(def); int32_t defindex = janetc_addfuncdef(c, def); /* And then load the closure and call it. */ int32_t cloreg = janetc_regalloc_temp(&c->scope->ra, JANETC_REGTEMP_0); @@ -823,6 +824,7 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) { if (structarg) def->flags |= JANET_FUNCDEF_FLAG_STRUCTARG; if (selfref) def->name = janet_unwrap_symbol(head); + janet_def_addflags(def); defindex = janetc_addfuncdef(c, def); /* Ensure enough slots for vararg function. */