diff options
Diffstat (limited to 'apps/plugins/lua/lstring.c')
-rw-r--r-- | apps/plugins/lua/lstring.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/apps/plugins/lua/lstring.c b/apps/plugins/lua/lstring.c index bf0536e311..6d73f1e9ea 100644 --- a/apps/plugins/lua/lstring.c +++ b/apps/plugins/lua/lstring.c | |||
@@ -22,30 +22,34 @@ | |||
22 | 22 | ||
23 | 23 | ||
24 | void luaS_resize (lua_State *L, int newsize) { | 24 | void luaS_resize (lua_State *L, int newsize) { |
25 | GCObject **newhash; | ||
26 | stringtable *tb; | 25 | stringtable *tb; |
27 | int i; | 26 | int i; |
28 | if (G(L)->gcstate == GCSsweepstring) | ||
29 | return; /* cannot resize during GC traverse */ | ||
30 | newhash = luaM_newvector(L, newsize, GCObject *); | ||
31 | tb = &G(L)->strt; | 27 | tb = &G(L)->strt; |
32 | for (i=0; i<newsize; i++) newhash[i] = NULL; | 28 | if (luaC_sweepstrgc(L) || newsize == tb->size || is_resizing_strings_gc(L)) |
29 | return; /* cannot resize during GC traverse or doesn't need to be resized */ | ||
30 | set_resizing_strings_gc(L); | ||
31 | if (newsize > tb->size) { | ||
32 | luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); | ||
33 | for (i=tb->size; i<newsize; i++) tb->hash[i] = NULL; | ||
34 | } | ||
33 | /* rehash */ | 35 | /* rehash */ |
34 | for (i=0; i<tb->size; i++) { | 36 | for (i=0; i<tb->size; i++) { |
35 | GCObject *p = tb->hash[i]; | 37 | GCObject *p = tb->hash[i]; |
38 | tb->hash[i] = NULL; | ||
36 | while (p) { /* for each node in the list */ | 39 | while (p) { /* for each node in the list */ |
37 | GCObject *next = p->gch.next; /* save next */ | 40 | GCObject *next = p->gch.next; /* save next */ |
38 | unsigned int h = gco2ts(p)->hash; | 41 | unsigned int h = gco2ts(p)->hash; |
39 | int h1 = lmod(h, newsize); /* new position */ | 42 | int h1 = lmod(h, newsize); /* new position */ |
40 | lua_assert(cast_int(h%newsize) == lmod(h, newsize)); | 43 | lua_assert(cast_int(h%newsize) == lmod(h, newsize)); |
41 | p->gch.next = newhash[h1]; /* chain it */ | 44 | p->gch.next = tb->hash[h1]; /* chain it */ |
42 | newhash[h1] = p; | 45 | tb->hash[h1] = p; |
43 | p = next; | 46 | p = next; |
44 | } | 47 | } |
45 | } | 48 | } |
46 | luaM_freearray(L, tb->hash, tb->size, TString *); | 49 | if (newsize < tb->size) |
50 | luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); | ||
47 | tb->size = newsize; | 51 | tb->size = newsize; |
48 | tb->hash = newhash; | 52 | unset_resizing_strings_gc(L); |
49 | } | 53 | } |
50 | 54 | ||
51 | 55 | ||
@@ -55,6 +59,9 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, | |||
55 | stringtable *tb; | 59 | stringtable *tb; |
56 | if (l > ((MAX_SIZET - sizeof(TString))/sizeof(char)) - sizeof("")) | 60 | if (l > ((MAX_SIZET - sizeof(TString))/sizeof(char)) - sizeof("")) |
57 | luaM_toobig(L); | 61 | luaM_toobig(L); |
62 | tb = &G(L)->strt; | ||
63 | if ((tb->nuse + 1) > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) | ||
64 | luaS_resize(L, tb->size*2); /* too crowded */ | ||
58 | ts = cast(TString *, luaM_malloc(L, sizetstring(type, l))); | 65 | ts = cast(TString *, luaM_malloc(L, sizetstring(type, l))); |
59 | ts->tsv.len = l; | 66 | ts->tsv.len = l; |
60 | ts->tsv.hash = h; | 67 | ts->tsv.hash = h; |
@@ -70,13 +77,10 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, | |||
70 | memcpy(ts+1, str, l*sizeof(char)); | 77 | memcpy(ts+1, str, l*sizeof(char)); |
71 | ((char *)(ts+1))[l] = '\0'; /* ending 0 */ | 78 | ((char *)(ts+1))[l] = '\0'; /* ending 0 */ |
72 | } | 79 | } |
73 | tb = &G(L)->strt; | ||
74 | h = lmod(h, tb->size); | 80 | h = lmod(h, tb->size); |
75 | ts->tsv.next = tb->hash[h]; /* chain new entry */ | 81 | ts->tsv.next = tb->hash[h]; /* chain new entry */ |
76 | tb->hash[h] = obj2gco(ts); | 82 | tb->hash[h] = obj2gco(ts); |
77 | tb->nuse++; | 83 | tb->nuse++; |
78 | if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) | ||
79 | luaS_resize(L, tb->size*2); /* too crowded */ | ||
80 | return ts; | 84 | return ts; |
81 | } | 85 | } |
82 | 86 | ||