diff --git a/src/lstring.c b/src/lstring.c
index a84cfab..601974b 100644
--- a/src/lstring.c
+++ b/src/lstring.c
@@ -20,30 +20,32 @@
 
 
 void luaS_resize (lua_State *L, int newsize) {
-  GCObject **newhash;
   stringtable *tb;
   int i;
-  if (G(L)->gcstate == GCSsweepstring)
-    return;  /* cannot resize during GC traverse */
-  newhash = luaM_newvector(L, newsize, GCObject *);
   tb = &G(L)->strt;
-  for (i=0; i<newsize; i++) newhash[i] = NULL;
+  if (G(L)->gcstate == GCSsweepstring || newsize == tb->size)
+    return;  /* cannot resize during GC traverse or doesn't need to be resized */
+  if (newsize > tb->size) {
+    luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *);
+    for (i=tb->size; i<newsize; i++) tb->hash[i] = NULL;
+  }
   /* rehash */
   for (i=0; i<tb->size; i++) {
     GCObject *p = tb->hash[i];
+    tb->hash[i] = NULL;
     while (p) {  /* for each node in the list */
       GCObject *next = p->gch.next;  /* save next */
       unsigned int h = gco2ts(p)->hash;
       int h1 = lmod(h, newsize);  /* new position */
       lua_assert(cast_int(h%newsize) == lmod(h, newsize));
-      p->gch.next = newhash[h1];  /* chain it */
-      newhash[h1] = p;
+      p->gch.next = tb->hash[h1];  /* chain it */
+      tb->hash[h1] = p;
       p = next;
     }
   }
-  luaM_freearray(L, tb->hash, tb->size, TString *);
+  if (newsize < tb->size)
+    luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *);
   tb->size = newsize;
-  tb->hash = newhash;
 }
 
 
