Merge branch 'master' into optimize_mcode

This commit is contained in:
2026-02-20 23:18:27 -06:00
11 changed files with 373 additions and 5 deletions

View File

@@ -25,6 +25,7 @@
#define BLOB_IMPLEMENTATION
#include "quickjs-internal.h"
#include <unistd.h>
// #define DUMP_BUDDY
#ifdef DUMP_BUDDY
@@ -11718,10 +11719,10 @@ JSValue JS_GetStack(JSContext *ctx) {
JSGCRef item_ref;
JS_PushGCRef(ctx, &item_ref);
item_ref.val = JS_NewObject(ctx);
JS_SetPropertyStr(ctx, item_ref.val, "fn",
JS_NewString(ctx, frames[i].fn ? frames[i].fn : "<anonymous>"));
JS_SetPropertyStr(ctx, item_ref.val, "file",
JS_NewString(ctx, frames[i].file ? frames[i].file : "<unknown>"));
JSValue fn_str = JS_NewString(ctx, frames[i].fn ? frames[i].fn : "<anonymous>");
JS_SetPropertyStr(ctx, item_ref.val, "fn", fn_str);
JSValue file_str = JS_NewString(ctx, frames[i].file ? frames[i].file : "<unknown>");
JS_SetPropertyStr(ctx, item_ref.val, "file", file_str);
JS_SetPropertyStr(ctx, item_ref.val, "line", JS_NewInt32(ctx, frames[i].line));
JS_SetPropertyStr(ctx, item_ref.val, "col", JS_NewInt32(ctx, frames[i].col));
JS_SetPropertyNumber(ctx, arr_ref.val, i, item_ref.val);
@@ -11731,3 +11732,65 @@ JSValue JS_GetStack(JSContext *ctx) {
JS_PopGCRef(ctx, &arr_ref);
return result;
}
/* Crash-safe stack printer: walks JS frames and writes to stderr
using only write() (async-signal-safe). No GC allocations.
Best-effort: if the heap is corrupted, we may double-fault. */
void JS_CrashPrintStack(JSContext *ctx) {
if (!ctx) return;
if (JS_IsNull(ctx->reg_current_frame)) return;
static const char hdr[] = "\n--- JS Stack at crash ---\n";
write(STDERR_FILENO, hdr, sizeof(hdr) - 1);
JSFrameRegister *frame = (JSFrameRegister *)JS_VALUE_GET_PTR(ctx->reg_current_frame);
uint32_t cur_pc = ctx->current_register_pc;
int is_first = 1;
int depth = 0;
while (frame && depth < 32) {
if (!JS_IsFunction(frame->function)) break;
JSFunction *fn = JS_VALUE_GET_FUNCTION(frame->function);
if (fn->kind == JS_FUNC_KIND_REGISTER && JS_VALUE_GET_CODE(fn->u.cell.code)->u.reg.code) {
JSCodeRegister *code = JS_VALUE_GET_CODE(fn->u.cell.code)->u.reg.code;
uint32_t pc = is_first ? cur_pc : (uint32_t)(JS_VALUE_GET_INT(frame->address) >> 16);
const char *name = code->name_cstr ? code->name_cstr : "<anonymous>";
const char *file = code->filename_cstr ? code->filename_cstr : "<unknown>";
int line = 0;
if (code->line_table && pc < code->instr_count)
line = code->line_table[pc].line;
/* Format: " at name (file:line)\n" using only write() */
char buf[512];
int pos = 0;
buf[pos++] = ' '; buf[pos++] = ' '; buf[pos++] = ' '; buf[pos++] = ' ';
buf[pos++] = 'a'; buf[pos++] = 't'; buf[pos++] = ' ';
for (const char *p = name; *p && pos < 200; p++) buf[pos++] = *p;
buf[pos++] = ' '; buf[pos++] = '(';
for (const char *p = file; *p && pos < 440; p++) buf[pos++] = *p;
buf[pos++] = ':';
/* itoa for line number */
if (line == 0) {
buf[pos++] = '0';
} else {
char digits[12];
int d = 0;
int n = line;
while (n > 0) { digits[d++] = '0' + (n % 10); n /= 10; }
for (int i = d - 1; i >= 0; i--) buf[pos++] = digits[i];
}
buf[pos++] = ')'; buf[pos++] = '\n';
write(STDERR_FILENO, buf, pos);
}
if (JS_IsNull(frame->caller)) break;
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
is_first = 0;
depth++;
}
static const char ftr[] = "--- End JS Stack ---\n";
write(STDERR_FILENO, ftr, sizeof(ftr) - 1);
}