From f3d6904052118c628f0293602808729e41b2f158 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 9 Feb 2024 22:01:05 -0500 Subject: [PATCH] less jl_get_global reflection (#53250) --- base/filesystem.jl | 8 +- src/jl_exported_funcs.inc | 5 - src/jl_uv.c | 19 ---- src/jlapi.c | 49 --------- src/jsvm-emscripten/asyncify_setup.js | 144 -------------------------- src/jsvm-emscripten/task.js | 15 --- src/julia.h | 7 -- src/julia_threads.h | 19 +--- src/rtutils.c | 16 --- src/stackwalk.c | 2 - src/staticdata_utils.c | 26 +++++ src/task.c | 62 ++--------- 12 files changed, 40 insertions(+), 332 deletions(-) delete mode 100644 src/jsvm-emscripten/asyncify_setup.js delete mode 100644 src/jsvm-emscripten/task.js diff --git a/base/filesystem.jl b/base/filesystem.jl index d9760ec08a8a9..bb804392c49af 100644 --- a/base/filesystem.jl +++ b/base/filesystem.jl @@ -195,9 +195,13 @@ end function read(f::File, ::Type{UInt8}) check_open(f) - ret = ccall(:jl_fs_read_byte, Int32, (OS_HANDLE,), f.handle) + p = Ref{UInt8}() + ret = ccall(:jl_fs_read, Int32, (OS_HANDLE, Ptr{Cvoid}, Csize_t), + f.handle, p, 1) uv_error("read", ret) - return ret % UInt8 + @assert ret <= sizeof(p) == 1 + ret < 1 && throw(EOFError()) + return p[] % UInt8 end function read(f::File, ::Type{Char}) diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index 138bde4a0830a..a72058f10f42d 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -112,7 +112,6 @@ XX(jl_enter_handler) \ XX(jl_enter_threaded_region) \ XX(jl_environ) \ - XX(jl_eof_error) \ XX(jl_eqtable_get) \ XX(jl_eqtable_pop) \ XX(jl_eqtable_put) \ @@ -239,8 +238,6 @@ XX(jl_method_lookup_by_tt) \ XX(jl_method_lookup) \ XX(jl_gf_invoke_lookup_worlds) \ - XX(jl_git_branch) \ - XX(jl_git_commit) \ XX(jl_global_event_loop) \ XX(jl_has_empty_intersection) \ XX(jl_has_free_typevars) \ @@ -436,7 +433,6 @@ XX(jl_stderr_obj) \ XX(jl_stderr_stream) \ XX(jl_stdin_stream) \ - XX(jl_stdout_obj) \ XX(jl_stdout_stream) \ XX(jl_stored_inline) \ XX(jl_string_ptr) \ @@ -516,7 +512,6 @@ XX(jl_vprintf) \ XX(jl_wakeup_thread) \ XX(jl_write_compiler_output) \ - XX(jl_yield) \ #define JL_RUNTIME_EXPORTED_FUNCS_WIN(XX) \ XX(jl_setjmp) \ diff --git a/src/jl_uv.c b/src/jl_uv.c index dca08f5ddd91d..582484f78e181 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -662,25 +662,6 @@ JL_DLLEXPORT int jl_fs_read(uv_os_fd_t handle, char *data, size_t len) return ret; } -JL_DLLEXPORT int jl_fs_read_byte(uv_os_fd_t handle) -{ - uv_fs_t req; - unsigned char c; - uv_buf_t buf[1]; - buf[0].base = (char*)&c; - buf[0].len = 1; - int ret = uv_fs_read(unused_uv_loop_arg, &req, handle, buf, 1, -1, NULL); - uv_fs_req_cleanup(&req); - switch (ret) { - case -1: return ret; - case 0: jl_eof_error(); - case 1: return (int)c; - default: - assert(0 && "jl_fs_read_byte: Invalid return value from uv_fs_read"); - return -1; - } -} - JL_DLLEXPORT int jl_fs_close(uv_os_fd_t handle) { uv_fs_t req; diff --git a/src/jlapi.c b/src/jlapi.c index bde8b4f9f1245..276a792b2cd66 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -437,20 +437,6 @@ JL_DLLEXPORT jl_value_t *jl_call3(jl_function_t *f, jl_value_t *a, return v; } -/** - * @brief Yield to the Julia scheduler. - * - * Yields control to the Julia scheduler, allowing other Julia tasks to run. - */ -JL_DLLEXPORT void jl_yield(void) -{ - static jl_function_t *yieldfunc = NULL; - if (yieldfunc == NULL) - yieldfunc = (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("yield")); - if (yieldfunc != NULL) - jl_call0(yieldfunc); -} - /** * @brief Get a field from a Julia object. * @@ -619,41 +605,6 @@ JL_DLLEXPORT const char *jl_ver_string(void) return JULIA_VERSION_STRING; } -// return char* from String field in Base.GIT_VERSION_INFO -static const char *git_info_string(const char *fld) -{ - static jl_value_t *GIT_VERSION_INFO = NULL; - if (!GIT_VERSION_INFO) - GIT_VERSION_INFO = jl_get_global(jl_base_module, jl_symbol("GIT_VERSION_INFO")); - jl_value_t *f = jl_get_field(GIT_VERSION_INFO, fld); - assert(jl_is_string(f)); - return jl_string_data(f); -} - -/** - * @brief Get the name of the Git branch for the Julia build. - * - * @return A C string containing the name of the Git branch. - */ -JL_DLLEXPORT const char *jl_git_branch(void) -{ - static const char *branch = NULL; - if (!branch) branch = git_info_string("branch"); - return branch; -} - -/** - * @brief Get the Git commit hash for the Julia build. - * - * @return A C string containing the Git commit hash. - */ -JL_DLLEXPORT const char *jl_git_commit(void) -{ - static const char *commit = NULL; - if (!commit) commit = git_info_string("commit"); - return commit; -} - /** * @brief Convert a Julia value to a tagged value. * diff --git a/src/jsvm-emscripten/asyncify_setup.js b/src/jsvm-emscripten/asyncify_setup.js deleted file mode 100644 index 6783206602fd0..0000000000000 --- a/src/jsvm-emscripten/asyncify_setup.js +++ /dev/null @@ -1,144 +0,0 @@ -Module.preRun.push(function() { - if (typeof Asyncify !== "undefined") { - Asyncify.instrumentWasmExports = function (exports) { return exports; }; - Asyncify.handleSleep = function (startAsync) { - if (ABORT) return; - Module['noExitRuntime'] = true; - if (Asyncify.state === Asyncify.State.Normal) { - // Prepare to sleep. Call startAsync, and see what happens: - // if the code decided to call our callback synchronously, - // then no async operation was in fact begun, and we don't - // need to do anything. - var reachedCallback = false; - var reachedAfterCallback = false; - var task = get_current_task(); - startAsync(function(returnValue) { - assert(!returnValue || typeof returnValue === 'number'); // old emterpretify API supported other stuff - if (ABORT) return; - Asyncify.returnValue = returnValue || 0; - reachedCallback = true; - if (!reachedAfterCallback) { - // We are happening synchronously, so no need for async. - return; - } - schedule_and_wait(task); - }); - reachedAfterCallback = true; - if (!reachedCallback) { - Module['_jl_task_wait'](); - } - } else if (Asyncify.state === Asyncify.State.Rewinding) { - // Stop a resume. - finish_schedule_task(); - } else { - abort('invalid state: ' + Asyncify.state); - } - return Asyncify.returnValue; - }; - } -}); - -function get_current_task() { - return Module['_jl_get_current_task'](); -} - -function get_root_task() { - return Module['_jl_get_root_task'](); -} - -function task_ctx_ptr(task) { - return Module["_task_ctx_ptr"](task); -} - -function ctx_save(ctx) { - var stackPtr = stackSave(); - - // Save the bottom of the C stack in the task context. It simultaneously - // serves as the top of the asyncify stack. - HEAP32[ctx + 4 >> 2] = stackPtr; - - Asyncify.state = Asyncify.State.Unwinding; - Module['_asyncify_start_unwind'](ctx); - if (Browser.mainLoop.func) { - Browser.mainLoop.pause(); - } -} - -function do_start_task(old_stack) -{ - try { - // start_task is always the entry point for any task - Module['_start_task'](); - } catch(e) { - stackRestore(old_stack) - if (e !== e+0 && e !== 'killed') throw e; - maybe_schedule_next(); - return; - } - // Either unwind or normal exit. In either case, we're back at the main task - if (Asyncify.state === Asyncify.State.Unwinding) { - // We just finished unwinding for a sleep. - Asyncify.state = Asyncify.State.Normal; - Module['_asyncify_stop_unwind'](); - } - stackRestore(old_stack); - maybe_schedule_next(); -} - -function schedule_and_wait(task) { - Module['_jl_schedule_task'](task); - Module['_jl_task_wait'](); -} - -function finish_schedule_task() { - Asyncify.state = Asyncify.State.Normal; - Module['_asyncify_stop_rewind'](); -} - -next_ctx = 0; -next_need_start = true; -function set_next_ctx(ctx, needs_start) { - next_ctx = ctx; - next_need_start = needs_start; -} - -function root_ctx() { - return task_ctx_ptr(get_root_task()) -} - -function ctx_switch(lastt_ctx) { - if (lastt_ctx == root_ctx()) { - // If we're in the root context, switch to - // the new ctx now, else we'll get there after - // unwinding. - return schedule_next() - } else if (lastt_ctx == 0) { - throw 'killed'; - } else { - return ctx_save(lastt_ctx); - } -} - -function schedule_next() -{ - old_stack = stackSave(); - var next_task_stack = HEAP32[next_ctx + 4 >> 2]; - if (!next_need_start) { - Asyncify.state = Asyncify.State.Rewinding; - Module['_asyncify_start_rewind'](next_ctx); - if (Browser.mainLoop.func) { - Browser.mainLoop.resume(); - } - } - next_ctx = -1; - stackRestore(next_task_stack); - do_start_task(old_stack) -} - -function maybe_schedule_next() { - assert(next_ctx != -1); - if (next_ctx == root_ctx() || next_ctx == 0) { - return; - } - schedule_next() -} diff --git a/src/jsvm-emscripten/task.js b/src/jsvm-emscripten/task.js deleted file mode 100644 index ba695a5a40052..0000000000000 --- a/src/jsvm-emscripten/task.js +++ /dev/null @@ -1,15 +0,0 @@ -mergeInto(LibraryManager.library, { - jl_set_fiber: function(ctx) { - set_next_ctx(ctx, false); - return ctx_switch(0) - }, - jl_swap_fiber: function(lastt_ctx, ctx) { - set_next_ctx(ctx, false); - return ctx_switch(lastt_ctx) - }, - jl_start_fiber: function(lastt_ctx, ctx) { - set_next_ctx(ctx, true); - return ctx_switch(lastt_ctx) - } -}); - diff --git a/src/julia.h b/src/julia.h index 7d143a3daa3fc..ee20641d17805 100644 --- a/src/julia.h +++ b/src/julia.h @@ -2003,7 +2003,6 @@ JL_DLLEXPORT void JL_NORETURN jl_bounds_error_tuple_int(jl_value_t **v, JL_DLLEXPORT void JL_NORETURN jl_bounds_error_unboxed_int(void *v, jl_value_t *vt, size_t i); JL_DLLEXPORT void JL_NORETURN jl_bounds_error_ints(jl_value_t *v JL_MAYBE_UNROOTED, size_t *idxs, size_t nidxs); -JL_DLLEXPORT void JL_NORETURN jl_eof_error(void); // Return the exception currently being handled, or `jl_nothing`. // @@ -2173,9 +2172,6 @@ JL_DLLEXPORT jl_value_t *jl_call2(jl_function_t *f JL_MAYBE_UNROOTED, jl_value_t JL_DLLEXPORT jl_value_t *jl_call3(jl_function_t *f JL_MAYBE_UNROOTED, jl_value_t *a JL_MAYBE_UNROOTED, jl_value_t *b JL_MAYBE_UNROOTED, jl_value_t *c JL_MAYBE_UNROOTED); -// interfacing with Task runtime -JL_DLLEXPORT void jl_yield(void); - // async signal handling ------------------------------------------------------ JL_DLLEXPORT void jl_install_sigint_handler(void); @@ -2409,7 +2405,6 @@ JL_DLLEXPORT int jl_termios_size(void); // showing and std streams JL_DLLEXPORT void jl_flush_cstdio(void) JL_NOTSAFEPOINT; -JL_DLLEXPORT jl_value_t *jl_stdout_obj(void) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_value_t *jl_stderr_obj(void) JL_NOTSAFEPOINT; JL_DLLEXPORT size_t jl_static_show(JL_STREAM *out, jl_value_t *v) JL_NOTSAFEPOINT; JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) JL_NOTSAFEPOINT; @@ -2510,8 +2505,6 @@ JL_DLLEXPORT extern int jl_ver_minor(void); JL_DLLEXPORT extern int jl_ver_patch(void); JL_DLLEXPORT extern int jl_ver_is_release(void); JL_DLLEXPORT extern const char *jl_ver_string(void); -JL_DLLEXPORT const char *jl_git_branch(void); -JL_DLLEXPORT const char *jl_git_commit(void); // nullable struct representations typedef struct { diff --git a/src/julia_threads.h b/src/julia_threads.h index 292c11f61d60d..1c64a722850f2 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -30,7 +30,6 @@ JL_DLLEXPORT int8_t jl_threadpoolid(int16_t tid) JL_NOTSAFEPOINT; // JL_HAVE_ASM -- mostly setjmp // JL_HAVE_ASM && JL_HAVE_UNW_CONTEXT -- libunwind-based // JL_HAVE_UNW_CONTEXT -- libunwind-based -// JL_HAVE_ASYNCIFY -- task switching based on the binary asyncify transform // JL_HAVE_UCONTEXT -- posix standard API, requires syscall for resume // JL_HAVE_SIGALTSTACK -- requires several syscall for start, setjmp for resume @@ -45,8 +44,7 @@ typedef struct { #if !defined(JL_HAVE_UCONTEXT) && \ !defined(JL_HAVE_ASM) && \ !defined(JL_HAVE_UNW_CONTEXT) && \ - !defined(JL_HAVE_SIGALTSTACK) && \ - !defined(JL_HAVE_ASYNCIFY) + !defined(JL_HAVE_SIGALTSTACK) #if (defined(_CPU_X86_64_) || defined(_CPU_X86_) || defined(_CPU_AARCH64_) || \ defined(_CPU_ARM_) || defined(_CPU_PPC64_)) #define JL_HAVE_ASM @@ -57,8 +55,6 @@ typedef struct { //#define JL_HAVE_UNW_CONTEXT //#elif defined(_OS_LINUX_) //#define JL_HAVE_UNW_CONTEXT -#elif defined(_OS_EMSCRIPTEN_) -#define JL_HAVE_ASYNCIFY #elif !defined(JL_HAVE_ASM) #define JL_HAVE_UNW_CONTEXT // optimistically? #endif @@ -67,19 +63,6 @@ typedef struct { #if (!defined(JL_HAVE_UNW_CONTEXT) && defined(JL_HAVE_ASM)) || defined(JL_HAVE_SIGALTSTACK) typedef jl_stack_context_t _jl_ucontext_t; #endif -#if defined(JL_HAVE_ASYNCIFY) -#if defined(_COMPILER_TSAN_ENABLED_) -#error TSAN not currently supported with asyncify -#endif -typedef struct { - // This is the extent of the asyncify stack, but because the top of the - // asyncify stack (stacktop) is also the bottom of the C stack, we can - // reuse stacktop for both. N.B.: This matches the layout of the - // __asyncify_data struct. - void *stackbottom; - void *stacktop; -} _jl_ucontext_t; -#endif #pragma GCC visibility push(default) #if defined(JL_HAVE_UNW_CONTEXT) #define UNW_LOCAL_ONLY diff --git a/src/rtutils.c b/src/rtutils.c index a4cfa28039805..1ab881e613564 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -219,14 +219,6 @@ JL_DLLEXPORT void JL_NORETURN jl_bounds_error_ints(jl_value_t *v JL_MAYBE_UNROOT jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t)); } -JL_DLLEXPORT void JL_NORETURN jl_eof_error(void) -{ - jl_datatype_t *eof_error = - (jl_datatype_t*)jl_get_global(jl_base_module, jl_symbol("EOFError")); - assert(eof_error != NULL); - jl_throw(jl_new_struct(eof_error)); -} - JL_DLLEXPORT void jl_typeassert(jl_value_t *x, jl_value_t *t) { if (!jl_isa(x,t)) @@ -546,14 +538,6 @@ JL_DLLEXPORT void jl_flush_cstdio(void) JL_NOTSAFEPOINT fflush(stderr); } -JL_DLLEXPORT jl_value_t *jl_stdout_obj(void) JL_NOTSAFEPOINT -{ - if (jl_base_module == NULL) - return NULL; - jl_binding_t *stdout_obj = jl_get_module_binding(jl_base_module, jl_symbol("stdout"), 0); - return stdout_obj ? jl_atomic_load_relaxed(&stdout_obj->value) : NULL; -} - JL_DLLEXPORT jl_value_t *jl_stderr_obj(void) JL_NOTSAFEPOINT { if (jl_base_module == NULL) diff --git a/src/stackwalk.c b/src/stackwalk.c index 6efb177927637..37f239609504e 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -1087,8 +1087,6 @@ static void jl_rec_backtrace(jl_task_t *t) JL_NOTSAFEPOINT #pragma message("jl_rec_backtrace not defined for ASM/SETJMP on unknown system") (void)c; #endif -#elif defined(JL_HAVE_ASYNCIFY) - #pragma message("jl_rec_backtrace not defined for ASYNCIFY") #elif defined(JL_HAVE_SIGALTSTACK) #pragma message("jl_rec_backtrace not defined for SIGALTSTACK") #else diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index 199724e54ae00..aa39c53844a56 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -634,6 +634,32 @@ JL_DLLEXPORT uint8_t jl_match_cache_flags(uint8_t flags) return flags >= current_flags; } +// return char* from String field in Base.GIT_VERSION_INFO +static const char *git_info_string(const char *fld) +{ + static jl_value_t *GIT_VERSION_INFO = NULL; + if (!GIT_VERSION_INFO) + GIT_VERSION_INFO = jl_get_global(jl_base_module, jl_symbol("GIT_VERSION_INFO")); + jl_value_t *f = jl_get_field(GIT_VERSION_INFO, fld); + assert(jl_is_string(f)); + return jl_string_data(f); +} + +static const char *jl_git_branch(void) +{ + static const char *branch = NULL; + if (!branch) branch = git_info_string("branch"); + return branch; +} + +static const char *jl_git_commit(void) +{ + static const char *commit = NULL; + if (!commit) commit = git_info_string("commit"); + return commit; +} + + // "magic" string and version header of .ji file static const int JI_FORMAT_VERSION = 12; static const char JI_MAGIC[] = "\373jli\r\n\032\n"; // based on PNG signature diff --git a/src/task.c b/src/task.c index 8905b49e87f8e..4bf12250b7d2c 100644 --- a/src/task.c +++ b/src/task.c @@ -134,18 +134,11 @@ static inline void sanitizer_finish_switch_fiber(jl_task_t *last, jl_task_t *cur #define ROOT_TASK_STACK_ADJUSTMENT 3000000 #endif -#ifdef JL_HAVE_ASYNCIFY -// Switching logic is implemented in JavaScript -#define STATIC_OR_JS JL_DLLEXPORT -#else -#define STATIC_OR_JS static -#endif - static char *jl_alloc_fiber(_jl_ucontext_t *t, size_t *ssize, jl_task_t *owner) JL_NOTSAFEPOINT; -STATIC_OR_JS void jl_set_fiber(jl_ucontext_t *t); -STATIC_OR_JS void jl_swap_fiber(jl_ucontext_t *lastt, jl_ucontext_t *t); -STATIC_OR_JS void jl_start_fiber_swap(jl_ucontext_t *savet, jl_ucontext_t *t); -STATIC_OR_JS void jl_start_fiber_set(jl_ucontext_t *t); +static void jl_set_fiber(jl_ucontext_t *t); +static void jl_swap_fiber(jl_ucontext_t *lastt, jl_ucontext_t *t); +static void jl_start_fiber_swap(jl_ucontext_t *savet, jl_ucontext_t *t); +static void jl_start_fiber_set(jl_ucontext_t *t); #ifdef ALWAYS_COPY_STACKS # ifndef COPY_STACKS @@ -1172,47 +1165,6 @@ JL_DLLEXPORT jl_task_t *jl_get_current_task(void) return pgcstack == NULL ? NULL : container_of(pgcstack, jl_task_t, gcstack); } - -#ifdef JL_HAVE_ASYNCIFY -JL_DLLEXPORT jl_ucontext_t *task_ctx_ptr(jl_task_t *t) -{ - return &t->ctx.ctx; -} - -JL_DLLEXPORT jl_value_t *jl_get_root_task(void) -{ - jl_task_t *ct = jl_current_task; - return (jl_value_t*)ct->ptls->root_task; -} - -JL_DLLEXPORT void jl_task_wait() -{ - static jl_function_t *wait_func = NULL; - if (!wait_func) { - wait_func = (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("wait")); - } - jl_task_t *ct = jl_current_task; - size_t last_age = ct->world_age; - ct->world_age = jl_get_world_counter(); - jl_apply(&wait_func, 1); - ct->world_age = last_age; -} - -JL_DLLEXPORT void jl_schedule_task(jl_task_t *task) -{ - static jl_function_t *sched_func = NULL; - if (!sched_func) { - sched_func = (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("schedule")); - } - jl_task_t *ct = jl_current_task; - size_t last_age = ct->world_age; - ct->world_age = jl_get_world_counter(); - jl_value_t *args[] = {(jl_value_t*)sched_func, (jl_value_t*)task}; - jl_apply(args, 2); - ct->world_age = last_age; -} -#endif - // Do one-time initializations for task system void jl_init_tasks(void) JL_GC_DISABLED { @@ -1247,10 +1199,10 @@ void jl_init_tasks(void) JL_GC_DISABLED } #if defined(_COMPILER_ASAN_ENABLED_) -STATIC_OR_JS void NOINLINE JL_NORETURN _start_task(void); +static void NOINLINE JL_NORETURN _start_task(void); #endif -STATIC_OR_JS void NOINLINE JL_NORETURN JL_NO_ASAN start_task(void) +static void NOINLINE JL_NORETURN JL_NO_ASAN start_task(void) { CFI_NORETURN #if defined(_COMPILER_ASAN_ENABLED_) @@ -1266,7 +1218,7 @@ CFI_NORETURN _start_task(); } -STATIC_OR_JS void NOINLINE JL_NORETURN _start_task(void) +static void NOINLINE JL_NORETURN _start_task(void) { CFI_NORETURN #endif