crash fixes
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user