fix gc backtrace

This commit is contained in:
2026-02-20 14:51:42 -06:00
parent ebfc89e072
commit 11fb213a74
3 changed files with 46 additions and 3 deletions

View File

@@ -92,6 +92,10 @@
// #define DUMP_OBJECTS /* dump objects in JS_FreeContext */
// #define DUMP_READ_OBJECT
// #define DUMP_ROPE_REBALANCE
/* dump GC ref stack push/pop with C backtrace on mismatch.
When HAVE_ASAN is also set, uses __sanitizer_print_stack_trace()
for symbolized output; otherwise falls back to execinfo backtrace(). */
// #define DUMP_GC_REFS
/* test the GC by forcing it before each object allocation */
// #define FORCE_GC_AT_MALLOC

View File

@@ -157,9 +157,46 @@ JSValue *JS_PushGCRef (JSContext *ctx, JSGCRef *ref) {
return &ref->val;
}
#ifdef DUMP_GC_REFS
#ifdef HAVE_ASAN
void __sanitizer_print_stack_trace(void);
#else
#include <execinfo.h>
#endif
static void dump_gc_ref_backtrace(const char *label) {
fprintf(stderr, " [%s C backtrace]:\n", label);
#ifdef HAVE_ASAN
__sanitizer_print_stack_trace();
#else
void *bt[16];
int n = backtrace(bt, 16);
backtrace_symbols_fd(bt, n, 2);
#endif
fprintf(stderr, "\n");
}
#endif
JSValue JS_PopGCRef (JSContext *ctx, JSGCRef *ref) {
if (ctx->top_gc_ref != ref)
fprintf(stderr, "WARN: JS_PopGCRef mismatch (expected %p, got %p)\n", (void*)ctx->top_gc_ref, (void*)ref);
if (ctx->top_gc_ref != ref) {
fprintf(stderr, "WARN: JS_PopGCRef mismatch (expected %p, got %p)\n",
(void *)ctx->top_gc_ref, (void *)ref);
#ifdef DUMP_GC_REFS
/* Walk the stack to show what's between top and the ref being popped */
int depth = 0;
JSGCRef *walk = ctx->top_gc_ref;
while (walk && walk != ref && depth < 16) {
fprintf(stderr, " orphan #%d: ref=%p val=0x%llx\n",
depth, (void *)walk, (unsigned long long)walk->val);
walk = walk->prev;
depth++;
}
if (walk == ref)
fprintf(stderr, " (%d orphaned ref(s) between top and pop target)\n", depth);
else
fprintf(stderr, " (pop target not found in stack — chain is corrupt)\n");
dump_gc_ref_backtrace("pop site");
#endif
}
ctx->top_gc_ref = ref->prev;
return ref->val;
}
@@ -6011,6 +6048,7 @@ exception_ret:
return -1;
exception:
JS_PopGCRef (ctx, &v_ref);
JS_PopGCRef (ctx, &prop_ref);
JS_PopGCRef (ctx, &tab_ref);
JS_PopGCRef (ctx, &sep1_ref);

View File

@@ -387,7 +387,8 @@ run("function early return", function() {
run("extra and missing args", function() {
var fn = function(a, b) { return a + b }
assert_eq(fn(1, 2, 3), 3, "extra args ignored")
assert_eq(should_disrupt(function() { fn(1, 2, 3) }), true, "extra args disrupt")
assert_eq(fn(1, 2), 3, "exact args work")
var fn2 = function(a, b) { return a }
assert_eq(fn2(1), 1, "missing args ok")
})