diff --git a/Makefile b/Makefile index acad4177..e4a7a819 100755 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ static: # Bootstrap: build cell from scratch using meson (only needed once) # Also installs core scripts to ~/.cell/core bootstrap: - meson setup build_bootstrap -Dbuildtype=release + meson setup build_bootstrap -Dbuildtype=debugoptimized meson compile -C build_bootstrap cp build_bootstrap/cell . cp build_bootstrap/libcell_runtime.dylib . diff --git a/add.ce b/add.ce index 61218124..1d23f00b 100644 --- a/add.ce +++ b/add.ce @@ -1,6 +1,6 @@ // cell get [alias] - Add and install a package with its dependencies -var shop = use('shop') +var shop = use('internal/shop') if (args.length < 1) { log.console("Usage: cell get [alias]") diff --git a/build.ce b/build.ce index 31b685c2..63df587e 100644 --- a/build.ce +++ b/build.ce @@ -6,7 +6,7 @@ // cell build -t Cross-compile dynamic libraries for target platform var build = use('build') -var shop = use('shop') +var shop = use('internal/shop') var pkg_tools = use('package') var fd = use('fd') diff --git a/build.cm b/build.cm index 0086eec9..1d36eb39 100644 --- a/build.cm +++ b/build.cm @@ -11,7 +11,7 @@ var crypto = use('crypto') var utf8 = use('utf8') var os = use('os') var toolchains = use('toolchains') -var shop = use('shop') +var shop = use('internal/shop') var pkg_tools = use('package') var Build = {} diff --git a/cellfs.cm b/cellfs.cm index 99b1383b..9e2fb86d 100644 --- a/cellfs.cm +++ b/cellfs.cm @@ -278,7 +278,7 @@ function mount_package(name) { return } - var shop = use('shop') + var shop = use('internal/shop') var dir = shop.get_package_dir(name) if (!dir) { @@ -475,7 +475,6 @@ cellfs.writepath = set_writepath cellfs.basedir = basedir cellfs.prefdir = prefdir cellfs.realdir = realdir -cellfs.slurp = slurp cellfs.mount('.') diff --git a/clean.ce b/clean.ce index 87cb289c..1f54693b 100644 --- a/clean.ce +++ b/clean.ce @@ -1,7 +1,7 @@ // cell clean - Remove build artifacts from global shop var fd = use('fd') -var shop = use('shop') +var shop = use('internal/shop') var build_dir = shop.get_shop_path() + '/build' diff --git a/config.ce b/config.ce index 633777ae..591da507 100644 --- a/config.ce +++ b/config.ce @@ -2,7 +2,6 @@ var toml = use('toml') var pkg = use('package') -var text = use('text') function print_help() { log.console("Usage: cell config [options]") @@ -80,7 +79,7 @@ function format_value(val) { // Add underscores to large numbers return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '_') } - return String(val) + return text(val) } // Print configuration tree recursively diff --git a/fetch.ce b/fetch.ce index e3504300..e20823cf 100644 --- a/fetch.ce +++ b/fetch.ce @@ -8,7 +8,7 @@ // cell fetch - Fetch all packages // cell fetch - Fetch a specific package -var shop = use('shop') +var shop = use('internal/shop') // Parse arguments var target_pkg = null @@ -67,7 +67,7 @@ for (var pkg of packages_to_fetch) { } var result = shop.fetch(pkg) - if (result && result.ok) { + if (result) { if (result.zip_blob) { log.console("Fetched: " + pkg) success_count++ diff --git a/install.ce b/install.ce index fa8475f9..b5400237 100644 --- a/install.ce +++ b/install.ce @@ -1,7 +1,7 @@ // cell install - Install a package to the shop // Does not modify the current project's cell.toml -var shop = use('shop') +var shop = use('internal/shop') var build = use('build') if (args.length < 1) { diff --git a/internal/array.cm b/internal/array.cm index c10a809a..d494e45d 100644 --- a/internal/array.cm +++ b/internal/array.cm @@ -5,6 +5,7 @@ var _slice = Array.prototype.slice var _push = Array.prototype.push var _sort = Array.prototype.sort var _keys = Object.keys +var _from = Array.from function array(arg, arg2, arg3, arg4) { // array(number) - create array of size with nulls @@ -91,6 +92,9 @@ function array(arg, arg2, arg3, arg4) { // array(object) - keys if (typeof arg == 'object' && arg != null && !_isArray(arg)) { + if (arg instanceof Set) { + return _from(arg) + } return _keys(arg) } diff --git a/internal/engine.cm b/internal/engine.cm index 5a6491d7..805418b0 100644 --- a/internal/engine.cm +++ b/internal/engine.cm @@ -4,8 +4,6 @@ delete globalThis.cell var ACTORDATA = _cell.hidden.actorsym var SYSYM = '__SYSTEM__' -var __cell = globalThis._cell - var hidden = _cell.hidden var os = hidden.os; @@ -29,10 +27,19 @@ function use_embed(name) { return load_internal(`js_${name}_use`) } -globalThis.meme = function(obj) { - return { +globalThis.meme = function(obj, ...mixins) { + var result = { __proto__: obj } + + array.for(mixins, mix => { + if (isa(mix, object)) { + for (var key in mix) { + result[key] = mix[key] + } + } + }) + return result } globalThis.logical = function(val1) @@ -66,6 +73,11 @@ use_cache['core/os'] = os var _Symbol = Symbol +globalThis.key = function() +{ + return _Symbol() +} + // Load a core module from the file system function use_core(path) { var cache_key = 'core/' + path @@ -392,7 +404,7 @@ os.use_cache = use_cache os.global_shop_path = shop_path os.$_ = $_ -var shop = use_core('shop') +var shop = use_core('internal/shop') var json = use_core('json') var time = use_core('time') @@ -949,10 +961,6 @@ function enet_check() // enet_check(); -var init_end = time.number() - -var load_program_start = time.number() - // Finally, run the program actor_mod.setname(_cell.args.program) @@ -1005,8 +1013,8 @@ delete globalThis.WeakSet delete globalThis.WeakRef delete globalThis.BigInt delete globalThis.Symbol -delete globalThis.Map -delete globalThis.Set +//delete globalThis.Map +//delete globalThis.Set delete globalThis.Promise delete globalThis.ArrayBuffer delete globalThis.DataView diff --git a/internal/os.c b/internal/os.c index c417a34b..d26a3026 100644 --- a/internal/os.c +++ b/internal/os.c @@ -326,7 +326,7 @@ static JSValue js_os_dylib_open(JSContext *js, JSValue self, int argc, JSValue * #ifdef _WIN32 handle = LoadLibraryA(path); #else - handle = dlopen(path, RTLD_NOW | RTLD_LOCAL); + handle = dlopen(path, RTLD_NOW | RTLD_GLOBAL); #endif JS_FreeCString(js, path); diff --git a/shop.cm b/internal/shop.cm similarity index 94% rename from shop.cm rename to internal/shop.cm index f8bc6c56..b24bcac6 100644 --- a/shop.cm +++ b/internal/shop.cm @@ -99,6 +99,11 @@ function get_import_package(name) { return null } +function is_internal_path(path) +{ + return path && path.startsWith('internal/') +} + function split_explicit_package_import(path) { if (!path) return null @@ -429,6 +434,10 @@ function resolve_mod_fn(path, pkg) { function resolve_locator(path, ctx) { var explicit = split_explicit_package_import(path) + if (explicit) { + if (is_internal_path(explicit.path) && ctx && explicit.package != ctx) + explicit = null + } if (explicit) { var explicit_path = get_packages_dir() + '/' + safe_package_path(explicit.package) + '/' + explicit.path if (fd.is_file(explicit_path)) { @@ -456,6 +465,9 @@ function resolve_locator(path, ctx) return {path: ctx_path, scope: SCOPE_LOCAL, symbol: fn} } + if (is_internal_path(path)) + return null + // check for aliased dependency var alias = pkg_tools.split_alias(ctx, path) if (alias) { @@ -510,16 +522,20 @@ function get_lib_path(pkg) { // Resolve a C symbol by searching: // 1. If package_context is null, only check core internal symbols // 2. Otherwise: own package (internal then dylib) -> other packages (internal then dylib) -> core (internal only) -// Core is never loaded as a dynamic library via dlopen -function resolve_c_symbol(path, package_context) -{ - var explicit = split_explicit_package_import(path) - if (explicit) { - var sym = make_c_symbol(explicit.package, explicit.path) - if (os.internal_exists(sym)) { - return { - symbol: function() { return os.load_internal(sym) }, - scope: SCOPE_PACKAGE, + // Core is never loaded as a dynamic library via dlopen + function resolve_c_symbol(path, package_context) + { + var explicit = split_explicit_package_import(path) + if (explicit) { + if (is_internal_path(explicit.path) && package_context && explicit.package != package_context) + explicit = null + } + if (explicit) { + var sym = make_c_symbol(explicit.package, explicit.path) + if (os.internal_exists(sym)) { + return { + symbol: function() { return os.load_internal(sym) }, + scope: SCOPE_PACKAGE, package: explicit.package, path: sym } @@ -575,6 +591,9 @@ function resolve_c_symbol(path, package_context) } } + if (is_internal_path(path)) + return null + // 2. Check aliased package imports (e.g. 'prosperon/sprite') var pkg_alias = get_import_package(path) if (pkg_alias) { @@ -622,7 +641,15 @@ function resolve_c_symbol(path, package_context) return null } +// Cache for resolved module info +var module_info_cache = {} + function resolve_module_info(path, package_context) { + var lookup_key = package_context ? package_context + ':' + path : ':' + path + + if (module_info_cache[lookup_key]) + return module_info_cache[lookup_key] + var c_resolve = resolve_c_symbol(path, package_context) || {scope:999} var mod_resolve = resolve_locator(path + '.cm', package_context) || {scope:999} var min_scope = number.min(c_resolve.scope, mod_resolve.scope) @@ -630,58 +657,49 @@ function resolve_module_info(path, package_context) { if (min_scope == 999) return null - // Cache key is based on the realpath of the resolved file - // This ensures linked packages resolve to the same cache entry - // whether accessed via symlink or directly var cache_key if (mod_resolve.scope == SCOPE_CORE) { cache_key = 'core/' + path } else if (mod_resolve.scope < 900 && mod_resolve.path) { - // Use realpath to resolve symlinks and get the actual file location var real_path = fd.realpath(mod_resolve.path) if (real_path) { - // Derive cache key from the real path's package info var real_info = Shop.file_info(real_path) - if (real_info.package && real_info.name) { + if (real_info.package && real_info.name) cache_key = real_info.package + '/' + real_info.name - } else { - // Fallback to the realpath itself + else cache_key = real_path - } } } - // Fallback for C-only modules or if realpath failed if (!cache_key) { - if (min_scope == SCOPE_CORE) { + if (min_scope == SCOPE_CORE) cache_key = 'core/' + path - } else if (min_scope == SCOPE_LOCAL && package_context) { + else if (min_scope == SCOPE_LOCAL && package_context) cache_key = package_context + '/' + path - } else if (min_scope == SCOPE_PACKAGE) { - // For package imports like 'prosperon/sprite', resolve to canonical path + else if (min_scope == SCOPE_PACKAGE) { var pkg_alias = get_import_package(path) if (pkg_alias) { var canon_pkg = get_canonical_package(pkg_alias, package_context) if (canon_pkg) { var mod_name = get_import_name(path) cache_key = canon_pkg + '/' + mod_name - } else { + } else cache_key = path - } - } else { + } else cache_key = path - } - } else { + } else cache_key = path - } } - return { + var info = { cache_key: cache_key, c_resolve: c_resolve, mod_resolve: mod_resolve, min_scope: min_scope } + + module_info_cache[lookup_key] = info + return info } function get_module_cache_key(path, package_context) { @@ -689,7 +707,7 @@ function get_module_cache_key(path, package_context) { return info ? info.cache_key : null } -Shop.is_loaded = function(path, package_context) { +Shop.is_loaded = function is_loaded(path, package_context) { var cache_key = get_module_cache_key(path, package_context) return use_cache[cache_key] != null } @@ -732,7 +750,7 @@ function execute_module(info) } if (!used) throw new Error(`Module ${info} returned null`) - stone(used) +// stone(used) return used } @@ -745,7 +763,7 @@ function get_module(path, package_context) { return execute_module(info) } -Shop.use = function(path, package_context) { +Shop.use = function use(path, package_context) { var info = resolve_module_info(path, package_context) if (!info) throw new Error(`Module ${path} could not be found in ${package_context}`) @@ -1034,6 +1052,11 @@ Shop.file_reload = function(file) Shop.module_reload = function(path, package) { if (!Shop.is_loaded(path,package)) return + + // Clear the module info cache for this path + var lookup_key = package ? package + ':' + path : ':' + path + module_info_cache[lookup_key] = null + var info = resolve_module_info(path, package) if (!info) return @@ -1044,10 +1067,9 @@ Shop.module_reload = function(path, package) { for (var i in newmod) old[i] = newmod[i] - for (var i in old) { + for (var i in old) if (!(i in newmod)) old[i] = null - } } function get_package_scripts(package) diff --git a/link.ce b/link.ce index baa288fa..ab8ed3d9 100644 --- a/link.ce +++ b/link.ce @@ -13,7 +13,7 @@ // cell link gitea.pockle.world/john/prosperon github.com/prosperon (Links to another remote) var link = use('link') -var shop = use('shop') +var shop = use('internal/shop') var fd = use('fd') var toml = use('toml') diff --git a/list.ce b/list.ce index dfcbbbda..a12e038b 100644 --- a/list.ce +++ b/list.ce @@ -3,7 +3,7 @@ // cell list all -> list all packages (including those that are there due to installed packages) // cell list package -> list the packages for the package -var shop = use('shop') +var shop = use('internal/shop') var pkg = use('package') var mode = 'local' diff --git a/ls.ce b/ls.ce index 8edff609..c8731b56 100644 --- a/ls.ce +++ b/ls.ce @@ -2,7 +2,7 @@ // if args[0] is a package alias, list that one // otherwise, list the local one -var shop = use('shop') +var shop = use('internal/shop') var package = use('package') var ctx = null diff --git a/pack.ce b/pack.ce index 24e631b0..17e616e2 100644 --- a/pack.ce +++ b/pack.ce @@ -6,7 +6,7 @@ // cell pack -t Cross-compile for target platform var build = use('build') -var shop = use('shop') +var shop = use('internal/shop') var pkg_tools = use('package') var target = null diff --git a/remove.ce b/remove.ce index e3205cf6..0e7d96d0 100644 --- a/remove.ce +++ b/remove.ce @@ -1,6 +1,6 @@ // cell remove - Remove a package from dependencies or shop -var shop = use('shop') +var shop = use('internal/shop') if (args.length < 1) { log.console("Usage: cell remove ") diff --git a/source/cell.c b/source/cell.c index 994addc5..261f9c1b 100644 --- a/source/cell.c +++ b/source/cell.c @@ -275,6 +275,11 @@ double cell_random() { return (double)buf / 9007199254740992.0; } +void cell_trace_sethook(cell_hook) +{ + +} + int uncaught_exception(JSContext *js, JSValue v) { cell_rt *rt = JS_GetContextOpaque(js); diff --git a/source/cell.h b/source/cell.h index e48328ac..c40a9081 100644 --- a/source/cell.h +++ b/source/cell.h @@ -28,6 +28,11 @@ JSValue number2js(JSContext *js, double g); JSValue wota2value(JSContext *js, void *v); void *value2wota(JSContext *js, JSValue v, JSValue replacer, size_t *bytes); +#define CELL_HOOK_ENTER 1 +#define CELL_HOOK_EXIT 2 +typedef void (*cell_hook)(const char *name, int type); +void cell_trace_sethook(cell_hook); + // Macros to help with creating scripts #define MIST_CFUNC_DEF(name, length, func1, props) { name, props, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } diff --git a/source/cell_internal.h b/source/cell_internal.h index 52c72e05..d49e9ac8 100644 --- a/source/cell_internal.h +++ b/source/cell_internal.h @@ -56,6 +56,7 @@ typedef struct cell_rt { JSAtom actor_sym; const char *name; // human friendly name + cell_hook trace_hook; } cell_rt; cell_rt *create_actor(void *wota); diff --git a/source/quickjs.c b/source/quickjs.c index ce87fff1..837ffd77 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -340,11 +340,9 @@ struct JSContext { const char *filename, int flags, int scope_idx); void *user_opaque; - js_hook fn_start_hook; - js_hook fn_end_hook; - js_hook fn_cycle_hook; - js_hook fn_gc_hook; - int hook_disabled; + js_hook trace_hook; + int trace_type; + void *trace_data; }; typedef union JSFloat64Union { @@ -1569,9 +1567,11 @@ JSContext *JS_NewContextRaw(JSRuntime *rt) int i; ctx = js_mallocz_rt(rt, sizeof(JSContext)); + if (!ctx) return NULL; ctx->header.ref_count = 1; + ctx->trace_hook = NULL; add_gc_object(rt, &ctx->header, JS_GC_OBJ_TYPE_JS_CONTEXT); ctx->class_proto = js_malloc_rt(rt, sizeof(ctx->class_proto[0]) * @@ -1586,7 +1586,6 @@ JSContext *JS_NewContextRaw(JSRuntime *rt) ctx->class_proto[i] = JS_NULL; ctx->array_ctor = JS_NULL; ctx->regexp_ctor = JS_NULL; - JS_AddIntrinsicBasicObjects(ctx); rt->js = ctx; return ctx; @@ -5943,6 +5942,38 @@ static int find_line_num(JSContext *ctx, JSFunctionBytecode *b, return 0; } +/* return a string property without executing arbitrary JS code (used + when dumping the stack trace or in debug print). */ +static const char *get_prop_string(JSContext *ctx, JSValueConst obj, JSAtom prop) +{ + JSObject *p; + JSProperty *pr; + JSShapeProperty *prs; + JSValueConst val; + + if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) + return NULL; + p = JS_VALUE_GET_OBJ(obj); + prs = find_own_property(&pr, p, prop); + if (!prs) { + /* we look at one level in the prototype to handle the 'name' + field of the Error objects */ + p = p->shape->proto; + if (!p) + return NULL; + prs = find_own_property(&pr, p, prop); + if (!prs) + return NULL; + } + + if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL) + return NULL; + val = pr->u.value; + if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING) + return NULL; + return JS_ToCString(ctx, val); +} + /* in order to avoid executing arbitrary code during the stack trace generation, we only look at simple 'name' properties containing a string. */ @@ -5962,7 +5993,9 @@ static const char *get_func_name(JSContext *ctx, JSValueConst func) val = pr->u.value; if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING) return NULL; - return JS_ToCString(ctx, val); + +// char *buf = js_malloc(ctx->rt, 128); +// return JS_AtomGetStr(ctx, buf, 128, prs->atom); } #define JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL (1 << 0) @@ -12222,10 +12255,11 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, func = p->u.cfunc.c_function; - if (unlikely(ctx->fn_start_hook) && !ctx->hook_disabled) { - ctx->hook_disabled = 1; - ctx->fn_start_hook(ctx,func_obj); - ctx->hook_disabled = 0; + if (unlikely(ctx->trace_hook) && (ctx->trace_type & JS_HOOK_CALL)) { + js_debug dbg = {0}; + js_debug_info(ctx, func_obj, &dbg); + ctx->trace_hook(ctx, JS_HOOK_CALL, &dbg, ctx->trace_data); + free_js_debug_info(ctx, &dbg); } switch(cproto) { @@ -12312,13 +12346,14 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, } rt->current_stack_frame = sf->prev_frame; - - if (unlikely(ctx->fn_end_hook) && !ctx->hook_disabled) { - ctx->hook_disabled = 1; - ctx->fn_end_hook(ctx, func_obj); - ctx->hook_disabled = 0; + + if (unlikely(ctx->trace_hook) && (ctx->trace_type & JS_HOOK_RET)) { + js_debug dbg = {0}; + js_debug_info(ctx, func_obj, &dbg); + ctx->trace_hook(ctx, JS_HOOK_RET, &dbg, ctx->trace_data); + free_js_debug_info(ctx, &dbg); } - + return ret_val; } @@ -12418,10 +12453,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } b = p->u.func.function_bytecode; - if (unlikely(caller_ctx->fn_start_hook) && !caller_ctx->hook_disabled) { - caller_ctx->hook_disabled = 1; - caller_ctx->fn_start_hook(caller_ctx,func_obj); - caller_ctx->hook_disabled = 0; + if (unlikely(caller_ctx->trace_hook) && (caller_ctx->trace_type & JS_HOOK_CALL)) { + js_debug dbg = {0}; + js_debug_info(caller_ctx, func_obj, &dbg); + caller_ctx->trace_hook(caller_ctx, JS_HOOK_CALL, &dbg, caller_ctx->trace_data); + free_js_debug_info(caller_ctx, &dbg); } if (unlikely(argc < b->arg_count || (flags & JS_CALL_FLAG_COPY_ARGV))) { @@ -14584,11 +14620,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } rt->current_stack_frame = sf->prev_frame; - if (unlikely(caller_ctx->fn_end_hook) && !caller_ctx->hook_disabled) { - caller_ctx->hook_disabled = 1; - caller_ctx->fn_end_hook(caller_ctx,func_obj); - caller_ctx->hook_disabled = 0; - } + if (unlikely(caller_ctx->trace_hook) && (caller_ctx->trace_type & JS_HOOK_RET)) { + js_debug dbg = {0}; + js_debug_info(caller_ctx, func_obj, &dbg); + caller_ctx->trace_hook(caller_ctx, JS_HOOK_RET, &dbg, caller_ctx->trace_data); + free_js_debug_info(caller_ctx, &dbg); + } return ret_val; } @@ -36834,7 +36871,7 @@ void js_debug_info(JSContext *js, JSValue fn, js_debug *dbg) if (!JS_IsObject(fn)) return; JSObject *p = JS_VALUE_GET_OBJ(fn); - const char *fn_name = get_func_name(js,fn); + const char *fn_name = get_prop_string(js, fn, JS_ATOM_name); if (!fn_name) dbg->name = js_strdup(js, ""); @@ -36867,7 +36904,8 @@ void js_debug_info(JSContext *js, JSValue fn, js_debug *dbg) dbg->closure_n = b->closure_var_count; dbg->param_n = b->arg_count; dbg->vararg = 1; -// dbg->line = b->debug.line_num; + int pcol_num; + dbg->line = find_line_num(js, b, -1, &pcol_num); dbg->source = b->debug.source; dbg->srclen = b->debug.source_len; break; @@ -36890,16 +36928,11 @@ void free_js_debug_info(JSContext *js, js_debug *dbg) js_free(js, dbg->name); } -void js_debug_sethook(JSContext *ctx, js_hook hook, int type) +void js_debug_sethook(JSContext *ctx, js_hook hook, int type, void *user) { - if (type == JS_HOOK_CALL) - ctx->fn_start_hook = hook; - else if (type == JS_HOOK_RET) - ctx->fn_end_hook = hook; - else if (type == JS_HOOK_CYCLE) - ctx->fn_cycle_hook = hook; - else if (type == JS_HOOK_GC) - ctx->fn_gc_hook = hook; + ctx->trace_hook = hook; + ctx->trace_type = type; + ctx->trace_data = user; } uint32_t js_debugger_stack_depth(JSContext *ctx) { @@ -37502,4 +37535,4 @@ void *js_debugger_val_address(JSContext *ctx, JSValue val) { JSContext *JS_GetContext(JSRuntime *rt) { return rt->js; -} \ No newline at end of file +} diff --git a/source/quickjs.h b/source/quickjs.h index 72631aba..b959f6fb 100644 --- a/source/quickjs.h +++ b/source/quickjs.h @@ -961,7 +961,6 @@ void JS_PrintValueRT(JSRuntime *rt, JSPrintValueWrite *write_func, void *write_o void JS_PrintValue(JSContext *ctx, JSPrintValueWrite *write_func, void *write_opaque, JSValueConst val, const JSPrintValueOptions *options); - typedef struct js_debug { const char *name; // nameof function const char *what; @@ -979,12 +978,12 @@ typedef struct js_debug { void js_debug_info(JSContext *js, JSValue fn, js_debug *dbg); void free_js_debug_info(JSContext *js, js_debug *dbg); -typedef void (*js_hook)(JSContext*, JSValue); -#define JS_HOOK_CALL 0 -#define JS_HOOK_RET 1 -#define JS_HOOK_CYCLE 2 -#define JS_HOOK_GC 3 -void js_debug_sethook(JSContext *ctx, js_hook, int type); +typedef void (*js_hook)(JSContext*, int type, js_debug *dbg, void *user); +#define JS_HOOK_CALL 1 +#define JS_HOOK_RET 2 +#define JS_HOOK_CYCLE 4 +#define JS_HOOK_GC 8 +void js_debug_sethook(JSContext *ctx, js_hook, int type, void *user); uint32_t js_debugger_stack_depth(JSContext *ctx); JSValue js_debugger_backtrace_fns(JSContext *ctx, const uint8_t *cur_pc); diff --git a/source/scheduler.c b/source/scheduler.c index d10ed445..e3c66196 100644 --- a/source/scheduler.c +++ b/source/scheduler.c @@ -259,12 +259,7 @@ void actor_initialize(void) { void actor_free(cell_rt *actor) { lockless_shdel(actors, actor->id); - - // Note: Removing from ready queue is hard with a singly linked list. - // We assume actor_turn handles disrupted/freed actors gracefully or they run once more. - // The old code did lockless_rm(ready_queue, actor), which was O(N). - // Here we rely on the actor->disrupt flag checked in actor_turn. - + // Do not go forward with actor destruction until the actor is completely free pthread_mutex_lock(actor->msg_mutex); pthread_mutex_lock(actor->mutex); @@ -539,10 +534,6 @@ const char *register_actor(const char *id, cell_rt *actor, int mainthread, doubl int actor_interrupt_cb(JSRuntime *rt, cell_rt *crt) { - // Locking engine.lock for shutting_down might be too expensive for interrupt? - // Check atomic-like access or just access it. - // int s; pthread_mutex_lock(&engine.lock); s = engine.shutting_down; pthread_mutex_unlock(&engine.lock); - // But engine.shutting_down is int, atomic read on x86/arm usually ok. return engine.shutting_down || crt->disrupt; } @@ -573,10 +564,12 @@ const char *send_message(const char *id, void *msg) void actor_turn(cell_rt *actor) { pthread_mutex_lock(actor->mutex); - - actor->state = ACTOR_RUNNING; - + actor->state = ACTOR_RUNNING; + + if (actor->trace_hook) + actor->trace_hook(actor->name, CELL_HOOK_ENTER); + TAKETURN: pthread_mutex_lock(actor->msg_mutex); @@ -605,20 +598,12 @@ void actor_turn(cell_rt *actor) if (actor->disrupt) goto ENDTURN; - // Check if anyone else is waiting? - // In the new system, checking the global queue is expensive (lock). - // And "someone else waiting" logic was to yield. - // With threads, we don't need to yield as much, let the OS schedule. - // But we might want to prevent one actor hogging the worker? - // For now, remove the yield check or implement it with try_lock or simple check. - // int someone_else_waiting = (lockless_arrlen(ready_queue) > 0); - // We'll just remove the optimization/yield for now to simplify. - // if (!someone_else_waiting) goto TAKETURN; - ENDTURN: - actor->state = ACTOR_IDLE; - + actor->state = ACTOR_IDLE; + if (actor->trace_hook) + actor->trace_hook(actor->name, CELL_HOOK_EXIT); + set_actor_state(actor); pthread_mutex_unlock(actor->mutex); diff --git a/test.ce b/test.ce index aa3e87a6..f88fb151 100644 --- a/test.ce +++ b/test.ce @@ -1,4 +1,4 @@ -var shop = use('shop') +var shop = use('internal/shop') var fd = use('fd') var time = use('time') var json = use('json') diff --git a/tests/text.cm b/tests/text.cm index 29ea109b..94b9d10c 100644 --- a/tests/text.cm +++ b/tests/text.cm @@ -1,5 +1,3 @@ -var text = use('text') - return { // Array conversion tests test_array_basic: function() { diff --git a/tests/utf8.cm b/tests/utf8.cm index b26f64d1..7e9f29c9 100644 --- a/tests/utf8.cm +++ b/tests/utf8.cm @@ -1,4 +1,3 @@ -var text = use('text'); var blob = use('blob'); var utf8 = use('utf8'); diff --git a/toml.cm b/toml.cm index d7133fea..14a44ebc 100644 --- a/toml.cm +++ b/toml.cm @@ -146,7 +146,7 @@ function encode_toml(obj) { } else if (typeof value == 'boolean') { return value ? 'true' : 'false' } else if (typeof value == 'number') { - return String(value) + return text(value) } else if (isa(value, array)) { var items = [] for (var i = 0; i < value.length; i++) { @@ -154,7 +154,7 @@ function encode_toml(obj) { } return '[' + items.join(', ') + ']' } - return String(value) + return text(value) } function quote_key(k) { diff --git a/update.ce b/update.ce index a29df7a4..7cda4eb5 100644 --- a/update.ce +++ b/update.ce @@ -8,7 +8,7 @@ // cell update - Update all packages // cell update - Update a specific package -var shop = use('shop') +var shop = use('internal/shop') var target_pkg = null diff --git a/upgrade.ce b/upgrade.ce index 998e7a04..94454852 100644 --- a/upgrade.ce +++ b/upgrade.ce @@ -1,4 +1,4 @@ -var shop = use('shop') +var shop = use('internal/shop') var fd = use('fd') var cmd = args.length > 0 ? args[0] : null diff --git a/util.cm b/util.cm new file mode 100644 index 00000000..1135c111 --- /dev/null +++ b/util.cm @@ -0,0 +1,5 @@ +var shop = use('internal/shop') + +return { + file_reload: shop.file_reload +} \ No newline at end of file diff --git a/why.ce b/why.ce index de8556a0..539cbec6 100644 --- a/why.ce +++ b/why.ce @@ -1,4 +1,4 @@ -var shop = use('shop') +var shop = use('internal/shop') var pkg = use('package') if (!args || args.length < 1) {