Browse Source

Growth factor of 1.5 for stack and lexical buffer

Roberto Ierusalimschy 4 months ago
parent
commit
f4123b2fc2
3 changed files with 11 additions and 11 deletions
  1. 7 7
      lauxlib.c
  2. 1 1
      ldo.c
  3. 3 3
      llex.c

+ 7 - 7
lauxlib.c

@@ -541,17 +541,17 @@ static void newbox (lua_State *L) {
 
 
 /*
 /*
 ** Compute new size for buffer 'B', enough to accommodate extra 'sz'
 ** Compute new size for buffer 'B', enough to accommodate extra 'sz'
-** bytes plus one for a terminating zero. (The test for "not big enough"
-** also gets the case when the computation of 'newsize' overflows.)
+** bytes plus one for a terminating zero.
 */
 */
 static size_t newbuffsize (luaL_Buffer *B, size_t sz) {
 static size_t newbuffsize (luaL_Buffer *B, size_t sz) {
-  size_t newsize = (B->size / 2) * 3;  /* buffer size * 1.5 */
-  if (l_unlikely(sz > MAX_SIZE - B->n - 1))
+  size_t newsize = B->size;
+  if (l_unlikely(sz >= MAX_SIZE - B->n))
     return cast_sizet(luaL_error(B->L, "resulting string too large"));
     return cast_sizet(luaL_error(B->L, "resulting string too large"));
-  if (newsize < B->n + sz + 1 || newsize > MAX_SIZE) {
-    /* newsize was not big enough or too big */
+  /* else  B->n + sz + 1 <= MAX_SIZE */
+  if (newsize <= MAX_SIZE/3 * 2)  /* no overflow? */
+    newsize += (newsize >> 1);  /* new size *= 1.5 */
+  if (newsize < B->n + sz + 1)  /* not big enough? */
     newsize = B->n + sz + 1;
     newsize = B->n + sz + 1;
-  }
   return newsize;
   return newsize;
 }
 }
 
 

+ 1 - 1
ldo.c

@@ -319,7 +319,7 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) {
     return 0;  /* if not 'raiseerror', just signal it */
     return 0;  /* if not 'raiseerror', just signal it */
   }
   }
   else if (n < MAXSTACK) {  /* avoids arithmetic overflows */
   else if (n < MAXSTACK) {  /* avoids arithmetic overflows */
-    int newsize = 2 * size;  /* tentative new size */
+    int newsize = size + (size >> 1);  /* tentative new size (size * 1.5) */
     int needed = cast_int(L->top.p - L->stack.p) + n;
     int needed = cast_int(L->top.p - L->stack.p) + n;
     if (newsize > MAXSTACK)  /* cannot cross the limit */
     if (newsize > MAXSTACK)  /* cannot cross the limit */
       newsize = MAXSTACK;
       newsize = MAXSTACK;

+ 3 - 3
llex.c

@@ -62,10 +62,10 @@ static l_noret lexerror (LexState *ls, const char *msg, int token);
 static void save (LexState *ls, int c) {
 static void save (LexState *ls, int c) {
   Mbuffer *b = ls->buff;
   Mbuffer *b = ls->buff;
   if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) {
   if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) {
-    size_t newsize;
-    if (luaZ_sizebuffer(b) >= MAX_SIZE/2)
+    size_t newsize = luaZ_sizebuffer(b);  /* get old size */;
+    if (newsize >= (MAX_SIZE/3 * 2))  /* larger than MAX_SIZE/1.5 ? */
       lexerror(ls, "lexical element too long", 0);
       lexerror(ls, "lexical element too long", 0);
-    newsize = luaZ_sizebuffer(b) * 2;
+    newsize += (newsize >> 1);  /* new size is 1.5 times the old one */
     luaZ_resizebuffer(ls->L, b, newsize);
     luaZ_resizebuffer(ls->L, b, newsize);
   }
   }
   b->buffer[luaZ_bufflen(b)++] = cast_char(c);
   b->buffer[luaZ_bufflen(b)++] = cast_char(c);