Merge pull request #742 from TerryE/dev-stripdebug

Port of strip debug patch to the SDK 1.4-baseline dev
This commit is contained in:
Johny Mattsson 2015-11-10 12:20:36 +11:00
commit 7512e628b6
13 changed files with 404 additions and 33 deletions

View File

@ -65,6 +65,7 @@
#define READLINE_INTERVAL 80
#define LUA_TASK_PRIO USER_TASK_PRIO_0
#define LUA_PROCESS_LINE_SIG 2
#define LUA_OPTIMIZE_DEBUG 2
#ifdef DEVKIT_VERSION_0_9
#define KEYLED_INTERVAL 80

View File

@ -781,8 +781,91 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
}
#ifdef LUA_OPTIMIZE_DEBUG
/*
* Attempted to write to last (null terminator) byte of lineinfo, so need
* to grow the lineinfo vector and extend the fill bytes
*/
static unsigned char *growLineInfo(FuncState *fs) {
int i, oldsize = fs->packedlineinfoSize;
Proto *f = fs->f;
unsigned char *p, *r;
lua_assert(f->packedlineinfo==NULL || f->packedlineinfo[oldsize-1] == 0);
/* using the macro results in a redundant if test, but what the hell */
luaM_growvector(fs->L, f->packedlineinfo, fs->packedlineinfoSize, fs->packedlineinfoSize,
unsigned char, MAX_INT, "code size overflow");
r = p = f->packedlineinfo + oldsize;
if (oldsize) *--r = INFO_FILL_BYTE;
i = fs->packedlineinfoSize - oldsize - 1;
while (i--) *p++ = INFO_FILL_BYTE;
*p = 0;
return r;
}
static void generateInfoDeltaLine(FuncState *fs, int line) {
/* Handle first time through when lineinfo points is NULL */
unsigned char *p = fs->f->packedlineinfo ? lineInfoTop(fs) + 1 : growLineInfo(fs);
#define addDLbyte(v) if (*p==0) p = growLineInfo(fs); *p++ = (v);
int delta = line - fs->lastline - 1;
if (delta) {
if (delta<0) {
delta = -delta - 1;
addDLbyte((INFO_DELTA_MASK|INFO_SIGN_MASK) | (delta & INFO_DELTA_6BITS));
} else {
delta = delta - 1;
addDLbyte(INFO_DELTA_MASK | (delta & INFO_DELTA_6BITS));
}
delta >>= 6;
while (delta) {
addDLbyte(INFO_DELTA_MASK | (delta & INFO_DELTA_7BITS));
delta >>= 7;
}
}
addDLbyte(1);
fs->lastline = line;
fs->lastlineOffset = p - fs->f->packedlineinfo - 1;
#undef addDLbyte
}
#endif
void luaK_fixline (FuncState *fs, int line) {
fs->f->lineinfo[fs->pc - 1] = line;
#ifdef LUA_OPTIMIZE_DEBUG
/* The fixup line can be the same as existing one and in this case there's nothing to do */
if (line != fs->lastline) {
/* first remove the current line reference */
unsigned char *p = lineInfoTop(fs);
lua_assert(*p < 127);
if (*p >1) {
(*p)--; /* this is simply decrementing the last count a multi-PC line */
} else {
/* it's a bit more complicated if it's the 1st instruction on the line */
int delta = 0;
unsigned char code;
/* this logic handles <i/c> [1snnnnnnn [1nnnnnnn]*]? <i/c=1> */
*p-- = INFO_FILL_BYTE;
/* work backwards over the coded delta computing the delta */
while ((code=*p) & INFO_DELTA_MASK) {
*p-- = INFO_FILL_BYTE;
if (*p & INFO_DELTA_MASK) {
delta = delta + ((code & INFO_DELTA_7BITS)<<7);
} else {
delta += (code & INFO_DELTA_6BITS) + 1;
if (code & INFO_SIGN_MASK) delta = -delta;
}
}
/* and reposition the FuncState lastline pointers at the previous instruction count */
fs->lastline-= delta + 1;
fs->lastlineOffset = p - fs->f->packedlineinfo;
}
/* Then add the new line reference */
generateInfoDeltaLine(fs, line);
}
#else
fs->f->lineinfo[fs->pc - 1] = line;
#endif
}
@ -794,9 +877,25 @@ static int luaK_code (FuncState *fs, Instruction i, int line) {
MAX_INT, "code size overflow");
f->code[fs->pc] = i;
/* save corresponding line information */
#ifdef LUA_OPTIMIZE_DEBUG
/* note that frst time fs->lastline==0 through, so the else branch is taken */
if (fs->pc == fs->lineinfoLastPC+1) {
if (line == fs->lastline && f->packedlineinfo[fs->lastlineOffset] < INFO_MAX_LINECNT) {
f->packedlineinfo[fs->lastlineOffset]++;
} else {
generateInfoDeltaLine(fs, line);
}
} else {
/* The last instruction is occasionally overwritten as part of branch optimisation*/
lua_assert(fs->pc == fs->lineinfoLastPC); /* panic if its anything other than this !! */
luaK_fixline(fs,line);
}
fs->lineinfoLastPC = fs->pc;
#else
luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
MAX_INT, "code size overflow");
f->lineinfo[fs->pc] = line;
#endif
return fs->pc++;
}

View File

@ -171,21 +171,114 @@ static void info_tailcall (lua_Debug *ar) {
}
static void collectvalidlines (lua_State *L, Closure *f) {
if (f == NULL || f->c.isC) {
setnilvalue(L->top);
static void collectvalidlines (lua_State *L, Closure *f) {
if (f == NULL || f->c.isC) {
setnilvalue(L->top);
}
else {
# define INFO_FILL_BYTE 0x7F
# define INFO_DELTA_MASK 0x80
# define INFO_SIGN_MASK 0x40
# define INFO_DELTA_6BITS 0x3F
# define INFO_DELTA_7BITS 0x7F
# define INFO_MAX_LINECNT 126
Table *t = luaH_new(L, 0, 0);
#ifdef LUA_OPTIMIZE_DEBUG
int line = 0;
unsigned char *p = f->l.p->packedlineinfo;
if (p) {
for (; *p && *p != INFO_FILL_BYTE; ) {
if (*p & INFO_DELTA_MASK) { /* line delta */
int delta = *p & INFO_DELTA_6BITS;
unsigned char sign = *p++ & INFO_SIGN_MASK;
int shift;
for (shift = 6; *p & INFO_DELTA_MASK; p++, shift += 7) {
delta += (*p & INFO_DELTA_7BITS)<<shift;
}
line += sign ? -delta : delta+2;
} else {
line++;
}
p++;
setbvalue(luaH_setnum(L, t, line), 1);
}
}
#else
int *lineinfo = f->l.p->lineinfo;
int i;
for (i=0; i<f->l.p->sizelineinfo; i++)
setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
#endif
sethvalue(L, L->top, t);
}
incr_top(L);
}
#ifdef LUA_OPTIMIZE_DEBUG
/*
* This may seem expensive but this is only accessed frequently in traceexec
* and the while loop will be executed roughly half the number of non-blank
* source lines in the Lua function and these tend to be short.
*/
int luaG_getline (const Proto *f, int pc) {
int line = 0, thispc = 0, nextpc;
unsigned char *p;
for (p = f->packedlineinfo; *p && *p != INFO_FILL_BYTE;) {
if (*p & INFO_DELTA_MASK) { /* line delta */
int delta = *p & INFO_DELTA_6BITS;
unsigned char sign = *p++ & INFO_SIGN_MASK;
int shift;
for (shift = 6; *p & INFO_DELTA_MASK; p++, shift += 7) {
delta += (*p & INFO_DELTA_7BITS)<<shift;
}
line += sign ? -delta : delta+2;
} else {
line++;
}
lua_assert(*p<127);
nextpc = thispc + *p++;
if (thispc <= pc && pc < nextpc) {
return line;
}
thispc = nextpc;
}
else {
Table *t = luaH_new(L, 0, 0);
int *lineinfo = f->l.p->lineinfo;
int i;
for (i=0; i<f->l.p->sizelineinfo; i++)
setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
sethvalue(L, L->top, t);
}
incr_top(L);
lua_assert(0);
return 0;
}
static int stripdebug (lua_State *L, Proto *f, int level) {
int len = 0, sizepackedlineinfo;
TString* dummy;
switch (level) {
case 3:
sizepackedlineinfo = c_strlen(cast(char *, f->packedlineinfo))+1;
f->packedlineinfo = luaM_freearray(L, f->packedlineinfo, sizepackedlineinfo, unsigned char);
len += sizepackedlineinfo;
case 2:
len += f->sizelocvars * (sizeof(struct LocVar) + sizeof(dummy->tsv) + sizeof(struct LocVar *));
f->locvars = luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
f->upvalues = luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
len += f->sizelocvars * (sizeof(struct LocVar) + sizeof(dummy->tsv) + sizeof(struct LocVar *)) +
f->sizeupvalues * (sizeof(dummy->tsv) + sizeof(TString *));
f->sizelocvars = 0;
f->sizeupvalues = 0;
}
return len;
}
/* This is a recursive function so it's stack size has been kept to a minimum! */
LUA_API int luaG_stripdebug (lua_State *L, Proto *f, int level, int recv){
int len = 0, i;
if (recv != 0 && f->sizep != 0) {
for(i=0;i<f->sizep;i++) len += luaG_stripdebug(L, f->p[i], level, recv);
}
len += stripdebug (L, f, level);
return len;
}
#endif
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
Closure *f, void *plight, CallInfo *ci) {
@ -252,7 +345,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
}
status = auxgetinfo(L, what, ar, f, plight, ci);
if (c_strchr(what, 'f')) {
if (f != NULL)
if (f != NULL)
setclvalue(L, L->top, f)
else if (plight != NULL)
setfvalue(L->top, plight)
@ -287,7 +380,9 @@ static int precheck (const Proto *pt) {
check(!(pt->is_vararg & VARARG_NEEDSARG) ||
(pt->is_vararg & VARARG_HASARG));
check(pt->sizeupvalues <= pt->nups);
#ifndef LUA_OPTIMIZE_DEBUG
check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
#endif
check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
return 1;
}

View File

@ -13,7 +13,19 @@
#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1)
#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
#ifdef LUA_OPTIMIZE_DEBUG
# include "lvm.h"
# define getline(f,pc) (((f)->packedlineinfo) ? luaG_getline((f), pc) : 0)
# define INFO_FILL_BYTE 0x7F
# define INFO_DELTA_MASK 0x80
# define INFO_SIGN_MASK 0x40
# define INFO_DELTA_6BITS 0x3F
# define INFO_DELTA_7BITS 0x7F
# define INFO_MAX_LINECNT 126
# define lineInfoTop(fs) ((fs)->f->packedlineinfo + (fs)->lastlineOffset)
#else
# define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
#endif
#define resethookcount(L) (L->hookcount = L->basehookcount)
@ -29,5 +41,9 @@ LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...);
LUAI_FUNC void luaG_errormsg (lua_State *L);
LUAI_FUNC int luaG_checkcode (const Proto *pt);
LUAI_FUNC int luaG_checkopenop (Instruction i);
#ifdef LUA_OPTIMIZE_DEBUG
LUAI_FUNC int luaG_getline (const Proto *f, int pc);
LUAI_FUNC int luaG_stripdebug (lua_State *L, Proto *f, int level, int recv);
#endif
#endif

View File

@ -72,18 +72,18 @@ static void DumpIntWithSize(int x, int sizeof_int, DumpState* D)
/* dump signed integer */
switch(sizeof_int) {
case 1: {
if (x>0x7F || x<(-0x80)) D->status=LUA_ERR_CC_INTOVERFLOW;
if (x>0x7F || x<(-0x80)) D->status=LUA_ERR_CC_INTOVERFLOW;
DumpChar(x,D);
} break;
case 2: {
if (x>0x7FFF || x<(-0x8000)) D->status=LUA_ERR_CC_INTOVERFLOW;
if (x>0x7FFF || x<(-0x8000)) D->status=LUA_ERR_CC_INTOVERFLOW;
int16_t y=(int16_t)x;
MaybeByteSwap((char*)&y,2,D);
DumpVar(y,D);
} break;
case 4: {
/* Need to reduce bounds by 1 to avoid messing 32-bit compilers up */
if (x>0x7FFFFFFE || x<(-0x7FFFFFFF)) D->status=LUA_ERR_CC_INTOVERFLOW;
if (x>0x7FFFFFFE || x<(-0x7FFFFFFF)) D->status=LUA_ERR_CC_INTOVERFLOW;
int32_t y=(int32_t)x;
MaybeByteSwap((char*)&y,4,D);
DumpVar(y,D);
@ -102,7 +102,7 @@ static void DumpSize(uint32_t x, DumpState* D)
/* dump unsigned integer */
switch(D->target.sizeof_strsize_t) {
case 1: {
if (x>0xFF) D->status=LUA_ERR_CC_INTOVERFLOW;
if (x>0xFF) D->status=LUA_ERR_CC_INTOVERFLOW;
DumpChar(x,D);
} break;
case 2: {
@ -144,8 +144,8 @@ static void DumpNumber(lua_Number x, DumpState* D)
} break;
case 8: {
double y=x;
// ARM FPA mode: keep endianness, but swap high and low parts of the
// memory representation. This is the default compilation mode for ARM
// ARM FPA mode: keep endianness, but swap high and low parts of the
// memory representation. This is the default compilation mode for ARM
// targets with non-EABI gcc
if(D->target.is_arm_fpa)
{
@ -153,7 +153,7 @@ static void DumpNumber(lua_Number x, DumpState* D)
c_memcpy(temp,pnum,4);
c_memcpy(pnum,pnum+4,4);
c_memcpy(pnum+4,temp,4);
}
}
MaybeByteSwap((char*)&y,8,D);
DumpVar(y,D);
} break;
@ -228,6 +228,16 @@ static void DumpConstants(const Proto* f, DumpState* D)
static void DumpDebug(const Proto* f, DumpState* D)
{
int i,n;
#ifdef LUA_OPTIMIZE_DEBUG
n = (D->strip || f->packedlineinfo == NULL) ? 0: c_strlen(cast(char *,f->packedlineinfo))+1;
DumpInt(n,D);
Align4(D);
if (n)
{
DumpBlock(f->packedlineinfo, n, D);
}
#else
n= (D->strip) ? 0 : f->sizelineinfo;
DumpInt(n,D);
Align4(D);
@ -235,7 +245,8 @@ static void DumpDebug(const Proto* f, DumpState* D)
{
DumpInt(f->lineinfo[i],D);
}
#endif
n= (D->strip) ? 0 : f->sizelocvars;
DumpInt(n,D);
for (i=0; i<n; i++)
@ -268,7 +279,7 @@ static void DumpHeader(DumpState* D)
{
char buf[LUAC_HEADERSIZE];
char *h=buf;
/* This code must be kept in sync wiht luaU_header */
c_memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
h+=sizeof(LUA_SIGNATURE)-1;
@ -280,7 +291,7 @@ static void DumpHeader(DumpState* D)
*h++=(char)sizeof(Instruction);
*h++=(char)D->target.sizeof_lua_Number;
*h++=(char)D->target.lua_Number_integral;
DumpBlock(buf,LUAC_HEADERSIZE,D);
}

View File

@ -9,6 +9,7 @@
#define LUAC_CROSS_FILE
#include "lua.h"
#include C_HEADER_STRING
#include "lfunc.h"
#include "lgc.h"
@ -119,14 +120,18 @@ Proto *luaF_newproto (lua_State *L) {
f->sizep = 0;
f->code = NULL;
f->sizecode = 0;
f->sizelineinfo = 0;
f->sizeupvalues = 0;
f->nups = 0;
f->upvalues = NULL;
f->numparams = 0;
f->is_vararg = 0;
f->maxstacksize = 0;
#ifdef LUA_OPTIMIZE_DEBUG
f->packedlineinfo = NULL;
#else
f->sizelineinfo = 0;
f->lineinfo = NULL;
#endif
f->sizelocvars = 0;
f->locvars = NULL;
f->linedefined = 0;
@ -143,7 +148,13 @@ void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
if (!proto_is_readonly(f)) {
luaM_freearray(L, f->code, f->sizecode, Instruction);
#ifdef LUA_OPTIMIZE_DEBUG
if (f->packedlineinfo) {
luaM_freearray(L, f->packedlineinfo, c_strlen(cast(char *, f->packedlineinfo))+1, unsigned char);
}
#else
luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
#endif
}
luaM_free(L, f);
}

View File

@ -312,12 +312,19 @@ static l_mem propagatemark (global_State *g) {
Proto *p = gco2p(o);
g->gray = p->gclist;
traverseproto(g, p);
return sizeof(Proto) + sizeof(Proto *) * p->sizep +
sizeof(TValue) * p->sizek +
sizeof(TValue) * p->sizek +
sizeof(LocVar) * p->sizelocvars +
sizeof(TString *) * p->sizeupvalues +
(proto_is_readonly(p) ? 0 : sizeof(Instruction) * p->sizecode +
#ifdef LUA_OPTIMIZE_DEBUG
(p->packedlineinfo ?
c_strlen(cast(char *, p->packedlineinfo))+1 :
0));
#else
sizeof(int) * p->sizelineinfo);
#endif
}
default: lua_assert(0); return 0;
}
@ -729,7 +736,7 @@ void luaC_linkupval (lua_State *L, UpVal *uv) {
GCObject *o = obj2gco(uv);
o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */
g->rootgc = o;
if (isgray(o)) {
if (isgray(o)) {
if (g->gcstate == GCSpropagate) {
gray2black(o); /* closed upvalues need barrier */
luaC_barrier(L, uv, uv->v);

View File

@ -211,10 +211,10 @@ typedef TValuefields TValue;
#define setpvalue(obj,x) \
{ void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TLIGHTUSERDATA; }
#define setrvalue(obj,x) \
{ void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TROTABLE; }
#define setfvalue(obj,x) \
{ void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TLIGHTFUNCTION; }
@ -394,14 +394,20 @@ typedef struct Proto {
TValue *k; /* constants used by the function */
Instruction *code;
struct Proto **p; /* functions defined inside the function */
#ifdef LUA_OPTIMIZE_DEBUG
unsigned char *packedlineinfo;
#else
int *lineinfo; /* map from opcodes to source lines */
#endif
struct LocVar *locvars; /* information about local variables */
TString **upvalues; /* upvalue names */
TString *source;
int sizeupvalues;
int sizek; /* size of `k' */
int sizecode;
#ifndef LUA_OPTIMIZE_DEBUG
int sizelineinfo;
#endif
int sizep; /* size of `p' */
int sizelocvars;
int linedefined;
@ -510,7 +516,7 @@ typedef struct Node {
typedef struct Table {
CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of `node' array */
struct Table *metatable;
TValue *array; /* array part */

View File

@ -344,6 +344,12 @@ static void open_func (LexState *ls, FuncState *fs) {
fs->bl = NULL;
f->source = ls->source;
f->maxstacksize = 2; /* registers 0/1 are always valid */
#ifdef LUA_OPTIMIZE_DEBUG
fs->packedlineinfoSize = 0;
fs->lastline = 0;
fs->lastlineOffset = 0;
fs->lineinfoLastPC = -1;
#endif
fs->h = luaH_new(L, 0, 0);
/* anchor table of constants and prototype (to avoid being collected) */
sethvalue2s(L, L->top, fs->h);
@ -361,8 +367,15 @@ static void close_func (LexState *ls) {
luaK_ret(fs, 0, 0); /* final return */
luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
f->sizecode = fs->pc;
#ifdef LUA_OPTIMIZE_DEBUG
f->packedlineinfo[fs->lastlineOffset+1]=0;
luaM_reallocvector(L, f->packedlineinfo, fs->packedlineinfoSize,
fs->lastlineOffset+2, unsigned char);
#else
luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
f->sizelineinfo = fs->pc;
#endif
luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);
f->sizek = fs->nk;
luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
@ -379,6 +392,21 @@ static void close_func (LexState *ls) {
L->top -= 2; /* remove table and prototype from the stack */
}
#ifdef LUA_OPTIMIZE_DEBUG
static void compile_stripdebug(lua_State *L, Proto *f) {
int level;
lua_pushlightuserdata(L, &luaG_stripdebug );
lua_gettable(L, LUA_REGISTRYINDEX);
level = lua_isnil(L, -1) ? LUA_OPTIMIZE_DEBUG : lua_tointeger(L, -1);
lua_pop(L, 1);
if (level > 1) {
int len = luaG_stripdebug(L, f, level, 1);
UNUSED(len);
}
}
#endif
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
struct LexState lexstate;
@ -394,6 +422,9 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
chunk(&lexstate);
check(&lexstate, TK_EOS);
close_func(&lexstate);
#ifdef LUA_OPTIMIZE_DEBUG
compile_stripdebug(L, funcstate.f);
#endif
L->top--; /* remove 'name' from stack */
lua_assert(funcstate.prev == NULL);
lua_assert(funcstate.f->nups == 0);

View File

@ -72,6 +72,12 @@ typedef struct FuncState {
lu_byte nactvar; /* number of active local variables */
upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */
unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */
#ifdef LUA_OPTIMIZE_DEBUG
int packedlineinfoSize; /* only used during compilation for line info */
int lastline; /* ditto */
int lastlineOffset; /* ditto */
int lineinfoLastPC; /* ditto */
#endif
} FuncState;

View File

@ -102,6 +102,9 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
#include LUA_USER_H
#endif
#if defined(LUA_OPTIMIZE_DEBUG) && LUA_OPTIMIZE_DEBUG == 0
#undef LUA_OPTIMIZE_DEBUG
#endif
/* type of numbers in Lua */
typedef LUA_NUMBER lua_Number;
@ -258,7 +261,7 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
/*
/*
** ===============================================================
** some useful macros
** ===============================================================

View File

@ -235,6 +235,20 @@ static void LoadDebug(LoadState* S, Proto* f)
int i,n;
n=LoadInt(S);
Align4(S);
#ifdef LUA_OPTIMIZE_DEBUG
if(n) {
if (!luaZ_direct_mode(S->Z)) {
f->packedlineinfo=luaM_newvector(S->L,n,unsigned char);
LoadBlock(S,f->packedlineinfo,n);
} else {
f->packedlineinfo=(unsigned char*)luaZ_get_crt_address(S->Z);
LoadBlock(S,NULL,n);
}
} else {
f->packedlineinfo=NULL;
}
#else
if (!luaZ_direct_mode(S->Z)) {
f->lineinfo=luaM_newvector(S->L,n,int);
LoadVector(S,f->lineinfo,n,sizeof(int));
@ -243,6 +257,7 @@ static void LoadDebug(LoadState* S, Proto* f)
LoadVector(S,NULL,n,sizeof(int));
}
f->sizelineinfo=n;
#endif
n=LoadInt(S);
f->locvars=luaM_newvector(S->L,n,LocVar);
f->sizelocvars=n;

View File

@ -3,10 +3,13 @@
#include "lua.h"
#include "lauxlib.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lopcodes.h"
#include "lstring.h"
#include "lundump.h"
@ -483,6 +486,69 @@ static int node_restore (lua_State *L)
return 0;
}
#ifdef LUA_OPTIMIZE_DEBUG
/* node.stripdebug([level[, function]]). 
* level: 1 don't discard debug
* 2 discard Local and Upvalue debug info
* 3 discard Local, Upvalue and lineno debug info.
* function: Function to be stripped as per setfenv except 0 not permitted.
* If no arguments then the current default setting is returned.
* If function is omitted, this is the default setting for future compiles
* The function returns an estimated integer count of the bytes stripped.
*/
static int node_stripdebug (lua_State *L) {
int level;
if (L->top == L->base) {
lua_pushlightuserdata(L, &luaG_stripdebug );
lua_gettable(L, LUA_REGISTRYINDEX);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
lua_pushinteger(L, LUA_OPTIMIZE_DEBUG);
}
return 1;
}
level = luaL_checkint(L, 1);
if ((level <= 0) || (level > 3)) luaL_argerror(L, 1, "must in range 1-3");
if (L->top == L->base + 1) {
/* Store the default level in the registry if no function parameter */
lua_pushlightuserdata(L, &luaG_stripdebug);
lua_pushinteger(L, level);
lua_settable(L, LUA_REGISTRYINDEX);
lua_settop(L,0);
return 0;
}
if (level == 1) {
lua_settop(L,0);
lua_pushinteger(L, 0);
return 1;
}
if (!lua_isfunction(L, 2)) {
int scope = luaL_checkint(L, 2);
if (scope > 0) {
/* if the function parameter is a +ve integer then climb to find function */
lua_Debug ar;
lua_pop(L, 1); /* pop level as getinfo will replace it by the function */
if (lua_getstack(L, scope, &ar)) {
lua_getinfo(L, "f", &ar);
}
}
}
if(!lua_isfunction(L, 2) || lua_iscfunction(L, -1)) luaL_argerror(L, 2, "must be a Lua Function");
// lua_lock(L);
Proto *f = clvalue(L->base + 1)->l.p;
// lua_unlock(L);
lua_settop(L,0);
lua_pushinteger(L, luaG_stripdebug(L, f, level, 1));
return 1;
}
#endif
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
@ -501,7 +567,7 @@ const LUA_REG_TYPE node_map[] =
#endif
{ LSTRKEY( "input" ), LFUNCVAL( node_input ) },
{ LSTRKEY( "output" ), LFUNCVAL( node_output ) },
// Moved to adc module, use adc.readvdd33()
// Moved to adc module, use adc.readvdd33()
// { LSTRKEY( "readvdd33" ), LFUNCVAL( node_readvdd33) },
{ LSTRKEY( "compile" ), LFUNCVAL( node_compile) },
{ LSTRKEY( "CPU80MHZ" ), LNUMVAL( CPU80MHZ ) },
@ -509,6 +575,10 @@ const LUA_REG_TYPE node_map[] =
{ LSTRKEY( "setcpufreq" ), LFUNCVAL( node_setcpufreq) },
{ LSTRKEY( "bootreason" ), LFUNCVAL( node_bootreason) },
{ LSTRKEY( "restore" ), LFUNCVAL( node_restore) },
#ifdef LUA_OPTIMIZE_DEBUG
{ LSTRKEY( "stripdebug" ), LFUNCVAL( node_stripdebug ) },
#endif
// Combined to dsleep(us, option)
// { LSTRKEY( "dsleepsetoption" ), LFUNCVAL( node_deepsleep_setoption) },
#if LUA_OPTIMIZE_MEMORY > 0