trace
This commit is contained in:
4
build.cm
4
build.cm
@@ -971,7 +971,7 @@ Build.compile_native = function(src_path, target, buildtype, pkg) {
|
||||
log.error('Linking native dylib failed for: ' + src_path); disrupt
|
||||
}
|
||||
|
||||
log.console('Built native: ' + fd.basename(dylib_path))
|
||||
log.shop('compiled native: ' + src_path)
|
||||
|
||||
return dylib_path
|
||||
}
|
||||
@@ -1043,7 +1043,7 @@ Build.compile_native_ir = function(optimized, src_path, opts) {
|
||||
log.error('Linking native dylib failed for: ' + src_path); disrupt
|
||||
}
|
||||
|
||||
log.console('Built native: ' + fd.basename(dylib_path))
|
||||
log.shop('compiled native: ' + src_path)
|
||||
|
||||
return dylib_path
|
||||
}
|
||||
|
||||
@@ -1558,6 +1558,7 @@ $_.clock(_ => {
|
||||
}
|
||||
|
||||
env.use = function(path) {
|
||||
if (path == 'prosperon/compositor') log.shop('DEBUG engine env.use: pkg=' + (pkg || '(null)'))
|
||||
var ck = 'core/' + path
|
||||
var _use_core_result = null
|
||||
var _use_core_ok = false
|
||||
|
||||
@@ -788,7 +788,7 @@ function resolve_mod_fn(path, pkg) {
|
||||
if (dylib_path) {
|
||||
handle = os.dylib_open(dylib_path)
|
||||
if (handle) {
|
||||
sym = pkg && _stem ? Shop.c_symbol_for_file(pkg, _stem) : null
|
||||
sym = pkg ? Shop.c_symbol_for_file(pkg, _stem || fd.basename(path)) : null
|
||||
return {_native: true, _handle: handle, _sym: sym}
|
||||
}
|
||||
}
|
||||
@@ -1280,6 +1280,7 @@ Shop.is_loaded = function is_loaded(path, package_context) {
|
||||
// Create a use function bound to a specific package context
|
||||
function make_use_fn(pkg, force_native) {
|
||||
return function(path) {
|
||||
if (path == 'prosperon/compositor') log.shop('DEBUG make_use_fn: pkg=' + (is_text(pkg) ? pkg : '(non-text)') + ' force_native=' + (force_native ? 'true' : 'false'))
|
||||
var _native = null
|
||||
if (force_native && !native_mode) {
|
||||
_native = function() {
|
||||
@@ -1323,6 +1324,7 @@ function execute_module(info)
|
||||
env = stone(env)
|
||||
used = os.native_module_load_named(
|
||||
mod_resolve.symbol._handle, mod_resolve.symbol._sym, env)
|
||||
log.shop('loaded ' + info.cache_key + ' [native]')
|
||||
} else {
|
||||
// Build env with runtime fns, capabilities, and use function
|
||||
file_info = Shop.file_info(mod_resolve.path)
|
||||
@@ -1334,6 +1336,7 @@ function execute_module(info)
|
||||
|
||||
// Load compiled bytecode with env
|
||||
used = mach_load(mod_resolve.symbol, env)
|
||||
log.shop('loaded ' + info.cache_key + ' [bytecode]')
|
||||
}
|
||||
} else if (c_resolve.scope < 900) {
|
||||
// C only
|
||||
@@ -1373,6 +1376,11 @@ Shop.use = function use(path, _pkg_ctx) {
|
||||
log.error("use() expects a text module path, but received a non-text value")
|
||||
disrupt
|
||||
}
|
||||
if (path == 'prosperon/compositor') {
|
||||
if (is_text(_pkg_ctx)) log.shop('DEBUG use(): _pkg_ctx=' + _pkg_ctx)
|
||||
else if (_pkg_ctx == null) log.shop('DEBUG use(): _pkg_ctx=NULL')
|
||||
else log.shop('DEBUG use(): _pkg_ctx is non-text non-null')
|
||||
}
|
||||
var package_context = is_core_dir(_pkg_ctx) ? 'core' : safe_canonicalize(_pkg_ctx)
|
||||
// Check for embedded module (static builds)
|
||||
var embed_key = 'embedded:' + path
|
||||
|
||||
@@ -789,9 +789,32 @@ double cell_random() {
|
||||
return (double)buf / 9007199254740992.0;
|
||||
}
|
||||
|
||||
static cell_hook g_cell_trace_hook = NULL;
|
||||
|
||||
void cell_trace_sethook(cell_hook hook)
|
||||
{
|
||||
(void)hook;
|
||||
g_cell_trace_hook = hook;
|
||||
}
|
||||
|
||||
cell_hook cell_trace_gethook(void)
|
||||
{
|
||||
return g_cell_trace_hook;
|
||||
}
|
||||
|
||||
void cell_rt_set_trace_hook(JSContext *ctx, cell_hook hook)
|
||||
{
|
||||
struct cell_rt *rt = JS_GetContextOpaque(ctx);
|
||||
if (rt) rt->trace_hook = hook;
|
||||
}
|
||||
|
||||
const char *cell_rt_name(struct cell_rt *rt)
|
||||
{
|
||||
return rt->name;
|
||||
}
|
||||
|
||||
JSContext *cell_rt_context(struct cell_rt *rt)
|
||||
{
|
||||
return rt->context;
|
||||
}
|
||||
|
||||
int uncaught_exception(JSContext *js, JSValue v)
|
||||
|
||||
@@ -37,8 +37,15 @@ JSValue js_core_json_use(JSContext *js);
|
||||
|
||||
#define CELL_HOOK_ENTER 1
|
||||
#define CELL_HOOK_EXIT 2
|
||||
typedef void (*cell_hook)(const char *name, int type);
|
||||
struct cell_rt;
|
||||
typedef void (*cell_hook)(struct cell_rt *rt, int type);
|
||||
void cell_trace_sethook(cell_hook);
|
||||
cell_hook cell_trace_gethook(void);
|
||||
void cell_rt_set_trace_hook(JSContext *ctx, cell_hook hook);
|
||||
size_t cell_ctx_heap_used(JSContext *ctx);
|
||||
const char *cell_rt_name(struct cell_rt *rt);
|
||||
JSContext *cell_rt_context(struct cell_rt *rt);
|
||||
void js_debug_gethook(JSContext *ctx, js_hook *hook, int *type, void **user);
|
||||
|
||||
// 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 } } } }
|
||||
|
||||
@@ -1345,6 +1345,20 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
|
||||
pc = code->entry_point;
|
||||
result = JS_NULL;
|
||||
|
||||
/* Fire trace hook for top-level register function entry */
|
||||
if (unlikely(ctx->trace_hook) && (ctx->trace_type & JS_HOOK_CALL)) {
|
||||
js_debug dbg = {0};
|
||||
if (code->name_cstr)
|
||||
snprintf(dbg.name, sizeof(dbg.name), "%s", code->name_cstr);
|
||||
if (code->filename_cstr)
|
||||
snprintf(dbg.filename, sizeof(dbg.filename), "%s", code->filename_cstr);
|
||||
if (code->line_table)
|
||||
dbg.line = code->line_table[code->entry_point].line;
|
||||
dbg.param_n = code->arity;
|
||||
dbg.unique = (int)(uintptr_t)code;
|
||||
ctx->trace_hook(ctx, JS_HOOK_CALL, &dbg, ctx->trace_data);
|
||||
}
|
||||
} /* end normal path block */
|
||||
|
||||
vm_dispatch:
|
||||
@@ -2132,6 +2146,8 @@ vm_dispatch:
|
||||
stone_mutable_text(frame->slots[a]);
|
||||
result = frame->slots[a];
|
||||
if (!JS_IsPtr(frame->caller)) goto done;
|
||||
if (unlikely(ctx->trace_hook) && (ctx->trace_type & JS_HOOK_RET))
|
||||
ctx->trace_hook(ctx, JS_HOOK_RET, NULL, ctx->trace_data);
|
||||
{
|
||||
#ifdef VALIDATE_GC
|
||||
const char *callee_name = "?";
|
||||
@@ -2177,6 +2193,8 @@ vm_dispatch:
|
||||
VM_CASE(MACH_RETNIL):
|
||||
result = JS_NULL;
|
||||
if (!JS_IsPtr(frame->caller)) goto done;
|
||||
if (unlikely(ctx->trace_hook) && (ctx->trace_type & JS_HOOK_RET))
|
||||
ctx->trace_hook(ctx, JS_HOOK_RET, NULL, ctx->trace_data);
|
||||
{
|
||||
JSFrameRegister *caller = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
|
||||
frame->caller = JS_NULL;
|
||||
@@ -2745,6 +2763,19 @@ vm_dispatch:
|
||||
if (fn->kind == JS_FUNC_KIND_REGISTER) {
|
||||
/* Register function: FRAME already allocated nr_slots — just switch */
|
||||
JSCodeRegister *fn_code = JS_VALUE_GET_CODE(fn->u.cell.code)->u.reg.code;
|
||||
/* Fire trace hook for register-to-register call */
|
||||
if (unlikely(ctx->trace_hook) && (ctx->trace_type & JS_HOOK_CALL)) {
|
||||
js_debug dbg = {0};
|
||||
if (fn_code->name_cstr)
|
||||
snprintf(dbg.name, sizeof(dbg.name), "%s", fn_code->name_cstr);
|
||||
if (fn_code->filename_cstr)
|
||||
snprintf(dbg.filename, sizeof(dbg.filename), "%s", fn_code->filename_cstr);
|
||||
if (fn_code->line_table)
|
||||
dbg.line = fn_code->line_table[fn_code->entry_point].line;
|
||||
dbg.param_n = fn_code->arity;
|
||||
dbg.unique = (int)(uintptr_t)fn_code;
|
||||
ctx->trace_hook(ctx, JS_HOOK_CALL, &dbg, ctx->trace_data);
|
||||
}
|
||||
/* Save return info */
|
||||
frame->address = JS_NewInt32(ctx, (pc << 16) | b);
|
||||
fr->caller = JS_MKPTR(frame);
|
||||
@@ -2800,6 +2831,23 @@ vm_dispatch:
|
||||
|
||||
if (fn->kind == JS_FUNC_KIND_REGISTER) {
|
||||
JSCodeRegister *fn_code = JS_VALUE_GET_CODE(FN_READ_CODE(fn))->u.reg.code;
|
||||
/* Tail call: fire RET for current, CALL for new */
|
||||
if (unlikely(ctx->trace_hook)) {
|
||||
if (ctx->trace_type & JS_HOOK_RET)
|
||||
ctx->trace_hook(ctx, JS_HOOK_RET, NULL, ctx->trace_data);
|
||||
if (ctx->trace_type & JS_HOOK_CALL) {
|
||||
js_debug dbg = {0};
|
||||
if (fn_code->name_cstr)
|
||||
snprintf(dbg.name, sizeof(dbg.name), "%s", fn_code->name_cstr);
|
||||
if (fn_code->filename_cstr)
|
||||
snprintf(dbg.filename, sizeof(dbg.filename), "%s", fn_code->filename_cstr);
|
||||
if (fn_code->line_table)
|
||||
dbg.line = fn_code->line_table[fn_code->entry_point].line;
|
||||
dbg.param_n = fn_code->arity;
|
||||
dbg.unique = (int)(uintptr_t)fn_code;
|
||||
ctx->trace_hook(ctx, JS_HOOK_CALL, &dbg, ctx->trace_data);
|
||||
}
|
||||
}
|
||||
int current_slots = (int)objhdr_cap56(frame->header);
|
||||
|
||||
if (fn_code->nr_slots <= current_slots) {
|
||||
@@ -3003,6 +3051,9 @@ suspend:
|
||||
return result;
|
||||
|
||||
done:
|
||||
/* Fire trace hook for top-level register function return */
|
||||
if (unlikely(ctx->trace_hook) && (ctx->trace_type & JS_HOOK_RET))
|
||||
ctx->trace_hook(ctx, JS_HOOK_RET, NULL, ctx->trace_data);
|
||||
#ifdef HAVE_ASAN
|
||||
__asan_js_ctx = NULL;
|
||||
#endif
|
||||
|
||||
@@ -1935,6 +1935,10 @@ int ctx_gc (JSContext *ctx, int allow_grow, size_t alloc_size) {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fire GC hook if registered */
|
||||
if (ctx->trace_hook && (ctx->trace_type & JS_HOOK_GC))
|
||||
ctx->trace_hook(ctx, JS_HOOK_GC, NULL, ctx->trace_data);
|
||||
|
||||
/* Check memory limit — kill actor if heap exceeds cap */
|
||||
if (ctx->heap_memory_limit > 0 && ctx->current_block_size > ctx->heap_memory_limit) {
|
||||
#ifdef ACTOR_TRACE
|
||||
@@ -11780,6 +11784,15 @@ void js_debug_sethook (JSContext *ctx, js_hook hook, int type, void *user) {
|
||||
ctx->trace_data = user;
|
||||
}
|
||||
|
||||
void js_debug_gethook (JSContext *ctx, js_hook *hook, int *type, void **user) {
|
||||
if (hook) *hook = ctx->trace_hook;
|
||||
if (type) *type = ctx->trace_type;
|
||||
if (user) *user = ctx->trace_data;
|
||||
}
|
||||
|
||||
size_t cell_ctx_heap_used (JSContext *ctx) {
|
||||
return (size_t)(ctx->heap_free - ctx->heap_base);
|
||||
}
|
||||
|
||||
/* Public API: get stack trace as JS array of {fn, file, line, col} objects.
|
||||
Does NOT clear reg_current_frame — caller is responsible if needed.
|
||||
|
||||
@@ -710,8 +710,13 @@ void actor_turn(cell_rt *actor)
|
||||
actor->name ? actor->name : actor->id, prev_state);
|
||||
#endif
|
||||
|
||||
if (!actor->trace_hook) {
|
||||
cell_hook gh = cell_trace_gethook();
|
||||
if (gh) actor->trace_hook = gh;
|
||||
}
|
||||
|
||||
if (actor->trace_hook)
|
||||
actor->trace_hook(actor->name, CELL_HOOK_ENTER);
|
||||
actor->trace_hook(actor, CELL_HOOK_ENTER);
|
||||
|
||||
JSValue result;
|
||||
|
||||
@@ -826,7 +831,7 @@ ENDTURN:
|
||||
actor->state = ACTOR_IDLE;
|
||||
|
||||
if (actor->trace_hook)
|
||||
actor->trace_hook(actor->name, CELL_HOOK_EXIT);
|
||||
actor->trace_hook(actor, CELL_HOOK_EXIT);
|
||||
|
||||
if (actor->disrupt) {
|
||||
#ifdef SCHEDULER_DEBUG
|
||||
@@ -853,7 +858,7 @@ ENDTURN_SLOW:
|
||||
actor->name ? actor->name : actor->id);
|
||||
#endif
|
||||
if (actor->trace_hook)
|
||||
actor->trace_hook(actor->name, CELL_HOOK_EXIT);
|
||||
actor->trace_hook(actor, CELL_HOOK_EXIT);
|
||||
enqueue_actor_priority(actor);
|
||||
pthread_mutex_unlock(actor->mutex);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user