diff --git a/meson.build b/meson.build index 2b0f731..32ac7a3 100644 --- a/meson.build +++ b/meson.build @@ -14,11 +14,6 @@ if get_option('bignum') add_project_arguments('-DCONFIG_BIGNUM', language : 'c') endif -if get_option('trace') - add_project_arguments('-DTRACY_ENABLE', language:'c') - deps += dependency('tracy', static:true) -endif - lib_sources = ['libbf.c', 'libregexp.c', 'quickjs.c', 'libunicode.c', 'cutils.c'] libquickjs = library('quickjs', diff --git a/meson.options b/meson.options index a8b1c86..ac09429 100644 --- a/meson.options +++ b/meson.options @@ -1,2 +1 @@ option('bignum', type:'boolean', value:true) -option('trace', type:'boolean', value:false) \ No newline at end of file diff --git a/quickjs.c b/quickjs.c index e8e1ced..f94cde8 100644 --- a/quickjs.c +++ b/quickjs.c @@ -429,8 +429,11 @@ struct JSContext { JSAtom doc_sym; JSAtom typeof_sym; - void (*fn_start_hook)(JSContext*, JSValue); - void (*fn_end_hook)(JSContext*, JSValue); + js_hook fn_start_hook; + js_hook fn_end_hook; + js_hook fn_cycle_hook; + js_hook fn_gc_hook; + int hook_disabled; uint64_t random_state; @@ -1629,9 +1632,6 @@ static void *js_def_malloc(JSMallocState *s, size_t size) s->malloc_count++; s->malloc_size += js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD; -#ifdef TRACY_ENABLE - TracyCAllocN(ptr,js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD, "quickjs"); -#endif return ptr; } @@ -1642,9 +1642,6 @@ static void js_def_free(JSMallocState *s, void *ptr) s->malloc_count--; s->malloc_size -= js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD; -#ifdef TRACY_ENABLE - TracyCFreeN(ptr, "quickjs"); -#endif free(ptr); } @@ -1661,26 +1658,17 @@ static void *js_def_realloc(JSMallocState *s, void *ptr, size_t size) if (size == 0) { s->malloc_count--; s->malloc_size -= old_size + MALLOC_OVERHEAD; -#ifdef TRACY_ENABLE - TracyCFreeN(ptr, "quickjs"); -#endif free(ptr); return NULL; } if (s->malloc_size + size - old_size > s->malloc_limit) return NULL; -#ifdef TRACY_ENABLE - TracyCFreeN(ptr, "quickjs"); -#endif ptr = realloc(ptr, size); if (!ptr) return NULL; s->malloc_size += js_def_malloc_usable_size(ptr) - old_size; -#ifdef TRACY_ENABLE - TracyCAllocN(ptr,js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD, "quickjs"); -#endif return ptr; } @@ -2090,6 +2078,7 @@ JSContext *JS_NewContextRaw(JSRuntime *rt) ctx->fn_start_hook = NULL; ctx->fn_end_hook = NULL; + ctx->hook_disabled = 0; return ctx; } @@ -16245,8 +16234,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->fn_start_hook(ctx,func_obj); + if (unlikely(ctx->fn_start_hook) && !ctx->hook_disabled) { + ctx->hook_disabled = 1; + ctx->fn_start_hook(ctx,func_obj); + ctx->hook_disabled = 0; + } switch(cproto) { case JS_CFUNC_constructor: @@ -16333,9 +16325,11 @@ 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->fn_end_hook(ctx, func_obj); + if (unlikely(ctx->fn_end_hook) && !ctx->hook_disabled) { + ctx->hook_disabled = 1; + ctx->fn_end_hook(ctx, func_obj); + ctx->hook_disabled = 0; + } return ret_val; } @@ -16468,8 +16462,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } b = p->u.func.function_bytecode; - if (unlikely(caller_ctx->fn_start_hook)) + 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(argc < b->arg_count || (flags & JS_CALL_FLAG_COPY_ARGV))) { arg_allocated_size = b->arg_count; @@ -19025,9 +19022,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } rt->current_stack_frame = sf->prev_frame; -// if (unlikely(ctx->fn_end_hook)) -// ctx->fn_end_hook(ctx,func_obj); - + 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; + } return ret_val; } @@ -54977,6 +54976,66 @@ JSValue js_debugger_backtrace_fns(JSContext *ctx, const uint8_t *cur_pc) return ret; } +#define STRLEN(s) (sizeof(s)/sizeof(s[0])) +#define CSTR "" + +void js_debug_info(JSContext *js, JSValue fn, js_debug *dbg) +{ + memset(dbg, 0, sizeof(*dbg)); + + if (!JS_IsObject(fn)) return; + JSObject *p = JS_VALUE_GET_OBJ(fn); + + char *fn_name = get_func_name(js,fn); + + if (!fn_name || fn_name[0] == 0) + dbg->name = js_strdup(js, ""); + else { + dbg->name = js_strdup(js, fn_name); + JS_FreeCString(js,fn_name); + } + + dbg->unique = (int)p; + + switch(p->class_id) { + case JS_CLASS_BYTECODE_FUNCTION: { + JSFunctionBytecode *b = p->u.func.function_bytecode; + // get filename + char *filename = JS_AtomToCString(js, b->debug.filename); + if (!filename || filename[0] == 0) + dbg->filename = js_strdup(js, "unknown"); + else { + dbg->filename = js_strdup(js, filename); + JS_FreeCString(js,filename); + } + + dbg->what = "JS"; + dbg->closure_n = b->closure_var_count; + dbg->param_n = b->arg_count; + dbg->vararg = 1; + dbg->line = b->debug.line_num; + dbg->source = b->debug.source; + dbg->srclen = b->debug.source_len; + break; + } + case JS_CLASS_C_FUNCTION: + dbg->filename = js_strdup(js, ""); + dbg->what = "C"; + dbg->nparams = 0; + dbg->vararg = 1; + dbg->line = 0; + dbg->source = CSTR; + dbg->srclen = STRLEN(CSTR); + break; + } +} + +void free_js_debug_info(JSContext *js, js_debug *dbg) +{ + js_free(js, dbg->filename); + js_free(js, dbg->name); +} + JSValue js_debugger_build_backtrace(JSContext *ctx, const uint8_t *cur_pc) { JSStackFrame *sf; diff --git a/quickjs.h b/quickjs.h index b253069..48a00ee 100644 --- a/quickjs.h +++ b/quickjs.h @@ -1202,6 +1202,23 @@ int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name, int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, const JSCFunctionListEntry *tab, int len); +typedef struct js_debug { + const char *name; // nameof function + const char *what; + const char *source; // source code of function + size_t srclen; + const char *filename; // name of file function is in + int nparams; + int vararg; + int line; // line the function is on + int param_n; + int closure_n; + uint32_t unique; // a unique identifier for this function +} js_debug; + +void js_debug_info(JSContext *js, JSValue fn, js_debug *dbg); +void free_js_debug_info(JSContext *js, js_debug *dbg); + JSValue js_debugger_closure_variables(JSContext *js, JSValue fn); JSValue js_debugger_local_variables(JSContext *ctx, int stack_index); JSValue js_debugger_build_backtrace(JSContext *ctx, const uint8_t *cur_pc);