git stack info
This commit is contained in:
60
quickjs.c
60
quickjs.c
@@ -6213,6 +6213,66 @@ struct gc_object {
|
||||
JSAtom classname;
|
||||
};
|
||||
|
||||
JSValue js_dump_stack_info(JSContext *ctx)
|
||||
{
|
||||
JSRuntime *rt = ctx->rt;
|
||||
JSValue ret = JS_NewObject(ctx);
|
||||
|
||||
// We can do a rough usage estimate:
|
||||
uintptr_t used = rt->stack_top ? (rt->stack_top - rt->stack_limit) : 0;
|
||||
JS_SetPropertyStr(ctx, ret, "used", JS_NewUint32(ctx, (uint32_t)used));
|
||||
JS_SetPropertyStr(ctx, ret, "maxSize", JS_NewUint32(ctx, (uint32_t)rt->stack_size));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue js_dump_object_for_cycle(JSContext *ctx, JSObject *p) {
|
||||
JSValue obj = JS_NewObject(ctx);
|
||||
|
||||
// For debugging, store pointer address as a string
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%p", (void *)p);
|
||||
JS_SetPropertyStr(ctx, obj, "addr", JS_NewString(ctx, buf));
|
||||
|
||||
// Class ID
|
||||
JS_SetPropertyStr(ctx, obj, "class_id", JS_NewUint32(ctx, p->class_id));
|
||||
|
||||
// If desired, store shape pointer, etc.
|
||||
if (p->shape) {
|
||||
snprintf(buf, sizeof(buf), "%p", (void *)p->shape);
|
||||
JS_SetPropertyStr(ctx, obj, "shape", JS_NewString(ctx, buf));
|
||||
}
|
||||
|
||||
// Maybe also store class name (if class_id < rt->class_count)
|
||||
if (p->class_id < ctx->rt->class_count) {
|
||||
JSAtom cname = ctx->rt->class_array[p->class_id].class_name;
|
||||
JSValue cname_val = JS_AtomToValue(ctx, cname);
|
||||
JS_SetPropertyStr(ctx, obj, "class_name", cname_val);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static JSValue build_cycle_array(JSContext *ctx, JSRuntime *rt) {
|
||||
JSValue arr = JS_NewArray(ctx);
|
||||
uint32_t idx = 0;
|
||||
|
||||
struct list_head *el;
|
||||
list_for_each(el, &rt->tmp_obj_list) {
|
||||
JSGCObjectHeader *p = list_entry(el, JSGCObjectHeader, link);
|
||||
// We can dump whichever GC types we want:
|
||||
if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {
|
||||
JSObject *obj = (JSObject *)p;
|
||||
JSValue dump = js_dump_object_for_cycle(ctx, obj);
|
||||
JS_SetPropertyUint32(ctx, arr, idx++, dump);
|
||||
} else {
|
||||
// For function bytecode or async function, you could create
|
||||
// a smaller descriptor or skip them, if desired.
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
static void JS_RunGCInternal(JSRuntime *rt, BOOL remove_weak_objects)
|
||||
{
|
||||
#ifdef TRACY_ENABLE
|
||||
|
||||
19
quickjs.h
19
quickjs.h
@@ -1205,7 +1205,24 @@ JSValue js_debugger_fn_info(JSContext *ctx, JSValue fn);
|
||||
JSValue js_debugger_backtrace_fns(JSContext *ctx, const uint8_t *cur_pc);
|
||||
uint32_t js_debugger_stack_depth(JSContext *ctx);
|
||||
JSValue js_dump_value(JSContext *ctx, JSValue v);
|
||||
JSValue js_dump_object(JSContext *ctx, JSObject *p);
|
||||
JSValue js_dump_object(JSContext *ctx, JSGCObjectHeader *p);
|
||||
JSValue js_dump_leaks(JSContext *ctx);
|
||||
JSVAlue js_dump_stack_info(JSContext *ctx);
|
||||
|
||||
JSValue js_get_memory_usage(JSContext *js);
|
||||
|
||||
JSValue js_dump_atoms(JSContext *js);
|
||||
JSValue js_dump_objects(JSContext *js);
|
||||
JSValue js_dump_shapes(JSContext *js);
|
||||
JSValue js_get_object_class_distribution(JSContext *js);
|
||||
JSValue js_get_object_type_overheads(JSContext *js);
|
||||
|
||||
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);
|
||||
|
||||
#undef js_unlikely
|
||||
#undef js_force_inline
|
||||
|
||||
Reference in New Issue
Block a user