summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lgc.c26
-rw-r--r--llimits.h11
-rw-r--r--lobject.h15
-rw-r--r--lstate.h5
-rw-r--r--lstring.c96
-rw-r--r--lstring.h9
-rw-r--r--ltable.c21
-rw-r--r--ltests.c5
-rw-r--r--lvm.c3
9 files changed, 144 insertions, 47 deletions
diff --git a/lgc.c b/lgc.c
index e3fdc9fc..e9dac6c5 100644
--- a/lgc.c
+++ b/lgc.c
@@ -65,7 +65,11 @@
65#define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) 65#define white2gray(x) resetbits(gch(x)->marked, WHITEBITS)
66#define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) 66#define black2gray(x) resetbit(gch(x)->marked, BLACKBIT)
67 67
68#define stringmark(s) ((void)((s) && resetbits((s)->tsv.marked, WHITEBITS))) 68/*
69** dirty trick: we know that 'reallymarkobject' does not use 'g' when
70** object is a string
71*/
72#define stringmark(s) markobject(NULL, s)
69 73
70 74
71#define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) 75#define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT)
@@ -240,18 +244,18 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list,
240 244
241 245
242/* 246/*
243** mark an object. Userdata and closed upvalues are visited and turned 247** mark an object. Userdata, strings, and closed upvalues are visited
244** black here. Strings remain gray (it is the same as making them 248** and turned black here. Other objects are marked gray and added
245** black). Other objects are marked gray and added to appropriate list 249** to appropriate list to be visited (and turned black) later. (Open
246** to be visited (and turned black) later. (Open upvalues are already 250** upvalues are already linked in 'headuv' list.)
247** linked in 'headuv' list.)
248*/ 251*/
249static void reallymarkobject (global_State *g, GCObject *o) { 252static void reallymarkobject (global_State *g, GCObject *o) {
250 lua_assert(iswhite(o) && !isdead(g, o));
251 white2gray(o); 253 white2gray(o);
252 switch (gch(o)->tt) { 254 switch (gch(o)->tt) {
253 case LUA_TSTRING: { 255 case LUA_TSHRSTR:
254 return; /* for strings, gray is as good as black */ 256 case LUA_TLNGSTR: {
257 gray2black(o);
258 return; /* nothing else to mark */
255 } 259 }
256 case LUA_TUSERDATA: { 260 case LUA_TUSERDATA: {
257 Table *mt = gco2u(o)->metatable; 261 Table *mt = gco2u(o)->metatable;
@@ -663,8 +667,10 @@ static void freeobj (lua_State *L, GCObject *o) {
663 case LUA_TTABLE: luaH_free(L, gco2t(o)); break; 667 case LUA_TTABLE: luaH_free(L, gco2t(o)); break;
664 case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; 668 case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break;
665 case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; 669 case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
666 case LUA_TSTRING: { 670 case LUA_TSHRSTR:
667 G(L)->strt.nuse--; 671 G(L)->strt.nuse--;
672 /* go through */
673 case LUA_TLNGSTR: {
668 luaM_freemem(L, o, sizestring(gco2ts(o))); 674 luaM_freemem(L, o, sizestring(gco2ts(o)));
669 break; 675 break;
670 } 676 }
diff --git a/llimits.h b/llimits.h
index 7cf2048b..5466a6b6 100644
--- a/llimits.h
+++ b/llimits.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: llimits.h,v 1.94 2011/11/29 15:39:48 roberto Exp roberto $ 2** $Id: llimits.h,v 1.95 2011/12/06 16:58:36 roberto Exp roberto $
3** Limits, basic types, and some other `installation-dependent' definitions 3** Limits, basic types, and some other `installation-dependent' definitions
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -125,6 +125,15 @@ typedef LUAI_UACNUMBER l_uacNumber;
125 125
126 126
127/* 127/*
128** maximum length for short strings, that is, strings that are
129** internalized. (Cannot be smaller than reserved words or tags
130** for metamethods; #"function" = 8, #"__newindex" = 10; should
131** not be larger than 255, to allow future changes)
132*/
133#define LUA_MAXSHORTLEN (8 * sizeof(void*))
134
135
136/*
128** type for virtual-machine instructions 137** type for virtual-machine instructions
129** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) 138** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
130*/ 139*/
diff --git a/lobject.h b/lobject.h
index a5ace499..568aef3f 100644
--- a/lobject.h
+++ b/lobject.h
@@ -52,6 +52,12 @@
52#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ 52#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */
53 53
54 54
55/*
56** LUA_TSTRING variants */
57#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */
58#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */
59
60
55/* Bit mark for collectable types */ 61/* Bit mark for collectable types */
56#define BIT_ISCOLLECTABLE (1 << 6) 62#define BIT_ISCOLLECTABLE (1 << 6)
57 63
@@ -129,7 +135,9 @@ typedef struct lua_TValue TValue;
129#define ttisnil(o) checktag((o), LUA_TNIL) 135#define ttisnil(o) checktag((o), LUA_TNIL)
130#define ttisboolean(o) checktag((o), LUA_TBOOLEAN) 136#define ttisboolean(o) checktag((o), LUA_TBOOLEAN)
131#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) 137#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA)
132#define ttisstring(o) checktag((o), ctb(LUA_TSTRING)) 138#define ttisstring(o) checktype((o), LUA_TSTRING)
139#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR))
140#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR))
133#define ttistable(o) checktag((o), ctb(LUA_TTABLE)) 141#define ttistable(o) checktag((o), ctb(LUA_TTABLE))
134#define ttisfunction(o) checktype(o, LUA_TFUNCTION) 142#define ttisfunction(o) checktype(o, LUA_TFUNCTION)
135#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) 143#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION)
@@ -199,7 +207,8 @@ typedef struct lua_TValue TValue;
199 207
200#define setsvalue(L,obj,x) \ 208#define setsvalue(L,obj,x) \
201 { TValue *io=(obj); \ 209 { TValue *io=(obj); \
202 val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TSTRING)); \ 210 TString *x_ = (x); \
211 val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \
203 checkliveness(G(L),io); } 212 checkliveness(G(L),io); }
204 213
205#define setuvalue(L,obj,x) \ 214#define setuvalue(L,obj,x) \
@@ -409,7 +418,7 @@ typedef union TString {
409 L_Umaxalign dummy; /* ensures maximum alignment for strings */ 418 L_Umaxalign dummy; /* ensures maximum alignment for strings */
410 struct { 419 struct {
411 CommonHeader; 420 CommonHeader;
412 lu_byte extra; /* reserved words for strings */ 421 lu_byte extra; /* reserved words for short strings; "has hash" for longs */
413 unsigned int hash; 422 unsigned int hash;
414 size_t len; /* number of characters in string */ 423 size_t len; /* number of characters in string */
415 } tsv; 424 } tsv;
diff --git a/lstate.h b/lstate.h
index cff8e202..38a7fb36 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.74 2011/09/30 12:45:07 roberto Exp roberto $ 2** $Id: lstate.h,v 2.75 2012/01/20 22:05:50 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -193,7 +193,8 @@ union GCObject {
193#define gch(o) (&(o)->gch) 193#define gch(o) (&(o)->gch)
194 194
195/* macros to convert a GCObject into a specific value */ 195/* macros to convert a GCObject into a specific value */
196#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) 196#define rawgco2ts(o) \
197 check_exp(novariant((o)->gch.tt) == LUA_TSTRING, &((o)->ts))
197#define gco2ts(o) (&rawgco2ts(o)->tsv) 198#define gco2ts(o) (&rawgco2ts(o)->tsv)
198#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) 199#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
199#define gco2u(o) (&rawgco2u(o)->uv) 200#define gco2u(o) (&rawgco2u(o)->uv)
diff --git a/lstring.c b/lstring.c
index 95a8a6f1..75861cf4 100644
--- a/lstring.c
+++ b/lstring.c
@@ -18,7 +18,37 @@
18#include "lstring.h" 18#include "lstring.h"
19 19
20 20
21/*
22** equality for long strings
23*/
24int luaS_eqlngstr (TString *a, TString *b) {
25 size_t len = a->tsv.len;
26 lua_assert(a->tsv.tt == LUA_TLNGSTR && b->tsv.tt == LUA_TLNGSTR);
27 return (len == b->tsv.len) && (memcmp(getstr(a), getstr(b), len) == 0);
28}
29
30
31/*
32** equality for strings
33*/
34int luaS_eqstr (TString *a, TString *b) {
35 return (a->tsv.tt == b->tsv.tt) &&
36 (a->tsv.tt == LUA_TSHRSTR ? eqshrstr(a, b) : luaS_eqlngstr(a, b));
37}
38
39
40unsigned int luaS_hash (const char *str, size_t l) {
41 unsigned int h = cast(unsigned int, l); /* seed */
42 size_t l1;
43 for (l1 = 0; l1 < l; l1++)
44 h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1]));
45 return h;
46}
47
21 48
49/*
50** resizes the string table
51*/
22void luaS_resize (lua_State *L, int newsize) { 52void luaS_resize (lua_State *L, int newsize) {
23 int i; 53 int i;
24 stringtable *tb = &G(L)->strt; 54 stringtable *tb = &G(L)->strt;
@@ -50,36 +80,47 @@ void luaS_resize (lua_State *L, int newsize) {
50} 80}
51 81
52 82
53static TString *newlstr (lua_State *L, const char *str, size_t l, 83/*
54 unsigned int h) { 84** creates a new string object
55 size_t totalsize; /* total size of TString object */ 85*/
56 GCObject **list; /* (pointer to) list where it will be inserted */ 86static TString *createstrobj (lua_State *L, const char *str, size_t l,
87 int tag, unsigned int h, GCObject **list) {
57 TString *ts; 88 TString *ts;
58 stringtable *tb = &G(L)->strt; 89 size_t totalsize; /* total size of TString object */
59 if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
60 luaM_toobig(L);
61 if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
62 luaS_resize(L, tb->size*2); /* too crowded */
63 totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); 90 totalsize = sizeof(TString) + ((l + 1) * sizeof(char));
64 list = &tb->hash[lmod(h, tb->size)]; 91 ts = &luaC_newobj(L, tag, totalsize, list, 0)->ts;
65 ts = &luaC_newobj(L, LUA_TSTRING, totalsize, list, 0)->ts;
66 ts->tsv.len = l; 92 ts->tsv.len = l;
67 ts->tsv.hash = h; 93 ts->tsv.hash = h;
68 ts->tsv.extra = 0; 94 ts->tsv.extra = 0;
69 memcpy(ts+1, str, l*sizeof(char)); 95 memcpy(ts+1, str, l*sizeof(char));
70 ((char *)(ts+1))[l] = '\0'; /* ending 0 */ 96 ((char *)(ts+1))[l] = '\0'; /* ending 0 */
71 tb->nuse++;
72 return ts; 97 return ts;
73} 98}
74 99
75 100
76TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { 101/*
102** creates a new short string, inserting it into string table
103*/
104static TString *newshrstr (lua_State *L, const char *str, size_t l,
105 unsigned int h) {
106 GCObject **list; /* (pointer to) list where it will be inserted */
107 stringtable *tb = &G(L)->strt;
108 TString *s;
109 if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
110 luaS_resize(L, tb->size*2); /* too crowded */
111 list = &tb->hash[lmod(h, tb->size)];
112 s = createstrobj(L, str, l, LUA_TSHRSTR, h, list);
113 tb->nuse++;
114 return s;
115}
116
117
118/*
119** checks whether short string exists and reuses it or creates a new one
120*/
121static TString *internshrstr (lua_State *L, const char *str, size_t l) {
77 GCObject *o; 122 GCObject *o;
78 unsigned int h = cast(unsigned int, l); /* seed */ 123 unsigned int h = luaS_hash(str, l);
79 size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
80 size_t l1;
81 for (l1=l; l1>=step; l1-=step) /* compute hash */
82 h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
83 for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; 124 for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
84 o != NULL; 125 o != NULL;
85 o = gch(o)->next) { 126 o = gch(o)->next) {
@@ -92,10 +133,27 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
92 return ts; 133 return ts;
93 } 134 }
94 } 135 }
95 return newlstr(L, str, l, h); /* not found; create a new string */ 136 return newshrstr(L, str, l, h); /* not found; create a new string */
96} 137}
97 138
98 139
140/*
141** new string (with explicit length)
142*/
143TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
144 if (l <= LUA_MAXSHORTLEN) /* short string? */
145 return internshrstr(L, str, l);
146 else {
147 if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
148 luaM_toobig(L);
149 return createstrobj(L, str, l, LUA_TLNGSTR, 0, NULL);
150 }
151}
152
153
154/*
155** new zero-terminated string
156*/
99TString *luaS_new (lua_State *L, const char *str) { 157TString *luaS_new (lua_State *L, const char *str) {
100 return luaS_newlstr(L, str, strlen(str)); 158 return luaS_newlstr(L, str, strlen(str));
101} 159}
diff --git a/lstring.h b/lstring.h
index 462bcc87..6cfcbfcc 100644
--- a/lstring.h
+++ b/lstring.h
@@ -25,15 +25,18 @@
25/* 25/*
26** test whether a string is a reserved word 26** test whether a string is a reserved word
27*/ 27*/
28#define isreserved(s) ((s)->tsv.extra > 0) 28#define isreserved(s) ((s)->tsv.tt == LUA_TSHRSTR && (s)->tsv.extra > 0)
29 29
30 30
31/* 31/*
32** equality for strings, which are always internalized 32** equality for short strings, which are always internalized
33*/ 33*/
34#define luaS_eqstr(a,b) ((a) == (b)) 34#define eqshrstr(a,b) check_exp((a)->tsv.tt == LUA_TSHRSTR, (a) == (b))
35 35
36 36
37LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l);
38LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
39LUAI_FUNC int luaS_eqstr (TString *a, TString *b);
37LUAI_FUNC void luaS_resize (lua_State *L, int newsize); 40LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
38LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); 41LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
39LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); 42LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
diff --git a/ltable.c b/ltable.c
index ce740ebe..3683fe60 100644
--- a/ltable.c
+++ b/ltable.c
@@ -50,7 +50,7 @@
50 50
51#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) 51#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
52 52
53#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) 53#define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
54#define hashboolean(t,p) hashpow2(t, p) 54#define hashboolean(t,p) hashpow2(t, p)
55 55
56 56
@@ -98,7 +98,15 @@ static Node *mainposition (const Table *t, const TValue *key) {
98 switch (ttype(key)) { 98 switch (ttype(key)) {
99 case LUA_TNUMBER: 99 case LUA_TNUMBER:
100 return hashnum(t, nvalue(key)); 100 return hashnum(t, nvalue(key));
101 case LUA_TSTRING: 101 case LUA_TLNGSTR: {
102 TString *s = rawtsvalue(key);
103 if (s->tsv.extra == 0) { /* no hash? */
104 s->tsv.hash = luaS_hash(getstr(s), s->tsv.len);
105 s->tsv.extra = 1; /* now it has its hash */
106 }
107 return hashstr(t, rawtsvalue(key));
108 }
109 case LUA_TSHRSTR:
102 return hashstr(t, rawtsvalue(key)); 110 return hashstr(t, rawtsvalue(key));
103 case LUA_TBOOLEAN: 111 case LUA_TBOOLEAN:
104 return hashboolean(t, bvalue(key)); 112 return hashboolean(t, bvalue(key));
@@ -453,12 +461,13 @@ const TValue *luaH_getint (Table *t, int key) {
453 461
454 462
455/* 463/*
456** search function for strings 464** search function for short strings
457*/ 465*/
458const TValue *luaH_getstr (Table *t, TString *key) { 466const TValue *luaH_getstr (Table *t, TString *key) {
459 Node *n = hashstr(t, key); 467 Node *n = hashstr(t, key);
468 lua_assert(key->tsv.tt == LUA_TSHRSTR);
460 do { /* check whether `key' is somewhere in the chain */ 469 do { /* check whether `key' is somewhere in the chain */
461 if (ttisstring(gkey(n)) && luaS_eqstr(rawtsvalue(gkey(n)), key)) 470 if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key))
462 return gval(n); /* that's it */ 471 return gval(n); /* that's it */
463 else n = gnext(n); 472 else n = gnext(n);
464 } while (n); 473 } while (n);
@@ -470,9 +479,9 @@ const TValue *luaH_getstr (Table *t, TString *key) {
470** main search function 479** main search function
471*/ 480*/
472const TValue *luaH_get (Table *t, const TValue *key) { 481const TValue *luaH_get (Table *t, const TValue *key) {
473 switch (ttypenv(key)) { 482 switch (ttype(key)) {
474 case LUA_TNIL: return luaO_nilobject; 483 case LUA_TNIL: return luaO_nilobject;
475 case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); 484 case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key));
476 case LUA_TNUMBER: { 485 case LUA_TNUMBER: {
477 int k; 486 int k;
478 lua_Number n = nvalue(key); 487 lua_Number n = nvalue(key);
diff --git a/ltests.c b/ltests.c
index 7b4c0e17..4b65942b 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 2.124 2011/11/09 19:08:07 roberto Exp roberto $ 2** $Id: ltests.c,v 2.125 2012/01/20 22:05:50 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -360,7 +360,8 @@ static void checkobject (global_State *g, GCObject *o) {
360 checkproto(g, gco2p(o)); 360 checkproto(g, gco2p(o));
361 break; 361 break;
362 } 362 }
363 case LUA_TSTRING: break; 363 case LUA_TSHRSTR:
364 case LUA_TLNGSTR: break;
364 default: lua_assert(0); 365 default: lua_assert(0);
365 } 366 }
366 } 367 }
diff --git a/lvm.c b/lvm.c
index fbc7c45a..3b7e24b7 100644
--- a/lvm.c
+++ b/lvm.c
@@ -258,7 +258,8 @@ int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) {
258 case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ 258 case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
259 case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); 259 case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
260 case LUA_TLCF: return fvalue(t1) == fvalue(t2); 260 case LUA_TLCF: return fvalue(t1) == fvalue(t2);
261 case LUA_TSTRING: return luaS_eqstr(rawtsvalue(t1), rawtsvalue(t2)); 261 case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2));
262 case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2));
262 case LUA_TUSERDATA: { 263 case LUA_TUSERDATA: {
263 if (uvalue(t1) == uvalue(t2)) return 1; 264 if (uvalue(t1) == uvalue(t2)) return 1;
264 else if (L == NULL) return 0; 265 else if (L == NULL) return 0;