Move debugging/introspection functionality to lj_debug.c.

This commit is contained in:
Mike Pall 2011-06-07 21:37:24 +02:00
parent b44ccd4263
commit 585cf05dbd
13 changed files with 521 additions and 457 deletions

View File

@ -358,7 +358,7 @@ LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \
LJLIB_C= $(LJLIB_O:.o=.c) LJLIB_C= $(LJLIB_O:.o=.c)
LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \ LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \
lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o \ lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \
lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_api.o \ lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_api.o \
lj_lex.o lj_parse.o \ lj_lex.o lj_parse.o \
lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \

View File

@ -13,9 +13,9 @@ buildvm_peobj.o: buildvm_peobj.c buildvm.h lj_def.h lua.h luaconf.h \
lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_lib.h lj_alloc.h lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_lib.h lj_alloc.h
lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h \ lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \
lj_meta.h lj_state.h lj_ctype.h lj_cconv.h lj_bc.h lj_ff.h lj_ffdef.h \ lj_tab.h lj_meta.h lj_state.h lj_ctype.h lj_cconv.h lj_bc.h lj_ff.h \
lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_lib.h lj_libdef.h lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_lib.h lj_libdef.h
lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_lib.h lj_libdef.h lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_lib.h lj_libdef.h
lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
@ -30,9 +30,10 @@ lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h \ lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h \
lj_libdef.h lj_libdef.h
lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h \ lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h \
lj_obj.h lj_def.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_bc.h lj_ir.h \ lj_obj.h lj_def.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \
lj_jit.h lj_ircall.h lj_iropt.h lj_target.h lj_target_*.h \ lj_bc.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_target.h \
lj_dispatch.h lj_vm.h lj_vmevent.h lj_lib.h luajit.h lj_libdef.h lj_target_*.h lj_dispatch.h lj_vm.h lj_vmevent.h lj_lib.h luajit.h \
lj_libdef.h
lib_math.o: lib_math.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ lib_math.o: lib_math.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_libdef.h lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_libdef.h
lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
@ -47,9 +48,9 @@ lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
lj_libdef.h lj_libdef.h
lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h
lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_udata.h lj_meta.h \ lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h lj_udata.h \
lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \ lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \
lj_traceerr.h lj_vm.h lj_lex.h lj_parse.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_lex.h lj_parse.h
lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h \ lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h \
lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h lj_traceerr.h \ lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h lj_traceerr.h \
@ -83,11 +84,14 @@ lj_crecord.o: lj_crecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_ffrecord.h lj_crecord.h lj_ffrecord.h lj_crecord.h
lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h
lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_state.h lj_frame.h lj_bc.h
lj_dispatch.o: lj_dispatch.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_dispatch.o: lj_dispatch.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_err.h lj_errmsg.h lj_state.h lj_frame.h lj_bc.h lj_ff.h lj_ffdef.h \ lj_err.h lj_errmsg.h lj_debug.h lj_state.h lj_frame.h lj_bc.h lj_ff.h \
lj_jit.h lj_ir.h lj_trace.h lj_dispatch.h lj_traceerr.h lj_vm.h luajit.h lj_ffdef.h lj_jit.h lj_ir.h lj_trace.h lj_dispatch.h lj_traceerr.h \
lj_vm.h luajit.h
lj_err.o: lj_err.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_err.h \ lj_err.o: lj_err.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_err.h \
lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_state.h lj_frame.h lj_bc.h \ lj_errmsg.h lj_debug.h lj_str.h lj_func.h lj_state.h lj_frame.h lj_bc.h \
lj_ff.h lj_ffdef.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \ lj_ff.h lj_ffdef.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \
lj_traceerr.h lj_vm.h lj_traceerr.h lj_vm.h
lj_ffrecord.o: lj_ffrecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_ffrecord.o: lj_ffrecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
@ -103,8 +107,8 @@ lj_gc.o: lj_gc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h \ lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h \
lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h
lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_gc.h lj_err.h lj_errmsg.h lj_frame.h lj_bc.h lj_jit.h lj_ir.h \ lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_frame.h lj_bc.h lj_jit.h \
lj_dispatch.h lj_ir.h lj_dispatch.h
lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \ lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \
lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h lj_carith.h \ lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h lj_carith.h \
@ -157,10 +161,10 @@ lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_tab.o: lj_tab.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_tab.o: lj_tab.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_err.h lj_errmsg.h lj_tab.h lj_err.h lj_errmsg.h lj_tab.h
lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_frame.h lj_bc.h lj_state.h \ lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_frame.h lj_bc.h \
lj_ir.h lj_jit.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h \ lj_state.h lj_ir.h lj_jit.h lj_iropt.h lj_mcode.h lj_trace.h \
lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h lj_vm.h \ lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \
lj_vmevent.h lj_target.h lj_target_*.h lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h
lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_gc.h lj_udata.h lj_gc.h lj_udata.h
lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
@ -172,18 +176,19 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h \ lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h \
lj_udata.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h \ lj_udata.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h \
lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_err.c \ lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_err.c \
lj_ff.h lj_ffdef.h lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c \ lj_debug.h lj_ff.h lj_ffdef.h lj_char.c lj_char.h lj_bc.c lj_bcdef.h \
lj_str.c lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_state.c lj_lex.h \ lj_obj.c lj_str.c lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_debug.c \
lj_alloc.h lj_dispatch.c luajit.h lj_vmevent.c lj_vmevent.h lj_vmmath.c \ lj_state.c lj_lex.h lj_alloc.h lj_dispatch.c luajit.h lj_vmevent.c \
lj_api.c lj_parse.h lj_lex.c lualib.h lj_parse.c lj_ctype.c lj_cdata.c \ lj_vmevent.h lj_vmmath.c lj_api.c lj_parse.h lj_lex.c lualib.h \
lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_carith.c lj_carith.h \ lj_parse.c lj_ctype.c lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c \
lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_lib.h lj_ir.c \ lj_ccall.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h lj_cparse.c \
lj_ircall.h lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h \ lj_cparse.h lj_lib.c lj_lib.h lj_ir.c lj_ircall.h lj_iropt.h \
lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c \ lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \
lj_mcode.c lj_mcode.h lj_snap.c lj_target.h lj_target_*.h lj_record.c \ lj_opt_loop.c lj_snap.h lj_opt_split.c lj_mcode.c lj_mcode.h lj_snap.c \
lj_record.h lj_ffrecord.h lj_crecord.c lj_crecord.h lj_ffrecord.c \ lj_target.h lj_target_*.h lj_record.c lj_record.h lj_ffrecord.h \
lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h lj_asm_*.h lj_trace.c \ lj_crecord.c lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h \
lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c lj_libdef.h \ lj_emit_*.h lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c \
lib_math.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c \ lib_aux.c lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c \
lib_debug.c lib_bit.c lib_jit.c lib_ffi.c lib_init.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c \
lib_ffi.c lib_init.c
luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h

View File

@ -18,6 +18,7 @@
#include "lj_obj.h" #include "lj_obj.h"
#include "lj_gc.h" #include "lj_gc.h"
#include "lj_err.h" #include "lj_err.h"
#include "lj_debug.h"
#include "lj_str.h" #include "lj_str.h"
#include "lj_tab.h" #include "lj_tab.h"
#include "lj_meta.h" #include "lj_meta.h"
@ -89,7 +90,7 @@ LJLIB_CF(getfenv)
cTValue *o = L->base; cTValue *o = L->base;
if (!(o < L->top && tvisfunc(o))) { if (!(o < L->top && tvisfunc(o))) {
int level = lj_lib_optint(L, 1, 1); int level = lj_lib_optint(L, 1, 1);
o = lj_err_getframe(L, level, &level); o = lj_debug_frame(L, level, &level);
if (o == NULL) if (o == NULL)
lj_err_arg(L, 1, LJ_ERR_INVLVL); lj_err_arg(L, 1, LJ_ERR_INVLVL);
} }
@ -110,7 +111,7 @@ LJLIB_CF(setfenv)
setgcref(L->env, obj2gco(t)); setgcref(L->env, obj2gco(t));
return 0; return 0;
} }
o = lj_err_getframe(L, level, &level); o = lj_debug_frame(L, level, &level);
if (o == NULL) if (o == NULL)
lj_err_arg(L, 1, LJ_ERR_INVLVL); lj_err_arg(L, 1, LJ_ERR_INVLVL);
} }

View File

@ -13,6 +13,7 @@
#include "lj_arch.h" #include "lj_arch.h"
#include "lj_obj.h" #include "lj_obj.h"
#include "lj_err.h" #include "lj_err.h"
#include "lj_debug.h"
#include "lj_str.h" #include "lj_str.h"
#include "lj_tab.h" #include "lj_tab.h"
#include "lj_bc.h" #include "lj_bc.h"
@ -189,13 +190,12 @@ LJLIB_CF(jit_util_funcinfo)
setintfield(L, t, "nconsts", (int32_t)pt->sizekn); setintfield(L, t, "nconsts", (int32_t)pt->sizekn);
setintfield(L, t, "upvalues", (int32_t)pt->sizeuv); setintfield(L, t, "upvalues", (int32_t)pt->sizeuv);
if (pc < pt->sizebc) if (pc < pt->sizebc)
setintfield(L, t, "currentline", setintfield(L, t, "currentline", lj_debug_line(pt, pc));
proto_lineinfo(pt) ? proto_line(pt, pc) : 0);
lua_pushboolean(L, (pt->flags & PROTO_IS_VARARG)); lua_pushboolean(L, (pt->flags & PROTO_IS_VARARG));
lua_setfield(L, -2, "isvararg"); lua_setfield(L, -2, "isvararg");
setstrV(L, L->top++, proto_chunkname(pt)); setstrV(L, L->top++, proto_chunkname(pt));
lua_setfield(L, -2, "source"); lua_setfield(L, -2, "source");
lj_err_pushloc(L, pt, pc); lj_debug_pushloc(L, pt, pc);
lua_setfield(L, -2, "loc"); lua_setfield(L, -2, "loc");
} else { } else {
GCfunc *fn = funcV(L->base); GCfunc *fn = funcV(L->base);

View File

@ -12,6 +12,7 @@
#include "lj_obj.h" #include "lj_obj.h"
#include "lj_gc.h" #include "lj_gc.h"
#include "lj_err.h" #include "lj_err.h"
#include "lj_debug.h"
#include "lj_str.h" #include "lj_str.h"
#include "lj_tab.h" #include "lj_tab.h"
#include "lj_func.h" #include "lj_func.h"
@ -832,30 +833,10 @@ LUA_API int lua_next(lua_State *L, int idx)
return more; return more;
} }
static const char *aux_upvalue(cTValue *f, uint32_t idx, TValue **val)
{
GCfunc *fn;
if (!tvisfunc(f)) return NULL;
fn = funcV(f);
if (isluafunc(fn)) {
GCproto *pt = funcproto(fn);
if (idx < pt->sizeuv) {
*val = uvval(&gcref(fn->l.uvptr[idx])->uv);
return strdata(proto_uvname(pt, idx));
}
} else {
if (idx < fn->c.nupvalues) {
*val = &fn->c.upvalue[idx];
return "";
}
}
return NULL;
}
LUA_API const char *lua_getupvalue(lua_State *L, int idx, int n) LUA_API const char *lua_getupvalue(lua_State *L, int idx, int n)
{ {
TValue *val; TValue *val;
const char *name = aux_upvalue(index2adr(L, idx), (uint32_t)(n-1), &val); const char *name = lj_debug_uvname(index2adr(L, idx), (uint32_t)(n-1), &val);
if (name) { if (name) {
copyTV(L, L->top, val); copyTV(L, L->top, val);
incr_top(L); incr_top(L);
@ -1010,7 +991,7 @@ LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n)
TValue *val; TValue *val;
const char *name; const char *name;
api_checknelems(L, 1); api_checknelems(L, 1);
name = aux_upvalue(f, (uint32_t)(n-1), &val); name = lj_debug_uvname(f, (uint32_t)(n-1), &val);
if (name) { if (name) {
L->top--; L->top--;
copyTV(L, val, L->top); copyTV(L, val, L->top);

429
src/lj_debug.c Normal file
View File

@ -0,0 +1,429 @@
/*
** Debugging and introspection.
** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
*/
#define lj_debug_c
#define LUA_CORE
#include "lj_obj.h"
#include "lj_err.h"
#include "lj_str.h"
#include "lj_tab.h"
#include "lj_state.h"
#include "lj_frame.h"
#include "lj_bc.h"
/* -- Frames -------------------------------------------------------------- */
/* Get frame corresponding to a level. */
cTValue *lj_debug_frame(lua_State *L, int level, int *size)
{
cTValue *frame, *nextframe, *bot = tvref(L->stack);
/* Traverse frames backwards. */
for (nextframe = frame = L->base-1; frame > bot; ) {
if (frame_gc(frame) == obj2gco(L))
level++; /* Skip dummy frames. See lj_meta_call(). */
if (level-- == 0) {
*size = (int)(nextframe - frame);
return frame; /* Level found. */
}
nextframe = frame;
if (frame_islua(frame)) {
frame = frame_prevl(frame);
} else {
if (frame_isvarg(frame))
level++; /* Skip vararg pseudo-frame. */
frame = frame_prevd(frame);
}
}
*size = level;
return NULL; /* Level not found. */
}
/* Invalid bytecode position. */
#define NO_BCPOS (~(BCPos)0)
/* Return bytecode position for function/frame or NO_BCPOS. */
static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
{
const BCIns *ins;
lua_assert(fn->c.gct == ~LJ_TFUNC || fn->c.gct == ~LJ_TTHREAD);
if (!isluafunc(fn)) { /* Cannot derive a PC for non-Lua functions. */
return NO_BCPOS;
} else if (nextframe == NULL) { /* Lua function on top. */
void *cf = cframe_raw(L->cframe);
if (cf == NULL || (char *)cframe_pc(cf) == (char *)cframe_L(cf))
return NO_BCPOS;
ins = cframe_pc(cf); /* Only happens during error/hook handling. */
} else {
if (frame_islua(nextframe)) {
ins = frame_pc(nextframe);
} else if (frame_iscont(nextframe)) {
ins = frame_contpc(nextframe);
} else {
/* Lua function below errfunc/gc/hook: find cframe to get the PC. */
void *cf = cframe_raw(L->cframe);
TValue *f = L->base-1;
if (cf == NULL)
return NO_BCPOS;
while (f > nextframe) {
if (frame_islua(f)) {
f = frame_prevl(f);
} else {
if (frame_isc(f))
cf = cframe_raw(cframe_prev(cf));
f = frame_prevd(f);
}
}
if (cframe_prev(cf))
cf = cframe_raw(cframe_prev(cf));
ins = cframe_pc(cf);
}
}
return proto_bcpos(funcproto(fn), ins) - 1;
}
/* -- Line numbers -------------------------------------------------------- */
/* Get line number for a bytecode position. */
BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc)
{
BCLine *lineinfo = proto_lineinfo(pt);
if (pc < pt->sizebc && lineinfo)
return lineinfo[pc];
return 0;
}
/* Get line number for function/frame. */
static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
{
BCPos pc = debug_framepc(L, fn, nextframe);
if (pc != NO_BCPOS) {
GCproto *pt = funcproto(fn);
lua_assert(pc < pt->sizebc);
return lj_debug_line(pt, pc);
}
return -1;
}
/* -- Variable names ------------------------------------------------------ */
/* Get name of a local variable from slot number and PC. */
static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
{
MSize i;
VarInfo *vi = proto_varinfo(pt);
for (i = 0; i < pt->sizevarinfo && vi[i].startpc <= pc; i++)
if (pc < vi[i].endpc && slot-- == 0)
return strdata(gco2str(gcref(vi[i].name)));
return NULL;
}
/* Get name of local variable from 1-based slot number and function/frame. */
static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
const char **name, BCReg slot1)
{
uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
uint32_t size = (uint32_t)ar->i_ci >> 16;
TValue *frame = tvref(L->stack) + offset;
TValue *nextframe = size ? frame + size : NULL;
GCfunc *fn = frame_func(frame);
BCPos pc = debug_framepc(L, fn, nextframe);
if (pc != NO_BCPOS &&
(*name = debug_varname(funcproto(fn), pc, slot1-1)) != NULL)
;
else if (slot1 > 0 && frame + slot1 < (nextframe ? nextframe : L->top))
*name = "(*temporary)";
else
*name = NULL;
return frame+slot1;
}
/* Get name of upvalue. */
const char *lj_debug_uvname(cTValue *o, uint32_t idx, TValue **tvp)
{
if (tvisfunc(o)) {
GCfunc *fn = funcV(o);
if (isluafunc(fn)) {
GCproto *pt = funcproto(fn);
if (idx < pt->sizeuv) {
*tvp = uvval(&gcref(fn->l.uvptr[idx])->uv);
return strdata(proto_uvname(pt, idx));
}
} else {
if (idx < fn->c.nupvalues) {
*tvp = &fn->c.upvalue[idx];
return "";
}
}
}
return NULL;
}
/* Deduce name of an object from slot number and PC. */
const char *lj_debug_slotname(GCproto *pt, const BCIns *ip, BCReg slot,
const char **name)
{
const char *lname;
restart:
lname = debug_varname(pt, proto_bcpos(pt, ip), slot);
if (lname != NULL) { *name = lname; return "local"; }
while (--ip > proto_bc(pt)) {
BCIns ins = *ip;
BCOp op = bc_op(ins);
BCReg ra = bc_a(ins);
if (bcmode_a(op) == BCMbase) {
if (slot >= ra && (op != BC_KNIL || slot <= bc_d(ins)))
return NULL;
} else if (bcmode_a(op) == BCMdst && ra == slot) {
switch (bc_op(ins)) {
case BC_MOV:
if (ra == slot) { slot = bc_d(ins); goto restart; }
break;
case BC_GGET:
*name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_d(ins))));
return "global";
case BC_TGETS:
*name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins))));
if (ip > proto_bc(pt)) {
BCIns insp = ip[-1];
if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1 &&
bc_d(insp) == bc_b(ins))
return "method";
}
return "field";
case BC_UGET:
*name = strdata(proto_uvname(pt, bc_d(ins)));
return "upvalue";
default:
return NULL;
}
}
}
return NULL;
}
/* Deduce function name from caller of a frame. */
const char *lj_debug_funcname(lua_State *L, TValue *frame, const char **name)
{
TValue *pframe;
GCfunc *fn;
BCPos pc;
if (frame_isvarg(frame))
frame = frame_prevd(frame);
pframe = frame_prev(frame);
fn = frame_func(pframe);
pc = debug_framepc(L, fn, frame);
if (pc != NO_BCPOS) {
GCproto *pt = funcproto(fn);
const BCIns *ip = &proto_bc(pt)[check_exp(pc < pt->sizebc, pc)];
MMS mm = bcmode_mm(bc_op(*ip));
if (mm == MM_call) {
BCReg slot = bc_a(*ip);
if (bc_op(*ip) == BC_ITERC) slot -= 3;
return lj_debug_slotname(pt, ip, slot, name);
} else if (mm != MM__MAX) {
*name = strdata(mmname_str(G(L), mm));
return "metamethod";
}
}
return NULL;
}
/* -- Source code locations ----------------------------------------------- */
/* Generate shortened source name. */
void lj_debug_shortname(char *out, const char *src)
{
if (*src == '=') {
strncpy(out, src+1, LUA_IDSIZE); /* remove first char */
out[LUA_IDSIZE-1] = '\0'; /* ensures null termination */
} else if (*src == '@') { /* out = "source", or "...source" */
size_t l = strlen(++src); /* skip the `@' */
if (l >= LUA_IDSIZE) {
src += l-(LUA_IDSIZE-4); /* get last part of file name */
strcpy(out, "...");
out += 3;
}
strcpy(out, src);
} else { /* out = [string "string"] */
size_t len; /* Length, up to first control char. */
for (len = 0; len < LUA_IDSIZE-12; len++)
if (((const unsigned char *)src)[len] < ' ') break;
strcpy(out, "[string \""); out += 9;
if (src[len] != '\0') { /* must truncate? */
if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15;
strncpy(out, src, len); out += len;
strcpy(out, "..."); out += 3;
} else {
strcpy(out, src); out += len;
}
strcpy(out, "\"]");
}
}
/* Add current location of a frame to error message. */
void lj_debug_addloc(lua_State *L, const char *msg,
cTValue *frame, cTValue *nextframe)
{
if (frame) {
GCfunc *fn = frame_func(frame);
if (isluafunc(fn)) {
BCLine line = debug_frameline(L, fn, nextframe);
if (line >= 0) {
char buf[LUA_IDSIZE];
lj_debug_shortname(buf, strdata(proto_chunkname(funcproto(fn))));
lj_str_pushf(L, "%s:%d: %s", buf, line, msg);
return;
}
}
}
lj_str_pushf(L, "%s", msg);
}
/* Push location string for a bytecode position to Lua stack. */
void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc)
{
GCstr *name = proto_chunkname(pt);
if (name) {
const char *s = strdata(name);
MSize i, len = name->len;
BCLine line = lj_debug_line(pt, pc);
if (*s == '@') {
s++; len--;
for (i = len; i > 0; i--)
if (s[i] == '/' || s[i] == '\\') {
s += i+1;
break;
}
lj_str_pushf(L, "%s:%d", s, line);
} else if (len > 40) {
lj_str_pushf(L, "%p:%d", pt, line);
} else if (*s == '=') {
lj_str_pushf(L, "%s:%d", s+1, line);
} else {
lj_str_pushf(L, "\"%s\":%d", s, line);
}
} else {
lj_str_pushf(L, "%p:%u", pt, pc);
}
}
/* -- Public debug API ---------------------------------------------------- */
/* lua_getupvalue() and lua_setupvalue() are in lj_api.c. */
LUA_API const char *lua_getlocal(lua_State *L, const lua_Debug *ar, int n)
{
const char *name;
TValue *o = debug_localname(L, ar, &name, (BCReg)n);
if (name) {
copyTV(L, L->top, o);
incr_top(L);
}
return name;
}
LUA_API const char *lua_setlocal(lua_State *L, const lua_Debug *ar, int n)
{
const char *name;
TValue *o = debug_localname(L, ar, &name, (BCReg)n);
if (name)
copyTV(L, o, L->top-1);
L->top--;
return name;
}
LUA_API int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar)
{
int status = 1;
TValue *frame = NULL;
TValue *nextframe = NULL;
GCfunc *fn;
if (*what == '>') {
TValue *func = L->top - 1;
api_check(L, tvisfunc(func));
fn = funcV(func);
L->top--;
what++;
} else {
uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
uint32_t size = (uint32_t)ar->i_ci >> 16;
lua_assert(offset != 0);
frame = tvref(L->stack) + offset;
if (size) nextframe = frame + size;
lua_assert(frame <= tvref(L->maxstack) &&
(!nextframe || nextframe <= tvref(L->maxstack)));
fn = frame_func(frame);
lua_assert(fn->c.gct == ~LJ_TFUNC);
}
for (; *what; what++) {
switch (*what) {
case 'S':
if (isluafunc(fn)) {
GCproto *pt = funcproto(fn);
ar->source = strdata(proto_chunkname(pt));
ar->linedefined = (int)proto_line(pt, 0);
ar->lastlinedefined = (int)pt->lastlinedefined;
ar->what = ar->linedefined ? "Lua" : "main";
} else {
ar->source = "=[C]";
ar->linedefined = -1;
ar->lastlinedefined = -1;
ar->what = "C";
}
lj_debug_shortname(ar->short_src, ar->source);
break;
case 'l':
ar->currentline = frame ? debug_frameline(L, fn, nextframe) : -1;
break;
case 'u':
ar->nups = fn->c.nupvalues;
break;
case 'n':
ar->namewhat = frame ? lj_debug_funcname(L, frame, &ar->name) : NULL;
if (ar->namewhat == NULL) {
ar->namewhat = "";
ar->name = NULL;
}
break;
case 'f':
setfuncV(L, L->top, fn);
incr_top(L);
break;
case 'L':
if (isluafunc(fn)) {
GCtab *t = lj_tab_new(L, 0, 0);
GCproto *pt = funcproto(fn);
BCLine *lineinfo = proto_lineinfo(pt);
MSize i, szl = pt->sizebc;
for (i = 1; i < szl; i++)
setboolV(lj_tab_setint(L, t, lineinfo[i]), 1);
settabV(L, L->top, t);
} else {
setnilV(L->top);
}
incr_top(L);
break;
default:
status = 0; /* Bad option. */
break;
}
}
return status;
}
LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
{
int size;
cTValue *frame = lj_debug_frame(L, level, &size);
if (frame) {
ar->i_ci = (size << 16) + (int)(frame - tvref(L->stack));
return 1;
} else {
ar->i_ci = level - size;
return 0;
}
}

23
src/lj_debug.h Normal file
View File

@ -0,0 +1,23 @@
/*
** Debugging and introspection.
** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
*/
#ifndef _LJ_DEBUG_H
#define _LJ_DEBUG_H
#include "lj_obj.h"
LJ_FUNC cTValue *lj_debug_frame(lua_State *L, int level, int *size);
LJ_FUNC BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc);
LJ_FUNC const char *lj_debug_uvname(cTValue *o, uint32_t idx, TValue **tvp);
LJ_FUNC const char *lj_debug_slotname(GCproto *pt, const BCIns *pc,
BCReg slot, const char **name);
LJ_FUNC const char *lj_debug_funcname(lua_State *L, TValue *frame,
const char **name);
LJ_FUNC void lj_debug_shortname(char *out, const char *src);
LJ_FUNC void lj_debug_addloc(lua_State *L, const char *msg,
cTValue *frame, cTValue *nextframe);
LJ_FUNC void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc);
#endif

View File

@ -8,6 +8,7 @@
#include "lj_obj.h" #include "lj_obj.h"
#include "lj_err.h" #include "lj_err.h"
#include "lj_debug.h"
#include "lj_state.h" #include "lj_state.h"
#include "lj_frame.h" #include "lj_frame.h"
#include "lj_bc.h" #include "lj_bc.h"
@ -380,8 +381,8 @@ void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc)
if ((g->hookmask & LUA_MASKLINE)) { if ((g->hookmask & LUA_MASKLINE)) {
BCPos npc = proto_bcpos(pt, pc) - 1; BCPos npc = proto_bcpos(pt, pc) - 1;
BCPos opc = proto_bcpos(pt, oldpc) - 1; BCPos opc = proto_bcpos(pt, oldpc) - 1;
BCLine line = proto_line(pt, npc); BCLine line = lj_debug_line(pt, npc);
if (pc <= oldpc || opc >= pt->sizebc || line != proto_line(pt, opc)) { if (pc <= oldpc || opc >= pt->sizebc || line != lj_debug_line(pt, opc)) {
callhook(L, LUA_HOOKLINE, line); callhook(L, LUA_HOOKLINE, line);
L->top = L->base + slots; /* Fix top again. */ L->top = L->base + slots; /* Fix top again. */
} }

View File

@ -1,9 +1,6 @@
/* /*
** Error handling and debugging API. ** Error handling.
** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
**
** Portions taken verbatim or adapted from the Lua interpreter.
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
*/ */
#define lj_err_c #define lj_err_c
@ -11,12 +8,11 @@
#include "lj_obj.h" #include "lj_obj.h"
#include "lj_err.h" #include "lj_err.h"
#include "lj_debug.h"
#include "lj_str.h" #include "lj_str.h"
#include "lj_tab.h"
#include "lj_func.h" #include "lj_func.h"
#include "lj_state.h" #include "lj_state.h"
#include "lj_frame.h" #include "lj_frame.h"
#include "lj_bc.h"
#include "lj_ff.h" #include "lj_ff.h"
#include "lj_trace.h" #include "lj_trace.h"
#include "lj_vm.h" #include "lj_vm.h"
@ -78,355 +74,6 @@ LJ_DATADEF const char *lj_err_allmsg =
#include "lj_errmsg.h" #include "lj_errmsg.h"
; ;
/* -- Frame and function introspection ------------------------------------ */
static BCPos currentpc(lua_State *L, GCfunc *fn, cTValue *nextframe)
{
const BCIns *ins;
lua_assert(fn->c.gct == ~LJ_TFUNC || fn->c.gct == ~LJ_TTHREAD);
if (!isluafunc(fn)) { /* Cannot derive a PC for non-Lua functions. */
return ~(BCPos)0;
} else if (nextframe == NULL) { /* Lua function on top. */
void *cf = cframe_raw(L->cframe);
if (cf == NULL || (char *)cframe_pc(cf) == (char *)cframe_L(cf))
return ~(BCPos)0;
ins = cframe_pc(cf); /* Only happens during error/hook handling. */
} else {
if (frame_islua(nextframe)) {
ins = frame_pc(nextframe);
} else if (frame_iscont(nextframe)) {
ins = frame_contpc(nextframe);
} else {
/* Lua function below errfunc/gc/hook: find cframe to get the PC. */
void *cf = cframe_raw(L->cframe);
TValue *f = L->base-1;
if (cf == NULL)
return ~(BCPos)0;
while (f > nextframe) {
if (frame_islua(f)) {
f = frame_prevl(f);
} else {
if (frame_isc(f))
cf = cframe_raw(cframe_prev(cf));
f = frame_prevd(f);
}
}
if (cframe_prev(cf))
cf = cframe_raw(cframe_prev(cf));
ins = cframe_pc(cf);
}
}
return proto_bcpos(funcproto(fn), ins) - 1;
}
static BCLine currentline(lua_State *L, GCfunc *fn, cTValue *nextframe)
{
BCPos pc = currentpc(L, fn, nextframe);
if (pc != ~(BCPos)0) {
GCproto *pt = funcproto(fn);
lua_assert(pc < pt->sizebc);
return proto_line(pt, pc);
} else {
return -1;
}
}
static const char *getvarname(const GCproto *pt, BCPos pc, BCReg slot)
{
MSize i;
VarInfo *vi = proto_varinfo(pt);
for (i = 0; i < pt->sizevarinfo && vi[i].startpc <= pc; i++)
if (pc < vi[i].endpc && slot-- == 0)
return strdata(gco2str(gcref(vi[i].name)));
return NULL;
}
static const char *getobjname(GCproto *pt, const BCIns *ip, BCReg slot,
const char **name)
{
const char *lname;
restart:
lname = getvarname(pt, proto_bcpos(pt, ip), slot);
if (lname != NULL) { *name = lname; return "local"; }
while (--ip > proto_bc(pt)) {
BCIns ins = *ip;
BCOp op = bc_op(ins);
BCReg ra = bc_a(ins);
if (bcmode_a(op) == BCMbase) {
if (slot >= ra && (op != BC_KNIL || slot <= bc_d(ins)))
return NULL;
} else if (bcmode_a(op) == BCMdst && ra == slot) {
switch (bc_op(ins)) {
case BC_MOV:
if (ra == slot) { slot = bc_d(ins); goto restart; }
break;
case BC_GGET:
*name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_d(ins))));
return "global";
case BC_TGETS:
*name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins))));
if (ip > proto_bc(pt)) {
BCIns insp = ip[-1];
if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1 &&
bc_d(insp) == bc_b(ins))
return "method";
}
return "field";
case BC_UGET:
*name = strdata(proto_uvname(pt, bc_d(ins)));
return "upvalue";
default:
return NULL;
}
}
}
return NULL;
}
static const char *getfuncname(lua_State *L, TValue *frame, const char **name)
{
MMS mm;
const BCIns *ip;
TValue *pframe;
GCfunc *fn;
BCPos pc;
if (frame_isvarg(frame))
frame = frame_prevd(frame);
pframe = frame_prev(frame);
fn = frame_func(pframe);
pc = currentpc(L, fn, frame);
if (pc == ~(BCPos)0)
return NULL;
lua_assert(pc < funcproto(fn)->sizebc);
ip = &proto_bc(funcproto(fn))[pc];
mm = bcmode_mm(bc_op(*ip));
if (mm == MM_call) {
BCReg slot = bc_a(*ip);
if (bc_op(*ip) == BC_ITERC) slot -= 3;
return getobjname(funcproto(fn), ip, slot, name);
} else if (mm != MM__MAX) {
*name = strdata(mmname_str(G(L), mm));
return "metamethod";
} else {
return NULL;
}
}
void lj_err_pushloc(lua_State *L, GCproto *pt, BCPos pc)
{
GCstr *name = proto_chunkname(pt);
if (name) {
const char *s = strdata(name);
MSize i, len = name->len;
BCLine line = pc < pt->sizebc ? proto_line(pt, pc) : 0;
if (*s == '@') {
s++; len--;
for (i = len; i > 0; i--)
if (s[i] == '/' || s[i] == '\\') {
s += i+1;
break;
}
lj_str_pushf(L, "%s:%d", s, line);
} else if (len > 40) {
lj_str_pushf(L, "%p:%d", pt, line);
} else if (*s == '=') {
lj_str_pushf(L, "%s:%d", s+1, line);
} else {
lj_str_pushf(L, "\"%s\":%d", s, line);
}
} else {
lj_str_pushf(L, "%p:%u", pt, pc);
}
}
static void err_chunkid(char *out, const char *src)
{
if (*src == '=') {
strncpy(out, src+1, LUA_IDSIZE); /* remove first char */
out[LUA_IDSIZE-1] = '\0'; /* ensures null termination */
} else if (*src == '@') { /* out = "source", or "...source" */
size_t l = strlen(++src); /* skip the `@' */
if (l >= LUA_IDSIZE) {
src += l-(LUA_IDSIZE-4); /* get last part of file name */
strcpy(out, "...");
out += 3;
}
strcpy(out, src);
} else { /* out = [string "string"] */
size_t len; /* Length, up to first control char. */
for (len = 0; len < LUA_IDSIZE-12; len++)
if (((const unsigned char *)src)[len] < ' ') break;
strcpy(out, "[string \""); out += 9;
if (src[len] != '\0') { /* must truncate? */
if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15;
strncpy(out, src, len); out += len;
strcpy(out, "..."); out += 3;
} else {
strcpy(out, src); out += len;
}
strcpy(out, "\"]");
}
}
/* -- Public debug API ---------------------------------------------------- */
static TValue *findlocal(lua_State *L, const lua_Debug *ar,
const char **name, BCReg slot)
{
uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
uint32_t size = (uint32_t)ar->i_ci >> 16;
TValue *frame = tvref(L->stack) + offset;
TValue *nextframe = size ? frame + size : NULL;
GCfunc *fn = frame_func(frame);
BCPos pc = currentpc(L, fn, nextframe);
if (pc != ~(BCPos)0 &&
(*name = getvarname(funcproto(fn), pc, slot-1)) != NULL)
;
else if (slot > 0 && frame + slot < (nextframe ? nextframe : L->top))
*name = "(*temporary)";
else
*name = NULL;
return frame+slot;
}
LUA_API const char *lua_getlocal(lua_State *L, const lua_Debug *ar, int n)
{
const char *name;
TValue *o = findlocal(L, ar, &name, (BCReg)n);
if (name) {
copyTV(L, L->top, o);
incr_top(L);
}
return name;
}
LUA_API const char *lua_setlocal(lua_State *L, const lua_Debug *ar, int n)
{
const char *name;
TValue *o = findlocal(L, ar, &name, (BCReg)n);
if (name)
copyTV(L, o, L->top-1);
L->top--;
return name;
}
LUA_API int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar)
{
int status = 1;
TValue *frame = NULL;
TValue *nextframe = NULL;
GCfunc *fn;
if (*what == '>') {
TValue *func = L->top - 1;
api_check(L, tvisfunc(func));
fn = funcV(func);
L->top--;
what++;
} else {
uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
uint32_t size = (uint32_t)ar->i_ci >> 16;
lua_assert(offset != 0);
frame = tvref(L->stack) + offset;
if (size) nextframe = frame + size;
lua_assert(frame <= tvref(L->maxstack) &&
(!nextframe || nextframe <= tvref(L->maxstack)));
fn = frame_func(frame);
lua_assert(fn->c.gct == ~LJ_TFUNC);
}
for (; *what; what++) {
switch (*what) {
case 'S':
if (isluafunc(fn)) {
GCproto *pt = funcproto(fn);
ar->source = strdata(proto_chunkname(pt));
ar->linedefined = (int)proto_line(pt, 0);
ar->lastlinedefined = (int)pt->lastlinedefined;
ar->what = (ar->linedefined == 0) ? "main" : "Lua";
} else {
ar->source = "=[C]";
ar->linedefined = -1;
ar->lastlinedefined = -1;
ar->what = "C";
}
err_chunkid(ar->short_src, ar->source);
break;
case 'l':
ar->currentline = frame ? currentline(L, fn, nextframe) : -1;
break;
case 'u':
ar->nups = fn->c.nupvalues;
break;
case 'n':
ar->namewhat = frame ? getfuncname(L, frame, &ar->name) : NULL;
if (ar->namewhat == NULL) {
ar->namewhat = "";
ar->name = NULL;
}
break;
case 'f':
setfuncV(L, L->top, fn);
incr_top(L);
break;
case 'L':
if (isluafunc(fn)) {
GCtab *t = lj_tab_new(L, 0, 0);
GCproto *pt = funcproto(fn);
BCLine *lineinfo = proto_lineinfo(pt);
MSize i, szl = pt->sizebc;
for (i = 1; i < szl; i++)
setboolV(lj_tab_setint(L, t, lineinfo[i]), 1);
settabV(L, L->top, t);
} else {
setnilV(L->top);
}
incr_top(L);
break;
default:
status = 0; /* Bad option. */
break;
}
}
return status;
}
cTValue *lj_err_getframe(lua_State *L, int level, int *size)
{
cTValue *frame, *nextframe, *bot = tvref(L->stack);
/* Traverse frames backwards. */
for (nextframe = frame = L->base-1; frame > bot; ) {
if (frame_gc(frame) == obj2gco(L))
level++; /* Skip dummy frames. See lj_meta_call(). */
if (level-- == 0) {
*size = (int)(nextframe - frame);
return frame; /* Level found. */
}
nextframe = frame;
if (frame_islua(frame)) {
frame = frame_prevl(frame);
} else {
if (frame_isvarg(frame))
level++; /* Skip vararg pseudo-frame. */
frame = frame_prevd(frame);
}
}
*size = level;
return NULL; /* Level not found. */
}
LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
{
int size;
cTValue *frame = lj_err_getframe(L, level, &size);
if (frame) {
ar->i_ci = (size << 16) + (int)(frame - tvref(L->stack));
return 1;
} else {
ar->i_ci = level - size;
return 0;
}
}
/* -- Internal frame unwinding -------------------------------------------- */ /* -- Internal frame unwinding -------------------------------------------- */
/* Unwind Lua stack and move error message to new top. */ /* Unwind Lua stack and move error message to new top. */
@ -854,25 +501,6 @@ LJ_NOINLINE void lj_err_run(lua_State *L)
lj_err_throw(L, LUA_ERRRUN); lj_err_throw(L, LUA_ERRRUN);
} }
/* Add location to error message. */
LJ_NOINLINE static void err_loc(lua_State *L, const char *msg,
cTValue *frame, cTValue *nextframe)
{
if (frame) {
GCfunc *fn = frame_func(frame);
if (isluafunc(fn)) {
char buff[LUA_IDSIZE];
BCLine line = currentline(L, fn, nextframe);
if (line >= 0) {
err_chunkid(buff, strdata(proto_chunkname(funcproto(fn))));
lj_str_pushf(L, "%s:%d: %s", buff, line, msg);
return;
}
}
}
lj_str_pushf(L, "%s", msg);
}
/* Formatted runtime error message. */ /* Formatted runtime error message. */
LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...)
{ {
@ -882,7 +510,7 @@ LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...)
if (curr_funcisL(L)) L->top = curr_topL(L); if (curr_funcisL(L)) L->top = curr_topL(L);
msg = lj_str_pushvf(L, err2msg(em), argp); msg = lj_str_pushvf(L, err2msg(em), argp);
va_end(argp); va_end(argp);
err_loc(L, msg, L->base-1, NULL); lj_debug_addloc(L, msg, L->base-1, NULL);
lj_err_run(L); lj_err_run(L);
} }
@ -898,7 +526,7 @@ LJ_NOINLINE void lj_err_lex(lua_State *L, const char *src, const char *tok,
{ {
char buff[LUA_IDSIZE]; char buff[LUA_IDSIZE];
const char *msg; const char *msg;
err_chunkid(buff, src); lj_debug_shortname(buff, src);
msg = lj_str_pushvf(L, err2msg(em), argp); msg = lj_str_pushvf(L, err2msg(em), argp);
msg = lj_str_pushf(L, "%s:%d: %s", buff, line, msg); msg = lj_str_pushf(L, "%s:%d: %s", buff, line, msg);
if (tok) if (tok)
@ -910,12 +538,12 @@ LJ_NOINLINE void lj_err_lex(lua_State *L, const char *src, const char *tok,
LJ_NOINLINE void lj_err_optype(lua_State *L, cTValue *o, ErrMsg opm) LJ_NOINLINE void lj_err_optype(lua_State *L, cTValue *o, ErrMsg opm)
{ {
const char *tname = typename(o); const char *tname = typename(o);
const char *oname = NULL;
const char *opname = err2msg(opm); const char *opname = err2msg(opm);
if (curr_funcisL(L)) { if (curr_funcisL(L)) {
GCproto *pt = curr_proto(L); GCproto *pt = curr_proto(L);
const BCIns *pc = cframe_Lpc(L) - 1; const BCIns *pc = cframe_Lpc(L) - 1;
const char *kind = getobjname(pt, pc, (BCReg)(o - L->base), &oname); const char *oname = NULL;
const char *kind = lj_debug_slotname(pt, pc, (BCReg)(o-L->base), &oname);
if (kind) if (kind)
err_msgv(L, LJ_ERR_BADOPRT, opname, kind, oname, tname); err_msgv(L, LJ_ERR_BADOPRT, opname, kind, oname, tname);
} }
@ -967,7 +595,7 @@ LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg)
} }
#endif #endif
} }
err_loc(L, msg, pframe, frame); lj_debug_addloc(L, msg, pframe, frame);
lj_err_run(L); lj_err_run(L);
} }
@ -993,7 +621,7 @@ LJ_NORET LJ_NOINLINE static void err_argmsg(lua_State *L, int narg,
const char *msg) const char *msg)
{ {
const char *fname = "?"; const char *fname = "?";
const char *ftype = getfuncname(L, L->base - 1, &fname); const char *ftype = lj_debug_funcname(L, L->base - 1, &fname);
if (narg < 0 && narg > LUA_REGISTRYINDEX) if (narg < 0 && narg > LUA_REGISTRYINDEX)
narg = (int)(L->top - L->base) + narg + 1; narg = (int)(L->top - L->base) + narg + 1;
if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */
@ -1066,8 +694,8 @@ LUALIB_API int luaL_typerror(lua_State *L, int narg, const char *xname)
LUALIB_API void luaL_where(lua_State *L, int level) LUALIB_API void luaL_where(lua_State *L, int level)
{ {
int size; int size;
cTValue *frame = lj_err_getframe(L, level, &size); cTValue *frame = lj_debug_frame(L, level, &size);
err_loc(L, "", frame, size ? frame+size : NULL); lj_debug_addloc(L, "", frame, size ? frame+size : NULL);
} }
LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...) LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...)

View File

@ -1,5 +1,5 @@
/* /*
** Error handling and debugging support. ** Error handling.
** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
*/ */
@ -38,7 +38,4 @@ LJ_FUNC_NORET void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...);
LJ_FUNC_NORET void lj_err_argtype(lua_State *L, int narg, const char *xname); LJ_FUNC_NORET void lj_err_argtype(lua_State *L, int narg, const char *xname);
LJ_FUNC_NORET void lj_err_argt(lua_State *L, int narg, int tt); LJ_FUNC_NORET void lj_err_argt(lua_State *L, int narg, int tt);
LJ_FUNC void lj_err_pushloc(lua_State *L, GCproto *pt, BCPos pc);
LJ_FUNC cTValue *lj_err_getframe(lua_State *L, int level, int *size);
#endif #endif

View File

@ -12,6 +12,7 @@
#include "lj_gc.h" #include "lj_gc.h"
#include "lj_err.h" #include "lj_err.h"
#include "lj_debug.h"
#include "lj_frame.h" #include "lj_frame.h"
#include "lj_jit.h" #include "lj_jit.h"
#include "lj_dispatch.h" #include "lj_dispatch.h"
@ -728,10 +729,8 @@ void lj_gdbjit_addtrace(jit_State *J, GCtrace *T)
ctx.spadjp = CFRAME_SIZE_JIT + ctx.spadjp = CFRAME_SIZE_JIT +
(MSize)(parent ? traceref(J, parent)->spadjust : 0); (MSize)(parent ? traceref(J, parent)->spadjust : 0);
ctx.spadj = CFRAME_SIZE_JIT + T->spadjust; ctx.spadj = CFRAME_SIZE_JIT + T->spadjust;
if (startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc) lua_assert(startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc);
ctx.lineno = proto_line(pt, proto_bcpos(pt, startpc)); ctx.lineno = lj_debug_line(pt, proto_bcpos(pt, startpc));
else
ctx.lineno = proto_line(pt, 0); /* Wrong, but better than nothing. */
ctx.filename = strdata(proto_chunkname(pt)); ctx.filename = strdata(proto_chunkname(pt));
if (*ctx.filename == '@' || *ctx.filename == '=') if (*ctx.filename == '@' || *ctx.filename == '=')
ctx.filename++; ctx.filename++;

View File

@ -12,6 +12,7 @@
#include "lj_gc.h" #include "lj_gc.h"
#include "lj_err.h" #include "lj_err.h"
#include "lj_debug.h"
#include "lj_str.h" #include "lj_str.h"
#include "lj_frame.h" #include "lj_frame.h"
#include "lj_state.h" #include "lj_state.h"
@ -103,10 +104,8 @@ static void perftools_addtrace(GCtrace *T)
name++; name++;
else else
name = "(string)"; name = "(string)";
if (startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc) lua_assert(startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc);
lineno = proto_line(pt, proto_bcpos(pt, startpc)); lineno = lj_debug_line(pt, proto_bcpos(pt, startpc));
else
lineno = proto_line(pt, 0); /* Wrong, but better than nothing. */
if (!fp) { if (!fp) {
char fname[40]; char fname[40];
sprintf(fname, "/tmp/perf-%d.map", getpid()); sprintf(fname, "/tmp/perf-%d.map", getpid());

View File

@ -38,6 +38,7 @@
#include "lj_func.c" #include "lj_func.c"
#include "lj_udata.c" #include "lj_udata.c"
#include "lj_meta.c" #include "lj_meta.c"
#include "lj_debug.c"
#include "lj_state.c" #include "lj_state.c"
#include "lj_dispatch.c" #include "lj_dispatch.c"
#include "lj_vmevent.c" #include "lj_vmevent.c"