Merge branch 'better_fn_error'
This commit is contained in:
@@ -494,6 +494,37 @@ static int mach_check_call_arity(JSContext *ctx, JSFunction *fn, int argc) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Scan backwards from pc to find what loaded the callee register.
|
||||||
|
Returns the name in buf, or NULL if unknown. */
|
||||||
|
static const char *mach_callee_name(JSContext *ctx, JSCodeRegister *code,
|
||||||
|
uint32_t pc, int reg,
|
||||||
|
char *buf, size_t buf_size) {
|
||||||
|
int hops = 4; /* limit move-chain depth */
|
||||||
|
for (int i = (int)pc - 2; i >= 0 && hops > 0; i--) {
|
||||||
|
MachInstr32 prev = code->instructions[i];
|
||||||
|
int prev_op = MACH_GET_OP(prev);
|
||||||
|
int prev_a = MACH_GET_A(prev);
|
||||||
|
if (prev_a != reg) continue;
|
||||||
|
if (prev_op == MACH_GETENV || prev_op == MACH_GETINTRINSIC) {
|
||||||
|
int bx = MACH_GET_Bx(prev);
|
||||||
|
if ((uint32_t)bx < code->cpool_count && JS_IsText(code->cpool[bx]))
|
||||||
|
return JS_KeyGetStr(ctx, buf, buf_size, code->cpool[bx]);
|
||||||
|
}
|
||||||
|
if (prev_op == MACH_LOAD_FIELD) {
|
||||||
|
int ci = MACH_GET_C(prev);
|
||||||
|
if ((uint32_t)ci < code->cpool_count && JS_IsText(code->cpool[ci]))
|
||||||
|
return JS_KeyGetStr(ctx, buf, buf_size, code->cpool[ci]);
|
||||||
|
}
|
||||||
|
if (prev_op == MACH_MOVE) {
|
||||||
|
reg = MACH_GET_B(prev);
|
||||||
|
hops--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break; /* some other op wrote to this reg — give up */
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- Link pass: resolve GETNAME to GETINTRINSIC or GETENV ---- */
|
/* ---- Link pass: resolve GETNAME to GETINTRINSIC or GETENV ---- */
|
||||||
|
|
||||||
static void mach_link_code(JSContext *ctx, JSCodeRegister *code, JSValue env) {
|
static void mach_link_code(JSContext *ctx, JSCodeRegister *code, JSValue env) {
|
||||||
@@ -2560,7 +2591,12 @@ vm_dispatch:
|
|||||||
/* A=frame_slot, B=func_reg, C=argc */
|
/* A=frame_slot, B=func_reg, C=argc */
|
||||||
JSValue func_val = frame->slots[b];
|
JSValue func_val = frame->slots[b];
|
||||||
if (!mist_is_function(func_val)) {
|
if (!mist_is_function(func_val)) {
|
||||||
JS_RaiseDisrupt(ctx, "not a function");
|
char nbuf[KEY_GET_STR_BUF_SIZE];
|
||||||
|
const char *name = mach_callee_name(ctx, code, pc, b, nbuf, sizeof(nbuf));
|
||||||
|
if (name)
|
||||||
|
JS_RaiseDisrupt(ctx, "%s is not a function", name);
|
||||||
|
else
|
||||||
|
JS_RaiseDisrupt(ctx, "not a function");
|
||||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||||
goto disrupt;
|
goto disrupt;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user