crash fixes

This commit is contained in:
2026-02-06 23:38:56 -06:00
parent 1abcaa92c7
commit aba8eb66bd

View File

@@ -33002,6 +33002,7 @@ static const char *mach_gen_binop_to_string (const char *kind) {
if (strcmp (kind, "<=") == 0) return "le";
if (strcmp (kind, ">") == 0) return "gt";
if (strcmp (kind, ">=") == 0) return "ge";
if (strcmp (kind, "**") == 0) return "pow";
if (strcmp (kind, "in") == 0) return "in";
return "add";
}
@@ -34379,15 +34380,15 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
JSValue right = frame->slots[(int)a3->valuedouble];
if (JS_VALUE_IS_BOTH_INT(left, right)) {
int32_t ia = JS_VALUE_GET_INT(left), ib = JS_VALUE_GET_INT(right);
if (ib == 0) { goto disrupt; }
if (ia % ib == 0) frame->slots[dest] = JS_NewInt32(ctx, ia / ib);
if (ib == 0) { frame->slots[dest] = JS_NULL; }
else if (ia % ib == 0) frame->slots[dest] = JS_NewInt32(ctx, ia / ib);
else frame->slots[dest] = JS_NewFloat64(ctx, (double)ia / (double)ib);
} else if (JS_IsNumber(left) && JS_IsNumber(right)) {
double a, b;
JS_ToFloat64(ctx, &a, left);
JS_ToFloat64(ctx, &b, right);
if (b == 0.0) { goto disrupt; }
frame->slots[dest] = JS_NewFloat64(ctx, a / b);
if (b == 0.0) { frame->slots[dest] = JS_NULL; }
else frame->slots[dest] = JS_NewFloat64(ctx, a / b);
} else { goto disrupt; }
}
else if (strcmp(op, "integer_divide") == 0) {
@@ -34396,14 +34397,14 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
JSValue right = frame->slots[(int)a3->valuedouble];
if (JS_VALUE_IS_BOTH_INT(left, right)) {
int32_t ib = JS_VALUE_GET_INT(right);
if (ib == 0) { goto disrupt; }
frame->slots[dest] = JS_NewInt32(ctx, JS_VALUE_GET_INT(left) / ib);
if (ib == 0) { frame->slots[dest] = JS_NULL; }
else frame->slots[dest] = JS_NewInt32(ctx, JS_VALUE_GET_INT(left) / ib);
} else if (JS_IsNumber(left) && JS_IsNumber(right)) {
double a, b;
JS_ToFloat64(ctx, &a, left);
JS_ToFloat64(ctx, &b, right);
if (b == 0.0) { goto disrupt; }
frame->slots[dest] = JS_NewInt32(ctx, (int32_t)(a / b));
if (b == 0.0) { frame->slots[dest] = JS_NULL; }
else frame->slots[dest] = JS_NewInt32(ctx, (int32_t)(a / b));
} else { goto disrupt; }
}
else if (strcmp(op, "modulo") == 0) {
@@ -34412,14 +34413,14 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
JSValue right = frame->slots[(int)a3->valuedouble];
if (JS_VALUE_IS_BOTH_INT(left, right)) {
int32_t ib = JS_VALUE_GET_INT(right);
if (ib == 0) { goto disrupt; }
frame->slots[dest] = JS_NewInt32(ctx, JS_VALUE_GET_INT(left) % ib);
if (ib == 0) { frame->slots[dest] = JS_NULL; }
else frame->slots[dest] = JS_NewInt32(ctx, JS_VALUE_GET_INT(left) % ib);
} else if (JS_IsNumber(left) && JS_IsNumber(right)) {
double a, b;
JS_ToFloat64(ctx, &a, left);
JS_ToFloat64(ctx, &b, right);
if (b == 0.0) { goto disrupt; }
frame->slots[dest] = JS_NewFloat64(ctx, fmod(a, b));
if (b == 0.0) { frame->slots[dest] = JS_NULL; }
else frame->slots[dest] = JS_NewFloat64(ctx, fmod(a, b));
} else { goto disrupt; }
}
else if (strcmp(op, "remainder") == 0) {
@@ -34428,14 +34429,25 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
JSValue right = frame->slots[(int)a3->valuedouble];
if (JS_VALUE_IS_BOTH_INT(left, right)) {
int32_t ib = JS_VALUE_GET_INT(right);
if (ib == 0) { goto disrupt; }
frame->slots[dest] = JS_NewInt32(ctx, JS_VALUE_GET_INT(left) % ib);
if (ib == 0) { frame->slots[dest] = JS_NULL; }
else frame->slots[dest] = JS_NewInt32(ctx, JS_VALUE_GET_INT(left) % ib);
} else if (JS_IsNumber(left) && JS_IsNumber(right)) {
double a, b;
JS_ToFloat64(ctx, &a, left);
JS_ToFloat64(ctx, &b, right);
if (b == 0.0) { goto disrupt; }
frame->slots[dest] = JS_NewFloat64(ctx, remainder(a, b));
if (b == 0.0) { frame->slots[dest] = JS_NULL; }
else frame->slots[dest] = JS_NewFloat64(ctx, remainder(a, b));
} else { goto disrupt; }
}
else if (strcmp(op, "pow") == 0) {
int dest = (int)a1->valuedouble;
JSValue left = frame->slots[(int)a2->valuedouble];
JSValue right = frame->slots[(int)a3->valuedouble];
if (JS_IsNumber(left) && JS_IsNumber(right)) {
double a, b;
JS_ToFloat64(ctx, &a, left);
JS_ToFloat64(ctx, &b, right);
frame->slots[dest] = JS_NewFloat64(ctx, pow(a, b));
} else { goto disrupt; }
}
else if (strcmp(op, "max") == 0) {
@@ -34740,6 +34752,17 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
} else { goto disrupt; }
}
/* ---- in operator ---- */
else if (strcmp(op, "in") == 0) {
int dest = (int)a1->valuedouble;
JSValue left = frame->slots[(int)a2->valuedouble];
JSValue right = frame->slots[(int)a3->valuedouble];
int ret = JS_HasPropertyKey(ctx, right, left);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
if (ret < 0) { goto disrupt; }
frame->slots[dest] = JS_NewBool(ctx, ret);
}
/* ---- Sensory (type checks) ---- */
else if (strcmp(op, "text?") == 0) {
int dest = (int)a1->valuedouble;
@@ -35366,23 +35389,32 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
continue;
disrupt:
/* Search frame chain for a disruption handler */
for (;;) {
JSFunction *fn = JS_VALUE_GET_FUNCTION(frame->function);
JSMCode *fn_code = fn->u.mcode.code;
if (fn_code->disruption_pc > 0) {
code = fn_code;
pc = fn_code->disruption_pc;
break;
/* Search frame chain for a disruption handler.
Use frame_pc to track each frame's execution point:
- For the faulting frame, it's the current pc.
- For unwound caller frames, read from frame->address. */
{
uint32_t frame_pc = pc;
for (;;) {
JSFunction *fn = JS_VALUE_GET_FUNCTION(frame->function);
JSMCode *fn_code = fn->u.mcode.code;
/* Only enter handler if we're not already inside it */
if (fn_code->disruption_pc > 0 && frame_pc < fn_code->disruption_pc) {
code = fn_code;
pc = fn_code->disruption_pc;
break;
}
if (JS_IsNull(frame->caller)) {
result = JS_NULL;
goto done;
}
/* Unwind one frame — read caller's saved pc from its address field */
JSFrameRegister *caller = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
frame->caller = JS_NULL;
frame = caller;
frame_ref.val = JS_MKPTR(frame);
frame_pc = (uint32_t)(JS_VALUE_GET_INT(frame->address) >> 16);
}
if (JS_IsNull(frame->caller)) {
result = JS_NULL;
goto done;
}
JSFrameRegister *caller = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
frame->caller = JS_NULL;
frame = caller;
frame_ref.val = JS_MKPTR(frame);
}
}
@@ -35478,6 +35510,8 @@ JSValue JS_CallMcode(JSContext *ctx, const char *mcode_json) {
/* Execute with global_obj as this */
JSValue result = mcode_exec(ctx, code, ctx->global_obj, 0, NULL, JS_NULL);
/* Clear frame ref before freeing mcode — stack trace data is inside code */
ctx->reg_current_frame = JS_NULL;
jsmcode_free(code);
return result;
}