/* Error in context of caller. */ LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) { TValue *frame = L->base-1; TValue *pframe = NULL; if (frame_islua(frame)) { pframe = frame_prevl(frame); } else if (frame_iscont(frame)) { #if LJ_HASFFI if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) { pframe = frame; frame = NULL; } else #endif { pframe = frame_prevd(frame); #if LJ_HASFFI /* Remove frame for FFI metamethods. */ if (frame_func(frame)->c.ffid >= FF_ffi_meta___index && frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) { L->base = pframe+1; L->top = frame; setcframe_pc(cframe_raw(L->cframe), frame_contpc(frame)); } #endif } } lj_debug_addloc(L, msg, pframe, frame); lj_err_run(L); }
/* Add frame links at the end of the snapshot. */ static BCReg snapshot_framelinks(jit_State *J, SnapEntry *map) { cTValue *frame = J->L->base - 1; cTValue *lim = J->L->base - J->baseslot; GCfunc *fn = frame_func(frame); cTValue *ftop = isluafunc(fn) ? (frame+funcproto(fn)->framesize) : J->L->top; MSize f = 0; lua_assert(!LJ_FR2); /* TODO_FR2: store 64 bit PCs. */ map[f++] = SNAP_MKPC(J->pc); /* The current PC is always the first entry. */ while (frame > lim) { /* Backwards traversal of all frames above base. */ if (frame_islua(frame)) { map[f++] = SNAP_MKPC(frame_pc(frame)); frame = frame_prevl(frame); } else if (frame_iscont(frame)) { map[f++] = SNAP_MKFTSZ(frame_ftsz(frame)); map[f++] = SNAP_MKPC(frame_contpc(frame)); frame = frame_prevd(frame); } else { lua_assert(!frame_isc(frame)); map[f++] = SNAP_MKFTSZ(frame_ftsz(frame)); frame = frame_prevd(frame); continue; } if (frame + funcproto(frame_func(frame))->framesize > ftop) ftop = frame + funcproto(frame_func(frame))->framesize; } lua_assert(f == (MSize)(1 + J->framedepth)); return (BCReg)(ftop - lim); }
/* Error in context of caller. */ LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) { TValue *frame = L->base-1; TValue *pframe = NULL; if (frame_islua(frame)) { pframe = frame_prevl(frame); } else if (frame_iscont(frame)) { pframe = frame_prevd(frame); #if LJ_HASFFI /* Remove frame for FFI metamethods. */ if (frame_func(frame)->c.ffid >= FF_ffi_meta___index && frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) { L->base = pframe+1; L->top = frame; } #endif } lj_debug_addloc(L, msg, pframe, frame); lj_err_run(L); }
/* Find error function for runtime errors. Requires an extra stack traversal. */ static ptrdiff_t finderrfunc(lua_State *L) { cTValue *frame = L->base-1, *bot = tvref(L->stack)+LJ_FR2; void *cf = L->cframe; while (frame > bot && cf) { while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ if (frame >= restorestack(L, -cframe_nres(cf))) break; if (cframe_errfunc(cf) >= 0) /* Error handler not inherited (-1)? */ return cframe_errfunc(cf); cf = cframe_prev(cf); /* Else unwind cframe and continue searching. */ if (cf == NULL) return 0; } switch (frame_typep(frame)) { case FRAME_LUA: case FRAME_LUAP: frame = frame_prevl(frame); break; case FRAME_C: cf = cframe_prev(cf); /* fallthrough */ case FRAME_VARG: frame = frame_prevd(frame); break; case FRAME_CONT: if (frame_iscont_fficb(frame)) cf = cframe_prev(cf); frame = frame_prevd(frame); break; case FRAME_CP: if (cframe_canyield(cf)) return 0; if (cframe_errfunc(cf) >= 0) return cframe_errfunc(cf); frame = frame_prevd(frame); break; case FRAME_PCALL: case FRAME_PCALLH: if (frame_func(frame_prevd(frame))->c.ffid == FF_xpcall) return savestack(L, frame_prevd(frame)+1); /* xpcall's errorfunc. */ return 0; default: lua_assert(0); return 0; } } return 0; }