diff options
-rw-r--r-- | lcode.c | 20 | ||||
-rw-r--r-- | llex.c | 15 | ||||
-rw-r--r-- | llex.h | 3 | ||||
-rw-r--r-- | lparser.c | 45 | ||||
-rw-r--r-- | lparser.h | 3 | ||||
-rw-r--r-- | ltable.h | 7 |
6 files changed, 47 insertions, 46 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.70 2013/06/20 17:37:31 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.71 2013/06/25 18:57:18 roberto Exp roberto $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -307,17 +307,21 @@ static void freeexp (FuncState *fs, expdesc *e) { | |||
307 | } | 307 | } |
308 | 308 | ||
309 | 309 | ||
310 | /* | ||
311 | ** Use scanner's table to cache position of constants in contant list | ||
312 | ** and try to reuse constants | ||
313 | */ | ||
310 | static int addk (FuncState *fs, TValue *key, TValue *v) { | 314 | static int addk (FuncState *fs, TValue *key, TValue *v) { |
311 | lua_State *L = fs->ls->L; | 315 | lua_State *L = fs->ls->L; |
312 | TValue *idx = luaH_set(L, fs->h, key); | ||
313 | Proto *f = fs->f; | 316 | Proto *f = fs->f; |
317 | TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ | ||
314 | int k, oldsize; | 318 | int k, oldsize; |
315 | if (ttisinteger(idx)) { | 319 | if (ttisinteger(idx)) { /* is there an index there? */ |
316 | k = ivalue(idx); | 320 | k = ivalue(idx); |
317 | if (luaV_rawequalobj(&f->k[k], v)) | 321 | /* correct value? (warning: must distinguish floats from integers!) */ |
318 | return k; | 322 | if (k < fs->nk && ttype(&f->k[k]) == ttype(v) && |
319 | /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); | 323 | luaV_rawequalobj(&f->k[k], v)) |
320 | go through and create a new entry for this value */ | 324 | return k; /* reuse index */ |
321 | } | 325 | } |
322 | /* constant not found; create a new entry */ | 326 | /* constant not found; create a new entry */ |
323 | oldsize = f->sizek; | 327 | oldsize = f->sizek; |
@@ -377,7 +381,7 @@ static int nilK (FuncState *fs) { | |||
377 | TValue k, v; | 381 | TValue k, v; |
378 | setnilvalue(&v); | 382 | setnilvalue(&v); |
379 | /* cannot use nil as key; instead use table itself to represent nil */ | 383 | /* cannot use nil as key; instead use table itself to represent nil */ |
380 | sethvalue(fs->ls->L, &k, fs->h); | 384 | sethvalue(fs->ls->L, &k, fs->ls->h); |
381 | return addk(fs, &k, &v); | 385 | return addk(fs, &k, &v); |
382 | } | 386 | } |
383 | 387 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llex.c,v 2.67 2013/06/19 14:27:00 roberto Exp roberto $ | 2 | ** $Id: llex.c,v 2.68 2013/08/21 20:09:51 roberto Exp roberto $ |
3 | ** Lexical Analyzer | 3 | ** Lexical Analyzer |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -119,22 +119,25 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) { | |||
119 | 119 | ||
120 | 120 | ||
121 | /* | 121 | /* |
122 | ** creates a new string and anchors it in function's table so that | 122 | ** creates a new string and anchors it in scanner's table so that |
123 | ** it will not be collected until the end of the function's compilation | 123 | ** it will not be collected until the end of the compilation |
124 | ** (by that time it should be anchored in function's prototype) | 124 | ** (by that time it should be anchored somewhere) |
125 | */ | 125 | */ |
126 | TString *luaX_newstring (LexState *ls, const char *str, size_t l) { | 126 | TString *luaX_newstring (LexState *ls, const char *str, size_t l) { |
127 | lua_State *L = ls->L; | 127 | lua_State *L = ls->L; |
128 | TValue *o; /* entry for `str' */ | 128 | TValue *o; /* entry for `str' */ |
129 | TString *ts = luaS_newlstr(L, str, l); /* create new string */ | 129 | TString *ts = luaS_newlstr(L, str, l); /* create new string */ |
130 | setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ | 130 | setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ |
131 | o = luaH_set(L, ls->fs->h, L->top - 1); | 131 | o = luaH_set(L, ls->h, L->top - 1); |
132 | if (ttisnil(o)) { /* not in use yet? (see 'addK') */ | 132 | if (ttisnil(o)) { /* not in use yet? */ |
133 | /* boolean value does not need GC barrier; | 133 | /* boolean value does not need GC barrier; |
134 | table has no metatable, so it does not need to invalidate cache */ | 134 | table has no metatable, so it does not need to invalidate cache */ |
135 | setbvalue(o, 1); /* t[string] = true */ | 135 | setbvalue(o, 1); /* t[string] = true */ |
136 | luaC_checkGC(L); | 136 | luaC_checkGC(L); |
137 | } | 137 | } |
138 | else { /* string already present */ | ||
139 | ts = rawtsvalue(keyfromval(o)); /* re-use value previously stored */ | ||
140 | } | ||
138 | L->top--; /* remove string from stack */ | 141 | L->top--; /* remove string from stack */ |
139 | return ts; | 142 | return ts; |
140 | } | 143 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llex.h,v 1.73 2013/04/16 18:46:28 roberto Exp roberto $ | 2 | ** $Id: llex.h,v 1.74 2013/04/26 13:07:53 roberto Exp roberto $ |
3 | ** Lexical Analyzer | 3 | ** Lexical Analyzer |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -60,6 +60,7 @@ typedef struct LexState { | |||
60 | struct lua_State *L; | 60 | struct lua_State *L; |
61 | ZIO *z; /* input stream */ | 61 | ZIO *z; /* input stream */ |
62 | Mbuffer *buff; /* buffer for tokens */ | 62 | Mbuffer *buff; /* buffer for tokens */ |
63 | Table *h; /* to avoid collection/reuse strings */ | ||
63 | struct Dyndata *dyd; /* dynamic structures used by the parser */ | 64 | struct Dyndata *dyd; /* dynamic structures used by the parser */ |
64 | TString *source; /* current source name */ | 65 | TString *source; /* current source name */ |
65 | TString *envn; /* environment variable name */ | 66 | TString *envn; /* environment variable name */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.133 2013/04/26 13:07:53 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.134 2013/08/16 18:55:49 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -35,6 +35,10 @@ | |||
35 | #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) | 35 | #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) |
36 | 36 | ||
37 | 37 | ||
38 | /* because all strings are unified by the scanner, the parser | ||
39 | can use pointer equality for string equality */ | ||
40 | #define eqstr(a,b) ((a) == (b)) | ||
41 | |||
38 | 42 | ||
39 | /* | 43 | /* |
40 | ** nodes for block list (list of active blocks) | 44 | ** nodes for block list (list of active blocks) |
@@ -57,16 +61,6 @@ static void statement (LexState *ls); | |||
57 | static void expr (LexState *ls, expdesc *v); | 61 | static void expr (LexState *ls, expdesc *v); |
58 | 62 | ||
59 | 63 | ||
60 | static void anchor_token (LexState *ls) { | ||
61 | /* last token from outer function must be EOS */ | ||
62 | lua_assert(ls->fs != NULL || ls->t.token == TK_EOS); | ||
63 | if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { | ||
64 | TString *ts = ls->t.seminfo.ts; | ||
65 | luaX_newstring(ls, getstr(ts), ts->tsv.len); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | |||
70 | /* semantic error */ | 64 | /* semantic error */ |
71 | static l_noret semerror (LexState *ls, const char *msg) { | 65 | static l_noret semerror (LexState *ls, const char *msg) { |
72 | ls->t.token = 0; /* remove 'near to' from final message */ | 66 | ls->t.token = 0; /* remove 'near to' from final message */ |
@@ -222,7 +216,7 @@ static int searchupvalue (FuncState *fs, TString *name) { | |||
222 | int i; | 216 | int i; |
223 | Upvaldesc *up = fs->f->upvalues; | 217 | Upvaldesc *up = fs->f->upvalues; |
224 | for (i = 0; i < fs->nups; i++) { | 218 | for (i = 0; i < fs->nups; i++) { |
225 | if (luaS_eqstr(up[i].name, name)) return i; | 219 | if (eqstr(up[i].name, name)) return i; |
226 | } | 220 | } |
227 | return -1; /* not found */ | 221 | return -1; /* not found */ |
228 | } | 222 | } |
@@ -246,7 +240,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { | |||
246 | static int searchvar (FuncState *fs, TString *n) { | 240 | static int searchvar (FuncState *fs, TString *n) { |
247 | int i; | 241 | int i; |
248 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { | 242 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { |
249 | if (luaS_eqstr(n, getlocvar(fs, i)->varname)) | 243 | if (eqstr(n, getlocvar(fs, i)->varname)) |
250 | return i; | 244 | return i; |
251 | } | 245 | } |
252 | return -1; /* not found */ | 246 | return -1; /* not found */ |
@@ -342,7 +336,7 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) { | |||
342 | FuncState *fs = ls->fs; | 336 | FuncState *fs = ls->fs; |
343 | Labellist *gl = &ls->dyd->gt; | 337 | Labellist *gl = &ls->dyd->gt; |
344 | Labeldesc *gt = &gl->arr[g]; | 338 | Labeldesc *gt = &gl->arr[g]; |
345 | lua_assert(luaS_eqstr(gt->name, label->name)); | 339 | lua_assert(eqstr(gt->name, label->name)); |
346 | if (gt->nactvar < label->nactvar) { | 340 | if (gt->nactvar < label->nactvar) { |
347 | TString *vname = getlocvar(fs, gt->nactvar)->varname; | 341 | TString *vname = getlocvar(fs, gt->nactvar)->varname; |
348 | const char *msg = luaO_pushfstring(ls->L, | 342 | const char *msg = luaO_pushfstring(ls->L, |
@@ -369,7 +363,7 @@ static int findlabel (LexState *ls, int g) { | |||
369 | /* check labels in current block for a match */ | 363 | /* check labels in current block for a match */ |
370 | for (i = bl->firstlabel; i < dyd->label.n; i++) { | 364 | for (i = bl->firstlabel; i < dyd->label.n; i++) { |
371 | Labeldesc *lb = &dyd->label.arr[i]; | 365 | Labeldesc *lb = &dyd->label.arr[i]; |
372 | if (luaS_eqstr(lb->name, gt->name)) { /* correct label? */ | 366 | if (eqstr(lb->name, gt->name)) { /* correct label? */ |
373 | if (gt->nactvar > lb->nactvar && | 367 | if (gt->nactvar > lb->nactvar && |
374 | (bl->upval || dyd->label.n > bl->firstlabel)) | 368 | (bl->upval || dyd->label.n > bl->firstlabel)) |
375 | luaK_patchclose(ls->fs, gt->pc, lb->nactvar); | 369 | luaK_patchclose(ls->fs, gt->pc, lb->nactvar); |
@@ -403,7 +397,7 @@ static void findgotos (LexState *ls, Labeldesc *lb) { | |||
403 | Labellist *gl = &ls->dyd->gt; | 397 | Labellist *gl = &ls->dyd->gt; |
404 | int i = ls->fs->bl->firstgoto; | 398 | int i = ls->fs->bl->firstgoto; |
405 | while (i < gl->n) { | 399 | while (i < gl->n) { |
406 | if (luaS_eqstr(gl->arr[i].name, lb->name)) | 400 | if (eqstr(gl->arr[i].name, lb->name)) |
407 | closegoto(ls, i, lb); | 401 | closegoto(ls, i, lb); |
408 | else | 402 | else |
409 | i++; | 403 | i++; |
@@ -525,7 +519,6 @@ static void codeclosure (LexState *ls, expdesc *v) { | |||
525 | 519 | ||
526 | 520 | ||
527 | static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { | 521 | static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { |
528 | lua_State *L = ls->L; | ||
529 | Proto *f; | 522 | Proto *f; |
530 | fs->prev = ls->fs; /* linked list of funcstates */ | 523 | fs->prev = ls->fs; /* linked list of funcstates */ |
531 | fs->ls = ls; | 524 | fs->ls = ls; |
@@ -544,10 +537,6 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { | |||
544 | f = fs->f; | 537 | f = fs->f; |
545 | f->source = ls->source; | 538 | f->source = ls->source; |
546 | f->maxstacksize = 2; /* registers 0/1 are always valid */ | 539 | f->maxstacksize = 2; /* registers 0/1 are always valid */ |
547 | fs->h = luaH_new(L); | ||
548 | /* anchor table of constants (to avoid being collected) */ | ||
549 | sethvalue2s(L, L->top, fs->h); | ||
550 | incr_top(L); | ||
551 | enterblock(fs, bl, 0); | 540 | enterblock(fs, bl, 0); |
552 | } | 541 | } |
553 | 542 | ||
@@ -572,9 +561,6 @@ static void close_func (LexState *ls) { | |||
572 | f->sizeupvalues = fs->nups; | 561 | f->sizeupvalues = fs->nups; |
573 | lua_assert(fs->bl == NULL); | 562 | lua_assert(fs->bl == NULL); |
574 | ls->fs = fs->prev; | 563 | ls->fs = fs->prev; |
575 | /* last token read was anchored in defunct function; must re-anchor it */ | ||
576 | anchor_token(ls); | ||
577 | L->top--; /* pop table of constants */ | ||
578 | luaC_checkGC(L); | 564 | luaC_checkGC(L); |
579 | } | 565 | } |
580 | 566 | ||
@@ -1202,7 +1188,7 @@ static void gotostat (LexState *ls, int pc) { | |||
1202 | static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { | 1188 | static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { |
1203 | int i; | 1189 | int i; |
1204 | for (i = fs->bl->firstlabel; i < ll->n; i++) { | 1190 | for (i = fs->bl->firstlabel; i < ll->n; i++) { |
1205 | if (luaS_eqstr(label, ll->arr[i].name)) { | 1191 | if (eqstr(label, ll->arr[i].name)) { |
1206 | const char *msg = luaO_pushfstring(fs->ls->L, | 1192 | const char *msg = luaO_pushfstring(fs->ls->L, |
1207 | "label " LUA_QS " already defined on line %d", | 1193 | "label " LUA_QS " already defined on line %d", |
1208 | getstr(label), ll->arr[i].line); | 1194 | getstr(label), ll->arr[i].line); |
@@ -1627,8 +1613,10 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | |||
1627 | LexState lexstate; | 1613 | LexState lexstate; |
1628 | FuncState funcstate; | 1614 | FuncState funcstate; |
1629 | Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ | 1615 | Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ |
1630 | /* anchor closure (to avoid being collected) */ | 1616 | setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */ |
1631 | setclLvalue(L, L->top, cl); | 1617 | incr_top(L); |
1618 | lexstate.h = luaH_new(L); /* create table for scanner */ | ||
1619 | sethvalue(L, L->top, lexstate.h); /* anchor it */ | ||
1632 | incr_top(L); | 1620 | incr_top(L); |
1633 | funcstate.f = cl->l.p = luaF_newproto(L); | 1621 | funcstate.f = cl->l.p = luaF_newproto(L); |
1634 | funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ | 1622 | funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ |
@@ -1641,6 +1629,7 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | |||
1641 | lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); | 1629 | lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); |
1642 | /* all scopes should be correctly finished */ | 1630 | /* all scopes should be correctly finished */ |
1643 | lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); | 1631 | lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); |
1644 | return cl; /* it's on the stack too */ | 1632 | L->top--; /* remove scanner's table */ |
1633 | return cl; /* closure is on the stack, too */ | ||
1645 | } | 1634 | } |
1646 | 1635 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.h,v 1.70 2012/05/08 13:53:33 roberto Exp roberto $ | 2 | ** $Id: lparser.h,v 1.71 2013/04/16 18:46:28 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -97,7 +97,6 @@ struct BlockCnt; /* defined in lparser.c */ | |||
97 | /* state needed to generate code for a given function */ | 97 | /* state needed to generate code for a given function */ |
98 | typedef struct FuncState { | 98 | typedef struct FuncState { |
99 | Proto *f; /* current function header */ | 99 | Proto *f; /* current function header */ |
100 | Table *h; /* table to find (and reuse) elements in `k' */ | ||
101 | struct FuncState *prev; /* enclosing function */ | 100 | struct FuncState *prev; /* enclosing function */ |
102 | struct LexState *ls; /* lexical state */ | 101 | struct LexState *ls; /* lexical state */ |
103 | struct BlockCnt *bl; /* chain of current blocks */ | 102 | struct BlockCnt *bl; /* chain of current blocks */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.h,v 2.16 2011/08/17 20:26:47 roberto Exp roberto $ | 2 | ** $Id: ltable.h,v 2.17 2013/04/26 15:39:25 roberto Exp roberto $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -18,6 +18,11 @@ | |||
18 | #define invalidateTMcache(t) ((t)->flags = 0) | 18 | #define invalidateTMcache(t) ((t)->flags = 0) |
19 | 19 | ||
20 | 20 | ||
21 | /* returns the key, given the value of a table entry */ | ||
22 | #define keyfromval(v) \ | ||
23 | (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) | ||
24 | |||
25 | |||
21 | LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); | 26 | LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); |
22 | LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, | 27 | LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, |
23 | TValue *value); | 28 | TValue *value); |