Quellcode durchsuchen

Merge pull request #742 from TerryE/dev-stripdebug

Port of strip debug patch to the SDK 1.4-baseline dev
Johny Mattsson vor 8 Jahren
Ursprung
Commit
7512e628b6
13 geänderte Dateien mit 403 neuen und 32 gelöschten Zeilen
  1. 1 0
      app/include/user_config.h
  2. 100 1
      app/lua/lcode.c
  3. 107 12
      app/lua/ldebug.c
  4. 17 1
      app/lua/ldebug.h
  5. 21 10
      app/lua/ldump.c
  6. 12 1
      app/lua/lfunc.c
  7. 9 2
      app/lua/lgc.c
  8. 9 3
      app/lua/lobject.h
  9. 31 0
      app/lua/lparser.c
  10. 6 0
      app/lua/lparser.h
  11. 4 1
      app/lua/lua.h
  12. 15 0
      app/lua/lundump.c
  13. 71 1
      app/modules/node.c

+ 1 - 0
app/include/user_config.h

@@ -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

+ 100 - 1
app/lua/lcode.c

@@ -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++;
 }
 

+ 107 - 12
app/lua/ldebug.c

@@ -171,20 +171,113 @@ 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); 
+  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);
   }
-  incr_top(L);
+  len += stripdebug (L, f, level);
+  return len;
 }
+#endif
 
 
 static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
@@ -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;
 }

+ 17 - 1
app/lua/ldebug.h

@@ -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

+ 21 - 10
app/lua/ldump.c

@@ -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);
 }
 

+ 12 - 1
app/lua/lfunc.c

@@ -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);
 }

+ 9 - 2
app/lua/lgc.c

@@ -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);

+ 9 - 3
app/lua/lobject.h

@@ -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 */

+ 31 - 0
app/lua/lparser.c

@@ -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);

+ 6 - 0
app/lua/lparser.h

@@ -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;
 
 

+ 4 - 1
app/lua/lua.h

@@ -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
 ** ===============================================================

+ 15 - 0
app/lua/lundump.c

@@ -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;

+ 71 - 1
app/modules/node.c

@@ -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