aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2011-06-09 01:27:37 +0200
committerMike Pall <mike>2011-06-09 01:27:37 +0200
commit8c32b38ca3d522d6c90249495231a331aafca7e2 (patch)
tree0dad822398bef90be8caec0945d6c32a790d7ec9
parent585cf05dbd54564d2d3387cef09b3ac2d5e52afd (diff)
downloadluajit-8c32b38ca3d522d6c90249495231a331aafca7e2.tar.gz
luajit-8c32b38ca3d522d6c90249495231a331aafca7e2.tar.bz2
luajit-8c32b38ca3d522d6c90249495231a331aafca7e2.zip
Flatten and compress in-memory debug info (saves ~70%).
-rw-r--r--src/Makefile.dep7
-rw-r--r--src/lib_jit.c6
-rw-r--r--src/lj_api.c4
-rw-r--r--src/lj_debug.c194
-rw-r--r--src/lj_debug.h22
-rw-r--r--src/lj_err.c2
-rw-r--r--src/lj_err.h2
-rw-r--r--src/lj_gc.c4
-rw-r--r--src/lj_gdbjit.c2
-rw-r--r--src/lj_lex.c2
-rw-r--r--src/lj_lex.h7
-rw-r--r--src/lj_obj.h29
-rw-r--r--src/lj_parse.c226
-rw-r--r--src/lj_trace.c2
14 files changed, 344 insertions, 165 deletions
diff --git a/src/Makefile.dep b/src/Makefile.dep
index 5e7f11dc..937fd67f 100644
--- a/src/Makefile.dep
+++ b/src/Makefile.dep
@@ -85,7 +85,8 @@ lj_crecord.o: lj_crecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
85lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 85lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
86 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h 86 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h
87lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 87lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
88 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_state.h lj_frame.h lj_bc.h 88 lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_state.h lj_frame.h \
89 lj_bc.h
89lj_dispatch.o: lj_dispatch.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 90lj_dispatch.o: lj_dispatch.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
90 lj_err.h lj_errmsg.h lj_debug.h lj_state.h lj_frame.h lj_bc.h lj_ff.h \ 91 lj_err.h lj_errmsg.h lj_debug.h lj_state.h lj_frame.h lj_bc.h lj_ff.h \
91 lj_ffdef.h lj_jit.h lj_ir.h lj_trace.h lj_dispatch.h lj_traceerr.h \ 92 lj_ffdef.h lj_jit.h lj_ir.h lj_trace.h lj_dispatch.h lj_traceerr.h \
@@ -143,8 +144,8 @@ lj_opt_split.o: lj_opt_split.c lj_obj.h lua.h luaconf.h lj_def.h \
143 lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_ir.h lj_jit.h lj_ircall.h \ 144 lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_ir.h lj_jit.h lj_ircall.h \
144 lj_iropt.h lj_vm.h 145 lj_iropt.h lj_vm.h
145lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 146lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
146 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_state.h \ 147 lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h \
147 lj_bc.h lj_ctype.h lj_lex.h lj_parse.h lj_vm.h lj_vmevent.h 148 lj_state.h lj_bc.h lj_ctype.h lj_lex.h lj_parse.h lj_vm.h lj_vmevent.h
148lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 149lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
149 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ 150 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \
150 lj_ff.h lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \ 151 lj_ff.h lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \
diff --git a/src/lib_jit.c b/src/lib_jit.c
index 758835aa..818b8787 100644
--- a/src/lib_jit.c
+++ b/src/lib_jit.c
@@ -181,8 +181,8 @@ LJLIB_CF(jit_util_funcinfo)
181 GCtab *t; 181 GCtab *t;
182 lua_createtable(L, 0, 16); /* Increment hash size if fields are added. */ 182 lua_createtable(L, 0, 16); /* Increment hash size if fields are added. */
183 t = tabV(L->top-1); 183 t = tabV(L->top-1);
184 setintfield(L, t, "linedefined", proto_line(pt, 0)); 184 setintfield(L, t, "linedefined", pt->firstline);
185 setintfield(L, t, "lastlinedefined", pt->lastlinedefined); 185 setintfield(L, t, "lastlinedefined", pt->firstline + pt->numline);
186 setintfield(L, t, "stackslots", pt->framesize); 186 setintfield(L, t, "stackslots", pt->framesize);
187 setintfield(L, t, "params", pt->numparams); 187 setintfield(L, t, "params", pt->numparams);
188 setintfield(L, t, "bytecodes", (int32_t)pt->sizebc); 188 setintfield(L, t, "bytecodes", (int32_t)pt->sizebc);
@@ -254,7 +254,7 @@ LJLIB_CF(jit_util_funcuvname)
254 GCproto *pt = check_Lproto(L, 0); 254 GCproto *pt = check_Lproto(L, 0);
255 uint32_t idx = (uint32_t)lj_lib_checkint(L, 2); 255 uint32_t idx = (uint32_t)lj_lib_checkint(L, 2);
256 if (idx < pt->sizeuv) { 256 if (idx < pt->sizeuv) {
257 setstrV(L, L->top-1, proto_uvname(pt, idx)); 257 setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx)));
258 return 1; 258 return 1;
259 } 259 }
260 return 0; 260 return 0;
diff --git a/src/lj_api.c b/src/lj_api.c
index 4e41ccc0..6a68cd84 100644
--- a/src/lj_api.c
+++ b/src/lj_api.c
@@ -836,7 +836,7 @@ LUA_API int lua_next(lua_State *L, int idx)
836LUA_API const char *lua_getupvalue(lua_State *L, int idx, int n) 836LUA_API const char *lua_getupvalue(lua_State *L, int idx, int n)
837{ 837{
838 TValue *val; 838 TValue *val;
839 const char *name = lj_debug_uvname(index2adr(L, idx), (uint32_t)(n-1), &val); 839 const char *name = lj_debug_uvnamev(index2adr(L, idx), (uint32_t)(n-1), &val);
840 if (name) { 840 if (name) {
841 copyTV(L, L->top, val); 841 copyTV(L, L->top, val);
842 incr_top(L); 842 incr_top(L);
@@ -991,7 +991,7 @@ LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n)
991 TValue *val; 991 TValue *val;
992 const char *name; 992 const char *name;
993 api_checknelems(L, 1); 993 api_checknelems(L, 1);
994 name = lj_debug_uvname(f, (uint32_t)(n-1), &val); 994 name = lj_debug_uvnamev(f, (uint32_t)(n-1), &val);
995 if (name) { 995 if (name) {
996 L->top--; 996 L->top--;
997 copyTV(L, val, L->top); 997 copyTV(L, val, L->top);
diff --git a/src/lj_debug.c b/src/lj_debug.c
index a5ffff74..1c4bac43 100644
--- a/src/lj_debug.c
+++ b/src/lj_debug.c
@@ -8,6 +8,7 @@
8 8
9#include "lj_obj.h" 9#include "lj_obj.h"
10#include "lj_err.h" 10#include "lj_err.h"
11#include "lj_debug.h"
11#include "lj_str.h" 12#include "lj_str.h"
12#include "lj_tab.h" 13#include "lj_tab.h"
13#include "lj_state.h" 14#include "lj_state.h"
@@ -89,9 +90,17 @@ static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
89/* Get line number for a bytecode position. */ 90/* Get line number for a bytecode position. */
90BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc) 91BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc)
91{ 92{
92 BCLine *lineinfo = proto_lineinfo(pt); 93 const void *lineinfo = proto_lineinfo(pt);
93 if (pc < pt->sizebc && lineinfo) 94 if (pc < pt->sizebc && lineinfo) {
94 return lineinfo[pc]; 95 BCLine first = pt->firstline;
96 if (pc-- == 0) return first;
97 if (pt->numline < 256)
98 return first + (BCLine)((const uint8_t *)lineinfo)[pc];
99 else if (pt->numline < 65536)
100 return first + (BCLine)((const uint16_t *)lineinfo)[pc];
101 else
102 return first + (BCLine)((const uint32_t *)lineinfo)[pc];
103 }
95 return 0; 104 return 0;
96} 105}
97 106
@@ -109,14 +118,49 @@ static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
109 118
110/* -- Variable names ------------------------------------------------------ */ 119/* -- Variable names ------------------------------------------------------ */
111 120
121/* Read ULEB128 value. */
122static uint32_t debug_read_uleb128(const uint8_t **pp)
123{
124 const uint8_t *p = *pp;
125 uint32_t v = *p++;
126 if (LJ_UNLIKELY(v >= 0x80)) {
127 int sh = 0;
128 v &= 0x7f;
129 do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
130 }
131 *pp = p;
132 return v;
133}
134
112/* Get name of a local variable from slot number and PC. */ 135/* Get name of a local variable from slot number and PC. */
113static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot) 136static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
114{ 137{
115 MSize i; 138 const uint8_t *p = proto_varinfo(pt);
116 VarInfo *vi = proto_varinfo(pt); 139 if (p) {
117 for (i = 0; i < pt->sizevarinfo && vi[i].startpc <= pc; i++) 140 BCPos lastpc = 0;
118 if (pc < vi[i].endpc && slot-- == 0) 141 for (;;) {
119 return strdata(gco2str(gcref(vi[i].name))); 142 const char *name = (const char *)p;
143 uint32_t vn = *p++;
144 BCPos startpc, endpc;
145 if (vn < VARNAME__MAX) {
146 if (vn == VARNAME_END) break; /* End of varinfo. */
147 } else {
148 while (*p++) ; /* Skip over variable name string. */
149 }
150 lastpc = startpc = lastpc + debug_read_uleb128(&p);
151 if (startpc > pc) break;
152 endpc = startpc + debug_read_uleb128(&p);
153 if (pc < endpc && slot-- == 0) {
154 if (vn < VARNAME__MAX) {
155#define VARNAMESTR(name, str) str "\0"
156 name = VARNAMEDEF(VARNAMESTR);
157#undef VARNAMESTR
158 if (--vn) while (*name++ || --vn) ;
159 }
160 return name;
161 }
162 }
163 }
120 return NULL; 164 return NULL;
121} 165}
122 166
@@ -141,7 +185,17 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
141} 185}
142 186
143/* Get name of upvalue. */ 187/* Get name of upvalue. */
144const char *lj_debug_uvname(cTValue *o, uint32_t idx, TValue **tvp) 188const char *lj_debug_uvname(GCproto *pt, uint32_t idx)
189{
190 const uint8_t *p = proto_uvinfo(pt);
191 lua_assert(idx < pt->sizeuv);
192 if (!p) return "";
193 if (idx) while (*p++ || --idx) ;
194 return (const char *)p;
195}
196
197/* Get name and value of upvalue. */
198const char *lj_debug_uvnamev(cTValue *o, uint32_t idx, TValue **tvp)
145{ 199{
146 if (tvisfunc(o)) { 200 if (tvisfunc(o)) {
147 GCfunc *fn = funcV(o); 201 GCfunc *fn = funcV(o);
@@ -149,7 +203,7 @@ const char *lj_debug_uvname(cTValue *o, uint32_t idx, TValue **tvp)
149 GCproto *pt = funcproto(fn); 203 GCproto *pt = funcproto(fn);
150 if (idx < pt->sizeuv) { 204 if (idx < pt->sizeuv) {
151 *tvp = uvval(&gcref(fn->l.uvptr[idx])->uv); 205 *tvp = uvval(&gcref(fn->l.uvptr[idx])->uv);
152 return strdata(proto_uvname(pt, idx)); 206 return lj_debug_uvname(pt, idx);
153 } 207 }
154 } else { 208 } else {
155 if (idx < fn->c.nupvalues) { 209 if (idx < fn->c.nupvalues) {
@@ -194,7 +248,7 @@ restart:
194 } 248 }
195 return "field"; 249 return "field";
196 case BC_UGET: 250 case BC_UGET:
197 *name = strdata(proto_uvname(pt, bc_d(ins))); 251 *name = lj_debug_uvname(pt, bc_d(ins));
198 return "upvalue"; 252 return "upvalue";
199 default: 253 default:
200 return NULL; 254 return NULL;
@@ -234,25 +288,26 @@ const char *lj_debug_funcname(lua_State *L, TValue *frame, const char **name)
234/* -- Source code locations ----------------------------------------------- */ 288/* -- Source code locations ----------------------------------------------- */
235 289
236/* Generate shortened source name. */ 290/* Generate shortened source name. */
237void lj_debug_shortname(char *out, const char *src) 291void lj_debug_shortname(char *out, GCstr *str)
238{ 292{
293 const char *src = strdata(str);
239 if (*src == '=') { 294 if (*src == '=') {
240 strncpy(out, src+1, LUA_IDSIZE); /* remove first char */ 295 strncpy(out, src+1, LUA_IDSIZE); /* Remove first char. */
241 out[LUA_IDSIZE-1] = '\0'; /* ensures null termination */ 296 out[LUA_IDSIZE-1] = '\0'; /* Ensures null termination. */
242 } else if (*src == '@') { /* out = "source", or "...source" */ 297 } else if (*src == '@') { /* Output "source", or "...source". */
243 size_t l = strlen(++src); /* skip the `@' */ 298 size_t len = str->len-1;
244 if (l >= LUA_IDSIZE) { 299 src++; /* Skip the `@' */
245 src += l-(LUA_IDSIZE-4); /* get last part of file name */ 300 if (len >= LUA_IDSIZE) {
246 strcpy(out, "..."); 301 src += len-(LUA_IDSIZE-4); /* Get last part of file name. */
247 out += 3; 302 *out++ = '.'; *out++ = '.'; *out++ = '.';
248 } 303 }
249 strcpy(out, src); 304 strcpy(out, src);
250 } else { /* out = [string "string"] */ 305 } else { /* Output [string "string"]. */
251 size_t len; /* Length, up to first control char. */ 306 size_t len; /* Length, up to first control char. */
252 for (len = 0; len < LUA_IDSIZE-12; len++) 307 for (len = 0; len < LUA_IDSIZE-12; len++)
253 if (((const unsigned char *)src)[len] < ' ') break; 308 if (((const unsigned char *)src)[len] < ' ') break;
254 strcpy(out, "[string \""); out += 9; 309 strcpy(out, "[string \""); out += 9;
255 if (src[len] != '\0') { /* must truncate? */ 310 if (src[len] != '\0') { /* Must truncate? */
256 if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15; 311 if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15;
257 strncpy(out, src, len); out += len; 312 strncpy(out, src, len); out += len;
258 strcpy(out, "..."); out += 3; 313 strcpy(out, "..."); out += 3;
@@ -273,7 +328,7 @@ void lj_debug_addloc(lua_State *L, const char *msg,
273 BCLine line = debug_frameline(L, fn, nextframe); 328 BCLine line = debug_frameline(L, fn, nextframe);
274 if (line >= 0) { 329 if (line >= 0) {
275 char buf[LUA_IDSIZE]; 330 char buf[LUA_IDSIZE];
276 lj_debug_shortname(buf, strdata(proto_chunkname(funcproto(fn)))); 331 lj_debug_shortname(buf, proto_chunkname(funcproto(fn)));
277 lj_str_pushf(L, "%s:%d: %s", buf, line, msg); 332 lj_str_pushf(L, "%s:%d: %s", buf, line, msg);
278 return; 333 return;
279 } 334 }
@@ -286,27 +341,23 @@ void lj_debug_addloc(lua_State *L, const char *msg,
286void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc) 341void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc)
287{ 342{
288 GCstr *name = proto_chunkname(pt); 343 GCstr *name = proto_chunkname(pt);
289 if (name) { 344 const char *s = strdata(name);
290 const char *s = strdata(name); 345 MSize i, len = name->len;
291 MSize i, len = name->len; 346 BCLine line = lj_debug_line(pt, pc);
292 BCLine line = lj_debug_line(pt, pc); 347 if (*s == '@') {
293 if (*s == '@') { 348 s++; len--;
294 s++; len--; 349 for (i = len; i > 0; i--)
295 for (i = len; i > 0; i--) 350 if (s[i] == '/' || s[i] == '\\') {
296 if (s[i] == '/' || s[i] == '\\') { 351 s += i+1;
297 s += i+1; 352 break;
298 break; 353 }
299 } 354 lj_str_pushf(L, "%s:%d", s, line);
300 lj_str_pushf(L, "%s:%d", s, line); 355 } else if (len > 40) {
301 } else if (len > 40) { 356 lj_str_pushf(L, "%p:%d", pt, line);
302 lj_str_pushf(L, "%p:%d", pt, line); 357 } else if (*s == '=') {
303 } else if (*s == '=') { 358 lj_str_pushf(L, "%s:%d", s+1, line);
304 lj_str_pushf(L, "%s:%d", s+1, line);
305 } else {
306 lj_str_pushf(L, "\"%s\":%d", s, line);
307 }
308 } else { 359 } else {
309 lj_str_pushf(L, "%p:%u", pt, pc); 360 lj_str_pushf(L, "\"%s\":%d", s, line);
310 } 361 }
311} 362}
312 363
@@ -359,56 +410,63 @@ LUA_API int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar)
359 lua_assert(fn->c.gct == ~LJ_TFUNC); 410 lua_assert(fn->c.gct == ~LJ_TFUNC);
360 } 411 }
361 for (; *what; what++) { 412 for (; *what; what++) {
362 switch (*what) { 413 if (*what == 'S') {
363 case 'S':
364 if (isluafunc(fn)) { 414 if (isluafunc(fn)) {
365 GCproto *pt = funcproto(fn); 415 GCproto *pt = funcproto(fn);
366 ar->source = strdata(proto_chunkname(pt)); 416 BCLine firstline = pt->firstline;
367 ar->linedefined = (int)proto_line(pt, 0); 417 GCstr *name = proto_chunkname(pt);
368 ar->lastlinedefined = (int)pt->lastlinedefined; 418 ar->source = strdata(name);
369 ar->what = ar->linedefined ? "Lua" : "main"; 419 lj_debug_shortname(ar->short_src, name);
420 ar->linedefined = (int)firstline;
421 ar->lastlinedefined = (int)(firstline + pt->numline);
422 ar->what = firstline ? "Lua" : "main";
370 } else { 423 } else {
371 ar->source = "=[C]"; 424 ar->source = "=[C]";
425 ar->short_src[0] = '[';
426 ar->short_src[1] = 'C';
427 ar->short_src[2] = ']';
428 ar->short_src[3] = '\0';
372 ar->linedefined = -1; 429 ar->linedefined = -1;
373 ar->lastlinedefined = -1; 430 ar->lastlinedefined = -1;
374 ar->what = "C"; 431 ar->what = "C";
375 } 432 }
376 lj_debug_shortname(ar->short_src, ar->source); 433 } else if (*what == 'l') {
377 break;
378 case 'l':
379 ar->currentline = frame ? debug_frameline(L, fn, nextframe) : -1; 434 ar->currentline = frame ? debug_frameline(L, fn, nextframe) : -1;
380 break; 435 } else if (*what == 'u') {
381 case 'u':
382 ar->nups = fn->c.nupvalues; 436 ar->nups = fn->c.nupvalues;
383 break; 437 } else if (*what == 'n') {
384 case 'n':
385 ar->namewhat = frame ? lj_debug_funcname(L, frame, &ar->name) : NULL; 438 ar->namewhat = frame ? lj_debug_funcname(L, frame, &ar->name) : NULL;
386 if (ar->namewhat == NULL) { 439 if (ar->namewhat == NULL) {
387 ar->namewhat = ""; 440 ar->namewhat = "";
388 ar->name = NULL; 441 ar->name = NULL;
389 } 442 }
390 break; 443 } else if (*what == 'f') {
391 case 'f':
392 setfuncV(L, L->top, fn); 444 setfuncV(L, L->top, fn);
393 incr_top(L); 445 incr_top(L);
394 break; 446 } else if (*what == 'L') {
395 case 'L':
396 if (isluafunc(fn)) { 447 if (isluafunc(fn)) {
397 GCtab *t = lj_tab_new(L, 0, 0); 448 GCtab *t = lj_tab_new(L, 0, 0);
398 GCproto *pt = funcproto(fn); 449 GCproto *pt = funcproto(fn);
399 BCLine *lineinfo = proto_lineinfo(pt); 450 const void *lineinfo = proto_lineinfo(pt);
400 MSize i, szl = pt->sizebc; 451 if (lineinfo) {
401 for (i = 1; i < szl; i++) 452 BCLine first = pt->firstline;
402 setboolV(lj_tab_setint(L, t, lineinfo[i]), 1); 453 int sz = pt->numline < 256 ? 1 : pt->numline < 65536 ? 2 : 4;
454 MSize i, szl = pt->sizebc-1;
455 for (i = 0; i < szl; i++) {
456 BCLine line = first +
457 (sz == 1 ? (BCLine)((const uint8_t *)lineinfo)[i] :
458 sz == 2 ? (BCLine)((const uint16_t *)lineinfo)[i] :
459 (BCLine)((const uint32_t *)lineinfo)[i]);
460 setboolV(lj_tab_setint(L, t, line), 1);
461 }
462 }
403 settabV(L, L->top, t); 463 settabV(L, L->top, t);
404 } else { 464 } else {
405 setnilV(L->top); 465 setnilV(L->top);
406 } 466 }
407 incr_top(L); 467 incr_top(L);
408 break; 468 } else {
409 default:
410 status = 0; /* Bad option. */ 469 status = 0; /* Bad option. */
411 break;
412 } 470 }
413 } 471 }
414 return status; 472 return status;
diff --git a/src/lj_debug.h b/src/lj_debug.h
index 5a1ddbec..f82fdfed 100644
--- a/src/lj_debug.h
+++ b/src/lj_debug.h
@@ -10,14 +10,32 @@
10 10
11LJ_FUNC cTValue *lj_debug_frame(lua_State *L, int level, int *size); 11LJ_FUNC cTValue *lj_debug_frame(lua_State *L, int level, int *size);
12LJ_FUNC BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc); 12LJ_FUNC BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc);
13LJ_FUNC const char *lj_debug_uvname(cTValue *o, uint32_t idx, TValue **tvp); 13LJ_FUNC const char *lj_debug_uvname(GCproto *pt, uint32_t idx);
14LJ_FUNC const char *lj_debug_uvnamev(cTValue *o, uint32_t idx, TValue **tvp);
14LJ_FUNC const char *lj_debug_slotname(GCproto *pt, const BCIns *pc, 15LJ_FUNC const char *lj_debug_slotname(GCproto *pt, const BCIns *pc,
15 BCReg slot, const char **name); 16 BCReg slot, const char **name);
16LJ_FUNC const char *lj_debug_funcname(lua_State *L, TValue *frame, 17LJ_FUNC const char *lj_debug_funcname(lua_State *L, TValue *frame,
17 const char **name); 18 const char **name);
18LJ_FUNC void lj_debug_shortname(char *out, const char *src); 19LJ_FUNC void lj_debug_shortname(char *out, GCstr *str);
19LJ_FUNC void lj_debug_addloc(lua_State *L, const char *msg, 20LJ_FUNC void lj_debug_addloc(lua_State *L, const char *msg,
20 cTValue *frame, cTValue *nextframe); 21 cTValue *frame, cTValue *nextframe);
21LJ_FUNC void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc); 22LJ_FUNC void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc);
22 23
24/* Fixed internal variable names. */
25#define VARNAMEDEF(_) \
26 _(FOR_IDX, "(for index)") \
27 _(FOR_STOP, "(for limit)") \
28 _(FOR_STEP, "(for step)") \
29 _(FOR_GEN, "(for generator)") \
30 _(FOR_STATE, "(for state)") \
31 _(FOR_CTL, "(for control)")
32
33enum {
34 VARNAME_END,
35#define VARNAMEENUM(name, str) VARNAME_##name,
36 VARNAMEDEF(VARNAMEENUM)
37#undef VARNAMEENUM
38 VARNAME__MAX
39};
40
23#endif 41#endif
diff --git a/src/lj_err.c b/src/lj_err.c
index 8d37af6a..42bb87fc 100644
--- a/src/lj_err.c
+++ b/src/lj_err.c
@@ -521,7 +521,7 @@ LJ_NOINLINE void lj_err_msg(lua_State *L, ErrMsg em)
521} 521}
522 522
523/* Lexer error. */ 523/* Lexer error. */
524LJ_NOINLINE void lj_err_lex(lua_State *L, const char *src, const char *tok, 524LJ_NOINLINE void lj_err_lex(lua_State *L, GCstr *src, const char *tok,
525 BCLine line, ErrMsg em, va_list argp) 525 BCLine line, ErrMsg em, va_list argp)
526{ 526{
527 char buff[LUA_IDSIZE]; 527 char buff[LUA_IDSIZE];
diff --git a/src/lj_err.h b/src/lj_err.h
index 69ede6d6..c65f484e 100644
--- a/src/lj_err.h
+++ b/src/lj_err.h
@@ -25,7 +25,7 @@ LJ_FUNCA_NORET void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode);
25LJ_FUNC_NORET void lj_err_mem(lua_State *L); 25LJ_FUNC_NORET void lj_err_mem(lua_State *L);
26LJ_FUNC_NORET void lj_err_run(lua_State *L); 26LJ_FUNC_NORET void lj_err_run(lua_State *L);
27LJ_FUNC_NORET void lj_err_msg(lua_State *L, ErrMsg em); 27LJ_FUNC_NORET void lj_err_msg(lua_State *L, ErrMsg em);
28LJ_FUNC_NORET void lj_err_lex(lua_State *L, const char *src, const char *tok, 28LJ_FUNC_NORET void lj_err_lex(lua_State *L, GCstr *src, const char *tok,
29 BCLine line, ErrMsg em, va_list argp); 29 BCLine line, ErrMsg em, va_list argp);
30LJ_FUNC_NORET void lj_err_optype(lua_State *L, cTValue *o, ErrMsg opm); 30LJ_FUNC_NORET void lj_err_optype(lua_State *L, cTValue *o, ErrMsg opm);
31LJ_FUNC_NORET void lj_err_comp(lua_State *L, cTValue *o1, cTValue *o2); 31LJ_FUNC_NORET void lj_err_comp(lua_State *L, cTValue *o1, cTValue *o2);
diff --git a/src/lj_gc.c b/src/lj_gc.c
index e65f7ffa..37d42467 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -257,10 +257,6 @@ static void gc_traverse_proto(global_State *g, GCproto *pt)
257 gc_mark_str(proto_chunkname(pt)); 257 gc_mark_str(proto_chunkname(pt));
258 for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) /* Mark collectable consts. */ 258 for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) /* Mark collectable consts. */
259 gc_markobj(g, proto_kgc(pt, i)); 259 gc_markobj(g, proto_kgc(pt, i));
260 for (i = 0; i < (ptrdiff_t)pt->sizeuv; i++) /* Mark upvalue names. */
261 gc_mark_str(proto_uvname(pt, i));
262 for (i = 0; i < (ptrdiff_t)pt->sizevarinfo; i++) /* Mark names of locals. */
263 gc_mark_str(gco2str(gcref(proto_varinfo(pt)[i].name)));
264#if LJ_HASJIT 260#if LJ_HASJIT
265 if (pt->trace) gc_marktrace(g, pt->trace); 261 if (pt->trace) gc_marktrace(g, pt->trace);
266#endif 262#endif
diff --git a/src/lj_gdbjit.c b/src/lj_gdbjit.c
index 28e063fb..fbaafc04 100644
--- a/src/lj_gdbjit.c
+++ b/src/lj_gdbjit.c
@@ -731,7 +731,7 @@ void lj_gdbjit_addtrace(jit_State *J, GCtrace *T)
731 ctx.spadj = CFRAME_SIZE_JIT + T->spadjust; 731 ctx.spadj = CFRAME_SIZE_JIT + T->spadjust;
732 lua_assert(startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc); 732 lua_assert(startpc >= proto_bc(pt) && startpc < proto_bc(pt) + pt->sizebc);
733 ctx.lineno = lj_debug_line(pt, proto_bcpos(pt, startpc)); 733 ctx.lineno = lj_debug_line(pt, proto_bcpos(pt, startpc));
734 ctx.filename = strdata(proto_chunkname(pt)); 734 ctx.filename = proto_chunknamestr(pt);
735 if (*ctx.filename == '@' || *ctx.filename == '=') 735 if (*ctx.filename == '@' || *ctx.filename == '=')
736 ctx.filename++; 736 ctx.filename++;
737 else 737 else
diff --git a/src/lj_lex.c b/src/lj_lex.c
index acfcb921..3411aa56 100644
--- a/src/lj_lex.c
+++ b/src/lj_lex.c
@@ -494,7 +494,7 @@ void lj_lex_error(LexState *ls, LexToken token, ErrMsg em, ...)
494 tok = lj_lex_token2str(ls, token); 494 tok = lj_lex_token2str(ls, token);
495 } 495 }
496 va_start(argp, em); 496 va_start(argp, em);
497 lj_err_lex(ls->L, strdata(ls->chunkname), tok, ls->linenumber, em, argp); 497 lj_err_lex(ls->L, ls->chunkname, tok, ls->linenumber, em, argp);
498 va_end(argp); 498 va_end(argp);
499} 499}
500 500
diff --git a/src/lj_lex.h b/src/lj_lex.h
index 0718f5a6..78a7e1a9 100644
--- a/src/lj_lex.h
+++ b/src/lj_lex.h
@@ -38,6 +38,13 @@ typedef struct BCInsLine {
38 BCLine line; /* Line number for this bytecode. */ 38 BCLine line; /* Line number for this bytecode. */
39} BCInsLine; 39} BCInsLine;
40 40
41/* Info for local variables. Only used during bytecode generation. */
42typedef struct VarInfo {
43 GCRef name; /* Local variable name. */
44 BCPos startpc; /* First point where the local variable is active. */
45 BCPos endpc; /* First point where the local variable is dead. */
46} VarInfo;
47
41/* Lua lexer state. */ 48/* Lua lexer state. */
42typedef struct LexState { 49typedef struct LexState {
43 struct FuncState *fs; /* Current FuncState. Defined in lj_parse.c. */ 50 struct FuncState *fs; /* Current FuncState. Defined in lj_parse.c. */
diff --git a/src/lj_obj.h b/src/lj_obj.h
index 6d6782b4..e85cf703 100644
--- a/src/lj_obj.h
+++ b/src/lj_obj.h
@@ -286,12 +286,6 @@ typedef struct GCcdataVar {
286#define SCALE_NUM_GCO ((int32_t)sizeof(lua_Number)/sizeof(GCRef)) 286#define SCALE_NUM_GCO ((int32_t)sizeof(lua_Number)/sizeof(GCRef))
287#define round_nkgc(n) (((n) + SCALE_NUM_GCO-1) & ~(SCALE_NUM_GCO-1)) 287#define round_nkgc(n) (((n) + SCALE_NUM_GCO-1) & ~(SCALE_NUM_GCO-1))
288 288
289typedef struct VarInfo {
290 GCRef name; /* Local variable name. */
291 BCPos startpc; /* First point where the local variable is active. */
292 BCPos endpc; /* First point where the local variable is dead. */
293} VarInfo;
294
295typedef struct GCproto { 289typedef struct GCproto {
296 GCHeader; 290 GCHeader;
297 uint8_t numparams; /* Number of parameters. */ 291 uint8_t numparams; /* Number of parameters. */
@@ -308,11 +302,11 @@ typedef struct GCproto {
308 uint16_t trace; /* Anchor for chain of root traces. */ 302 uint16_t trace; /* Anchor for chain of root traces. */
309 /* ------ The following fields are for debugging/tracebacks only ------ */ 303 /* ------ The following fields are for debugging/tracebacks only ------ */
310 GCRef chunkname; /* Name of the chunk this function was defined in. */ 304 GCRef chunkname; /* Name of the chunk this function was defined in. */
311 BCLine lastlinedefined; /* Last line of the function definition. */ 305 BCLine firstline; /* First line of the function definition. */
312 MSize sizevarinfo; /* Size of local var info array. */ 306 BCLine numline; /* Number of lines for the function definition. */
313 MRef varinfo; /* Names and extents of local variables. */ 307 MRef lineinfo; /* Compressed map from bytecode ins. to source line. */
314 MRef uvname; /* Array of upvalue names (GCRef of GCstr). */ 308 MRef uvinfo; /* Upvalue names. */
315 MRef lineinfo; /* Map from bytecode instructions to source lines. */ 309 MRef varinfo; /* Names and compressed extents of local variables. */
316} GCproto; 310} GCproto;
317 311
318#define PROTO_IS_VARARG 0x01 312#define PROTO_IS_VARARG 0x01
@@ -331,14 +325,11 @@ typedef struct GCproto {
331#define proto_bcpos(pt, pc) ((BCPos)((pc) - proto_bc(pt))) 325#define proto_bcpos(pt, pc) ((BCPos)((pc) - proto_bc(pt)))
332#define proto_uv(pt) (mref((pt)->uv, uint16_t)) 326#define proto_uv(pt) (mref((pt)->uv, uint16_t))
333 327
334#define proto_uvname(pt, idx) \ 328#define proto_chunkname(pt) (strref((pt)->chunkname))
335 check_exp((uintptr_t)(idx) < (pt)->sizeuv, \ 329#define proto_chunknamestr(pt) (strdata(proto_chunkname((pt))))
336 gco2str(gcref(mref((pt)->uvname, GCRef)[(idx)]))) 330#define proto_lineinfo(pt) (mref((pt)->lineinfo, const void))
337#define proto_chunkname(pt) (gco2str(gcref((pt)->chunkname))) 331#define proto_uvinfo(pt) (mref((pt)->uvinfo, const uint8_t))
338#define proto_lineinfo(pt) (mref((pt)->lineinfo, BCLine)) 332#define proto_varinfo(pt) (mref((pt)->varinfo, const uint8_t))
339#define proto_line(pt, pos) \
340 check_exp((uintptr_t)(pos) < (pt)->sizebc, proto_lineinfo(pt)[(pos)])
341#define proto_varinfo(pt) (mref((pt)->varinfo, VarInfo))
342 333
343/* -- Upvalue object ------------------------------------------------------ */ 334/* -- Upvalue object ------------------------------------------------------ */
344 335
diff --git a/src/lj_parse.c b/src/lj_parse.c
index 992034eb..bd9d9a7a 100644
--- a/src/lj_parse.c
+++ b/src/lj_parse.c
@@ -12,6 +12,7 @@
12#include "lj_obj.h" 12#include "lj_obj.h"
13#include "lj_gc.h" 13#include "lj_gc.h"
14#include "lj_err.h" 14#include "lj_err.h"
15#include "lj_debug.h"
15#include "lj_str.h" 16#include "lj_str.h"
16#include "lj_tab.h" 17#include "lj_tab.h"
17#include "lj_func.h" 18#include "lj_func.h"
@@ -1021,7 +1022,8 @@ static void var_new(LexState *ls, BCReg n, GCstr *name)
1021 lj_lex_error(ls, 0, LJ_ERR_XLIMC, LJ_MAX_VSTACK); 1022 lj_lex_error(ls, 0, LJ_ERR_XLIMC, LJ_MAX_VSTACK);
1022 lj_mem_growvec(ls->L, ls->vstack, ls->sizevstack, LJ_MAX_VSTACK, VarInfo); 1023 lj_mem_growvec(ls->L, ls->vstack, ls->sizevstack, LJ_MAX_VSTACK, VarInfo);
1023 } 1024 }
1024 lua_assert(lj_tab_getstr(fs->kt, name) != NULL); 1025 lua_assert((uintptr_t)name < VARNAME__MAX ||
1026 lj_tab_getstr(fs->kt, name) != NULL);
1025 /* NOBARRIER: name is anchored in fs->kt and ls->vstack is not a GCobj. */ 1027 /* NOBARRIER: name is anchored in fs->kt and ls->vstack is not a GCobj. */
1026 setgcref(ls->vstack[vtop].name, obj2gco(name)); 1028 setgcref(ls->vstack[vtop].name, obj2gco(name));
1027 fs->varmap[fs->nactvar+n] = (uint16_t)vtop; 1029 fs->varmap[fs->nactvar+n] = (uint16_t)vtop;
@@ -1031,6 +1033,9 @@ static void var_new(LexState *ls, BCReg n, GCstr *name)
1031#define var_new_lit(ls, n, v) \ 1033#define var_new_lit(ls, n, v) \
1032 var_new(ls, (n), lj_parse_keepstr(ls, "" v, sizeof(v)-1)) 1034 var_new(ls, (n), lj_parse_keepstr(ls, "" v, sizeof(v)-1))
1033 1035
1036#define var_new_fixed(ls, n, vn) \
1037 var_new(ls, (n), (GCstr *)(uintptr_t)(vn))
1038
1034/* Add local variables. */ 1039/* Add local variables. */
1035static void var_add(LexState *ls, BCReg nvars) 1040static void var_add(LexState *ls, BCReg nvars)
1036{ 1041{
@@ -1053,7 +1058,7 @@ static BCReg var_lookup_local(FuncState *fs, GCstr *n)
1053{ 1058{
1054 int i; 1059 int i;
1055 for (i = fs->nactvar-1; i >= 0; i--) { 1060 for (i = fs->nactvar-1; i >= 0; i--) {
1056 if (n == gco2str(gcref(var_get(fs->ls, fs, i).name))) 1061 if (n == strref(var_get(fs->ls, fs, i).name))
1057 return (BCReg)i; 1062 return (BCReg)i;
1058 } 1063 }
1059 return (BCReg)-1; /* Not found. */ 1064 return (BCReg)-1; /* Not found. */
@@ -1109,23 +1114,16 @@ static MSize var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first)
1109 1114
1110/* -- Function state management ------------------------------------------- */ 1115/* -- Function state management ------------------------------------------- */
1111 1116
1112/* NYI: compress debug info. */ 1117/* Fixup bytecode for prototype. */
1113 1118static void fs_fixup_bc(FuncState *fs, GCproto *pt, BCIns *bc, MSize n)
1114/* Fixup bytecode and lineinfo for prototype. */
1115static void fs_fixup_bc(FuncState *fs, GCproto *pt, BCIns *bc, BCLine *lineinfo)
1116{ 1119{
1117 MSize i, n = fs->pc;
1118 BCInsLine *base = fs->bcbase; 1120 BCInsLine *base = fs->bcbase;
1119 setmref(pt->lineinfo, lineinfo); 1121 MSize i;
1120 pt->sizebc = n; 1122 pt->sizebc = n;
1121 bc[n] = ~0u; /* Close potentially uninitialized gap between bc and kgc. */
1122 bc[0] = BCINS_AD((fs->flags & PROTO_IS_VARARG) ? BC_FUNCV : BC_FUNCF, 1123 bc[0] = BCINS_AD((fs->flags & PROTO_IS_VARARG) ? BC_FUNCV : BC_FUNCF,
1123 fs->framesize, 0); 1124 fs->framesize, 0);
1124 lineinfo[0] = fs->linedefined; 1125 for (i = 1; i < n; i++)
1125 for (i = 1; i < n; i++) {
1126 bc[i] = base[i].ins; 1126 bc[i] = base[i].ins;
1127 lineinfo[i] = base[i].line;
1128 }
1129} 1127}
1130 1128
1131/* Fixup constants for prototype. */ 1129/* Fixup constants for prototype. */
@@ -1189,20 +1187,138 @@ static void fs_fixup_uv(FuncState *fs, GCproto *pt, uint16_t *uv)
1189 uv[i] = fs->uvloc[i].slot; 1187 uv[i] = fs->uvloc[i].slot;
1190} 1188}
1191 1189
1192/* Fixup debug info for prototype. */ 1190#ifndef LUAJIT_DISABLE_DEBUGINFO
1193static void fs_fixup_dbg(FuncState *fs, GCproto *pt, VarInfo *vi, MSize sizevi) 1191/* Prepare lineinfo for prototype. */
1192static size_t fs_prep_line(FuncState *fs, BCLine numline)
1193{
1194 return (fs->pc-1) << (numline < 256 ? 0 : numline < 65536 ? 1 : 2);
1195}
1196
1197/* Fixup lineinfo for prototype. */
1198static void fs_fixup_line(FuncState *fs, GCproto *pt,
1199 void *lineinfo, BCLine numline)
1200{
1201 BCInsLine *base = fs->bcbase + 1;
1202 BCLine first = fs->linedefined;
1203 MSize i = 0, n = fs->pc-1;
1204 pt->firstline = fs->linedefined;
1205 pt->numline = numline;
1206 setmref(pt->lineinfo, lineinfo);
1207 if (LJ_LIKELY(numline < 256)) {
1208 uint8_t *li = (uint8_t *)lineinfo;
1209 do {
1210 BCLine delta = base[i].line - first;
1211 lua_assert(delta >= 0 && delta < 256);
1212 li[i] = (uint8_t)delta;
1213 } while (++i < n);
1214 } else if (LJ_LIKELY(numline < 65536)) {
1215 uint16_t *li = (uint16_t *)lineinfo;
1216 do {
1217 BCLine delta = base[i].line - first;
1218 lua_assert(delta >= 0 && delta < 65536);
1219 li[i] = (uint16_t)delta;
1220 } while (++i < n);
1221 } else {
1222 uint32_t *li = (uint32_t *)lineinfo;
1223 do {
1224 BCLine delta = base[i].line - first;
1225 lua_assert(delta >= 0);
1226 li[i] = (uint32_t)delta;
1227 } while (++i < n);
1228 }
1229}
1230
1231/* Resize buffer if needed. */
1232static LJ_NOINLINE void fs_buf_resize(LexState *ls, MSize len)
1233{
1234 MSize sz = ls->sb.sz * 2;
1235 while (ls->sb.n + len > sz) sz = sz * 2;
1236 lj_str_resizebuf(ls->L, &ls->sb, sz);
1237}
1238
1239static LJ_AINLINE void fs_buf_need(LexState *ls, MSize len)
1240{
1241 if (LJ_UNLIKELY(ls->sb.n + len > ls->sb.sz))
1242 fs_buf_resize(ls, len);
1243}
1244
1245/* Add string to buffer. */
1246static void fs_buf_str(LexState *ls, const char *str, MSize len)
1247{
1248 char *p = ls->sb.buf + ls->sb.n;
1249 MSize i;
1250 ls->sb.n += len;
1251 for (i = 0; i < len; i++) p[i] = str[i];
1252}
1253
1254/* Add ULEB128 value to buffer. */
1255static void fs_buf_uleb128(LexState *ls, uint32_t v)
1256{
1257 MSize n = ls->sb.n;
1258 uint8_t *p = (uint8_t *)ls->sb.buf;
1259 for (; v >= 0x80; v >>= 7)
1260 p[n++] = (uint8_t)((v & 0x7f) | 0x80);
1261 p[n++] = (uint8_t)v;
1262 ls->sb.n = n;
1263}
1264
1265/* Prepare variable info for prototype. */
1266static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar)
1194{ 1267{
1195 MSize i, n = fs->nuv;
1196 GCRef *uvname = (GCRef *)((char *)vi + sizevi*sizeof(VarInfo));
1197 VarInfo *vstack = fs->ls->vstack; 1268 VarInfo *vstack = fs->ls->vstack;
1198 setmref(pt->varinfo, vi); 1269 MSize i, n;
1199 setmref(pt->uvname, uvname); 1270 BCPos lastpc;
1200 pt->sizevarinfo = sizevi; 1271 lj_str_resetbuf(&ls->sb); /* Copy to temp. string buffer. */
1201 memcpy(vi, &vstack[fs->vbase], sizevi*sizeof(VarInfo)); 1272 /* Store upvalue names. */
1202 for (i = 0; i < n; i++) 1273 for (i = 0, n = fs->nuv; i < n; i++) {
1203 setgcref(uvname[i], gcref(vstack[fs->uvloc[i].vidx].name)); 1274 GCstr *s = strref(vstack[fs->uvloc[i].vidx].name);
1275 MSize len = s->len+1;
1276 fs_buf_need(ls, len);
1277 fs_buf_str(ls, strdata(s), len);
1278 }
1279 *ofsvar = ls->sb.n;
1280 vstack += fs->vbase;
1281 lastpc = 0;
1282 /* Store local variable names and compressed ranges. */
1283 for (i = 0, n = ls->vtop - fs->vbase; i < n; i++) {
1284 GCstr *s = strref(vstack[i].name);
1285 BCPos startpc = vstack[i].startpc, endpc = vstack[i].endpc;
1286 if ((uintptr_t)s < VARNAME__MAX) {
1287 fs_buf_need(ls, 1 + 2*5);
1288 ls->sb.buf[ls->sb.n++] = (uint8_t)(uintptr_t)s;
1289 } else {
1290 MSize len = s->len+1;
1291 fs_buf_need(ls, len + 2*5);
1292 fs_buf_str(ls, strdata(s), len);
1293 }
1294 fs_buf_uleb128(ls, startpc-lastpc);
1295 fs_buf_uleb128(ls, endpc-startpc);
1296 lastpc = startpc;
1297 }
1298 fs_buf_need(ls, 1);
1299 ls->sb.buf[ls->sb.n++] = '\0'; /* Terminator for varinfo. */
1300 return ls->sb.n;
1204} 1301}
1205 1302
1303/* Fixup variable info for prototype. */
1304static void fs_fixup_var(LexState *ls, GCproto *pt, uint8_t *p, size_t ofsvar)
1305{
1306 setmref(pt->uvinfo, p);
1307 setmref(pt->varinfo, (char *)p + ofsvar);
1308 memcpy(p, ls->sb.buf, ls->sb.n); /* Copy from temp. string buffer. */
1309}
1310#else
1311
1312/* Initialize with empty debug info, if disabled. */
1313#define fs_prep_line(fs, numline) (UNUSED(numline), 0)
1314#define fs_fixup_line(fs, pt, li, numline) \
1315 pt->firstline = pt->numline = 0, setmref((pt)->lineinfo, NULL)
1316#define fs_prep_var(ls, fs, ofsvar) (UNUSED(ofsvar), 0)
1317#define fs_fixup_var(ls, pt, p, ofsvar) \
1318 setmref((pt)->uvinfo, NULL), setmref((pt)->varinfo, NULL)
1319
1320#endif
1321
1206/* Check if bytecode op returns. */ 1322/* Check if bytecode op returns. */
1207static int bcopisret(BCOp op) 1323static int bcopisret(BCOp op)
1208{ 1324{
@@ -1253,8 +1369,8 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
1253{ 1369{
1254 lua_State *L = ls->L; 1370 lua_State *L = ls->L;
1255 FuncState *fs = ls->fs; 1371 FuncState *fs = ls->fs;
1256 MSize sizevi; 1372 BCLine numline = line - fs->linedefined;
1257 size_t sizept, ofsk, ofsuv, ofsdbg, ofsli; 1373 size_t sizept, ofsk, ofsuv, ofsli, ofsdbg, ofsvar;
1258 GCproto *pt; 1374 GCproto *pt;
1259 1375
1260 /* Apply final fixups. */ 1376 /* Apply final fixups. */
@@ -1264,33 +1380,29 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
1264 1380
1265 /* Calculate total size of prototype including all colocated arrays. */ 1381 /* Calculate total size of prototype including all colocated arrays. */
1266 sizept = sizeof(GCproto) + fs->pc*sizeof(BCIns) + fs->nkgc*sizeof(GCRef); 1382 sizept = sizeof(GCproto) + fs->pc*sizeof(BCIns) + fs->nkgc*sizeof(GCRef);
1267 sizept = (sizept + sizeof(lua_Number)-1) & ~(sizeof(lua_Number)-1); 1383 sizept = (sizept + sizeof(TValue)-1) & ~(sizeof(TValue)-1);
1268 ofsk = sizept; 1384 ofsk = sizept; sizept += fs->nkn*sizeof(TValue);
1269 sizept += fs->nkn*sizeof(lua_Number); 1385 ofsuv = sizept; sizept += ((fs->nuv+1)&~1)*2;
1270 ofsuv = sizept; 1386 ofsli = sizept; sizept += fs_prep_line(fs, numline);
1271 sizept += ((fs->nuv+1)&~1)*2; 1387 ofsdbg = sizept; sizept += fs_prep_var(ls, fs, &ofsvar);
1272 ofsdbg = sizept;
1273 sizevi = ls->vtop - fs->vbase;
1274 sizept += sizevi*sizeof(VarInfo) + fs->nuv*sizeof(GCRef);
1275 ofsli = sizept;
1276 sizept += fs->pc*sizeof(BCLine);
1277 1388
1278 /* Allocate prototype and initialize its fields. */ 1389 /* Allocate prototype and initialize its fields. */
1279 pt = (GCproto *)lj_mem_newgco(L, (MSize)sizept); 1390 pt = (GCproto *)lj_mem_newgco(L, (MSize)sizept);
1280 pt->gct = ~LJ_TPROTO; 1391 pt->gct = ~LJ_TPROTO;
1281 pt->sizept = (MSize)sizept; 1392 pt->sizept = (MSize)sizept;
1282 setgcref(pt->chunkname, obj2gco(ls->chunkname));
1283 pt->trace = 0; 1393 pt->trace = 0;
1284 pt->flags = fs->flags; 1394 pt->flags = fs->flags;
1285 pt->numparams = fs->numparams; 1395 pt->numparams = fs->numparams;
1286 pt->framesize = fs->framesize; 1396 pt->framesize = fs->framesize;
1287 pt->lastlinedefined = line; 1397 setgcref(pt->chunkname, obj2gco(ls->chunkname));
1288 1398
1289 fs_fixup_bc(fs, pt, (BCIns *)((char *)pt + sizeof(GCproto)), 1399 /* Close potentially uninitialized gap between bc and kgc. */
1290 (BCLine *)((char *)pt + ofsli)); 1400 *(uint32_t *)((char *)pt + ofsk - sizeof(GCRef)*(fs->nkgc+1)) = 0;
1401 fs_fixup_bc(fs, pt, (BCIns *)((char *)pt + sizeof(GCproto)), fs->pc);
1291 fs_fixup_k(fs, pt, (void *)((char *)pt + ofsk)); 1402 fs_fixup_k(fs, pt, (void *)((char *)pt + ofsk));
1292 fs_fixup_uv(fs, pt, (uint16_t *)((char *)pt + ofsuv)); 1403 fs_fixup_uv(fs, pt, (uint16_t *)((char *)pt + ofsuv));
1293 fs_fixup_dbg(fs, pt, (VarInfo *)((char *)pt + ofsdbg), sizevi); 1404 fs_fixup_line(fs, pt, (void *)((char *)pt + ofsli), numline);
1405 fs_fixup_var(ls, pt, (uint8_t *)((char *)pt + ofsdbg), ofsvar);
1294 1406
1295 lj_vmevent_send(L, BC, 1407 lj_vmevent_send(L, BC,
1296 setprotoV(L, L->top++, pt); 1408 setprotoV(L, L->top++, pt);
@@ -1300,12 +1412,6 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
1300 ls->vtop = fs->vbase; /* Reset variable stack. */ 1412 ls->vtop = fs->vbase; /* Reset variable stack. */
1301 ls->fs = fs->prev; 1413 ls->fs = fs->prev;
1302 lua_assert(ls->fs != NULL || ls->token == TK_eof); 1414 lua_assert(ls->fs != NULL || ls->token == TK_eof);
1303 /* Re-anchor last string token to avoid GC. */
1304 if (ls->token == TK_name || ls->token == TK_string) {
1305 /* NOBARRIER: the key is new or kept alive. */
1306 TValue *tv = lj_tab_setstr(ls->L, ls->fs->kt, strV(&ls->tokenval));
1307 if (tvisnil(tv)) setboolV(tv, 1);
1308 }
1309 return pt; 1415 return pt;
1310} 1416}
1311 1417
@@ -1530,8 +1636,6 @@ static void parse_chunk(LexState *ls);
1530static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line) 1636static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line)
1531{ 1637{
1532 FuncState fs, *pfs = ls->fs; 1638 FuncState fs, *pfs = ls->fs;
1533 BCReg kidx;
1534 BCLine lastline;
1535 GCproto *pt; 1639 GCproto *pt;
1536 ptrdiff_t oldbase = pfs->bcbase - ls->bcstack; 1640 ptrdiff_t oldbase = pfs->bcbase - ls->bcstack;
1537 fs_init(ls, &fs); 1641 fs_init(ls, &fs);
@@ -1541,19 +1645,19 @@ static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line)
1541 fs.bclim = pfs->bclim - pfs->pc; 1645 fs.bclim = pfs->bclim - pfs->pc;
1542 bcemit_AD(&fs, BC_FUNCF, 0, 0); /* Placeholder. */ 1646 bcemit_AD(&fs, BC_FUNCF, 0, 0); /* Placeholder. */
1543 parse_chunk(ls); 1647 parse_chunk(ls);
1544 lastline = ls->linenumber; 1648 if (ls->token != TK_end) lex_match(ls, TK_end, TK_function, line);
1545 lex_match(ls, TK_end, TK_function, line); 1649 pt = fs_finish(ls, (ls->lastline = ls->linenumber));
1546 pt = fs_finish(ls, lastline);
1547 pfs->bcbase = ls->bcstack + oldbase; /* May have been reallocated. */ 1650 pfs->bcbase = ls->bcstack + oldbase; /* May have been reallocated. */
1548 pfs->bclim = (BCPos)(ls->sizebcstack - oldbase); 1651 pfs->bclim = (BCPos)(ls->sizebcstack - oldbase);
1549 /* Store new prototype in the constant array of the parent. */ 1652 /* Store new prototype in the constant array of the parent. */
1550 kidx = const_gc(pfs, obj2gco(pt), LJ_TPROTO); 1653 expr_init(e, VRELOCABLE,
1551 expr_init(e, VRELOCABLE, bcemit_AD(pfs, BC_FNEW, 0, kidx)); 1654 bcemit_AD(pfs, BC_FNEW, 0, const_gc(pfs, obj2gco(pt), LJ_TPROTO)));
1552 if (!(pfs->flags & PROTO_HAS_FNEW)) { 1655 if (!(pfs->flags & PROTO_HAS_FNEW)) {
1553 if (pfs->flags & PROTO_HAS_RETURN) 1656 if (pfs->flags & PROTO_HAS_RETURN)
1554 pfs->flags |= PROTO_FIXUP_RETURN; 1657 pfs->flags |= PROTO_FIXUP_RETURN;
1555 pfs->flags |= PROTO_HAS_FNEW; 1658 pfs->flags |= PROTO_HAS_FNEW;
1556 } 1659 }
1660 lj_lex_next(ls);
1557} 1661}
1558 1662
1559/* Parse expression list. Last expression is left open. */ 1663/* Parse expression list. Last expression is left open. */
@@ -2146,9 +2250,9 @@ static void parse_for_num(LexState *ls, GCstr *varname, BCLine line)
2146 FuncScope bl; 2250 FuncScope bl;
2147 BCPos loop, loopend; 2251 BCPos loop, loopend;
2148 /* Hidden control variables. */ 2252 /* Hidden control variables. */
2149 var_new_lit(ls, FORL_IDX, "(for index)"); 2253 var_new_fixed(ls, FORL_IDX, VARNAME_FOR_IDX);
2150 var_new_lit(ls, FORL_STOP, "(for limit)"); 2254 var_new_fixed(ls, FORL_STOP, VARNAME_FOR_STOP);
2151 var_new_lit(ls, FORL_STEP, "(for step)"); 2255 var_new_fixed(ls, FORL_STEP, VARNAME_FOR_STEP);
2152 /* Visible copy of index variable. */ 2256 /* Visible copy of index variable. */
2153 var_new(ls, FORL_EXT, varname); 2257 var_new(ls, FORL_EXT, varname);
2154 lex_check(ls, '='); 2258 lex_check(ls, '=');
@@ -2220,9 +2324,9 @@ static void parse_for_iter(LexState *ls, GCstr *indexname)
2220 FuncScope bl; 2324 FuncScope bl;
2221 int isnext; 2325 int isnext;
2222 /* Hidden control variables. */ 2326 /* Hidden control variables. */
2223 var_new_lit(ls, nvars++, "(for generator)"); 2327 var_new_fixed(ls, nvars++, VARNAME_FOR_GEN);
2224 var_new_lit(ls, nvars++, "(for state)"); 2328 var_new_fixed(ls, nvars++, VARNAME_FOR_STATE);
2225 var_new_lit(ls, nvars++, "(for control)"); 2329 var_new_fixed(ls, nvars++, VARNAME_FOR_CTL);
2226 /* Visible variables returned from iterator. */ 2330 /* Visible variables returned from iterator. */
2227 var_new(ls, nvars++, indexname); 2331 var_new(ls, nvars++, indexname);
2228 while (lex_opt(ls, ',')) 2332 while (lex_opt(ls, ','))
@@ -2374,7 +2478,11 @@ GCproto *lj_parse(LexState *ls)
2374 FuncState fs; 2478 FuncState fs;
2375 GCproto *pt; 2479 GCproto *pt;
2376 lua_State *L = ls->L; 2480 lua_State *L = ls->L;
2481#ifdef LUAJIT_DISABLE_DEBUGINFO
2482 ls->chunkname = lj_str_newlit(L, "=");
2483#else
2377 ls->chunkname = lj_str_newz(L, ls->chunkarg); 2484 ls->chunkname = lj_str_newz(L, ls->chunkarg);
2485#endif
2378 setstrV(L, L->top, ls->chunkname); /* Anchor chunkname string. */ 2486 setstrV(L, L->top, ls->chunkname); /* Anchor chunkname string. */
2379 incr_top(L); 2487 incr_top(L);
2380 ls->level = 0; 2488 ls->level = 0;
diff --git a/src/lj_trace.c b/src/lj_trace.c
index 6b1dd2f6..fbd1b45a 100644
--- a/src/lj_trace.c
+++ b/src/lj_trace.c
@@ -98,7 +98,7 @@ static void perftools_addtrace(GCtrace *T)
98 static FILE *fp; 98 static FILE *fp;
99 GCproto *pt = &gcref(T->startpt)->pt; 99 GCproto *pt = &gcref(T->startpt)->pt;
100 const BCIns *startpc = mref(T->startpc, const BCIns); 100 const BCIns *startpc = mref(T->startpc, const BCIns);
101 const char *name = strdata(proto_chunkname(pt)); 101 const char *name = proto_chunknamestr(pt);
102 BCLine lineno; 102 BCLine lineno;
103 if (name[0] == '@' || name[0] == '=') 103 if (name[0] == '@' || name[0] == '=')
104 name++; 104 name++;