long strings are created directly in final position when possible

(instead of using an auxiliar buffer to first create the string
and then allocate the final string and copy result there)
This commit is contained in:
Roberto Ierusalimschy 2015-09-08 12:41:05 -03:00
parent 502214f8a5
commit 41964648ee
11 changed files with 62 additions and 58 deletions

4
ldo.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldo.c,v 2.138 2015/05/22 17:48:19 roberto Exp roberto $ ** $Id: ldo.c,v 2.139 2015/06/18 14:19:52 roberto Exp roberto $
** Stack and Call structure of Lua ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -684,7 +684,7 @@ static void f_parser (lua_State *L, void *ud) {
int c = zgetc(p->z); /* read first character */ int c = zgetc(p->z); /* read first character */
if (c == LUA_SIGNATURE[0]) { if (c == LUA_SIGNATURE[0]) {
checkmode(L, p->mode, "binary"); checkmode(L, p->mode, "binary");
cl = luaU_undump(L, p->z, &p->buff, p->name); cl = luaU_undump(L, p->z, p->name);
} }
else { else {
checkmode(L, p->mode, "text"); checkmode(L, p->mode, "text");

5
lgc.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lgc.c,v 2.205 2015/03/25 13:42:19 roberto Exp roberto $ ** $Id: lgc.c,v 2.206 2015/07/13 13:30:03 roberto Exp roberto $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -769,12 +769,11 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) {
*/ */
/* /*
** If possible, free concatenation buffer and shrink string table ** If possible, shrink string table
*/ */
static void checkSizes (lua_State *L, global_State *g) { static void checkSizes (lua_State *L, global_State *g) {
if (g->gckind != KGC_EMERGENCY) { if (g->gckind != KGC_EMERGENCY) {
l_mem olddebt = g->GCdebt; l_mem olddebt = g->GCdebt;
luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */
if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ if (g->strt.nuse < g->strt.size / 4) /* string table too big? */
luaS_resize(L, g->strt.size / 2); /* shrink it a little */ luaS_resize(L, g->strt.size / 2); /* shrink it a little */
g->GCestimate += g->GCdebt - olddebt; /* update estimate */ g->GCestimate += g->GCdebt - olddebt; /* update estimate */

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstate.c,v 2.128 2015/03/04 13:31:21 roberto Exp roberto $ ** $Id: lstate.c,v 2.129 2015/07/13 13:30:03 roberto Exp roberto $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -241,7 +241,6 @@ static void close_state (lua_State *L) {
if (g->version) /* closing a fully built state? */ if (g->version) /* closing a fully built state? */
luai_userstateclose(L); luai_userstateclose(L);
luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
luaZ_freebuffer(L, &g->buff);
freestack(L); freestack(L);
lua_assert(gettotalbytes(g) == sizeof(LG)); lua_assert(gettotalbytes(g) == sizeof(LG));
(*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */
@ -310,7 +309,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->strt.size = g->strt.nuse = 0; g->strt.size = g->strt.nuse = 0;
g->strt.hash = NULL; g->strt.hash = NULL;
setnilvalue(&g->l_registry); setnilvalue(&g->l_registry);
luaZ_initbuffer(L, &g->buff);
g->panic = NULL; g->panic = NULL;
g->version = NULL; g->version = NULL;
g->gcstate = GCSpause; g->gcstate = GCSpause;

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstate.h,v 2.122 2015/06/01 16:34:37 roberto Exp roberto $ ** $Id: lstate.h,v 2.123 2015/07/04 16:33:17 roberto Exp roberto $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -131,7 +131,6 @@ typedef struct global_State {
GCObject *tobefnz; /* list of userdata to be GC */ GCObject *tobefnz; /* list of userdata to be GC */
GCObject *fixedgc; /* list of objects not to be collected */ GCObject *fixedgc; /* list of objects not to be collected */
struct lua_State *twups; /* list of threads with open upvalues */ struct lua_State *twups; /* list of threads with open upvalues */
Mbuffer buff; /* temporary buffer for string concatenation */
unsigned int gcfinnum; /* number of finalizers to call in each GC step */ unsigned int gcfinnum; /* number of finalizers to call in each GC step */
int gcpause; /* size of pause between successive GCs */ int gcpause; /* size of pause between successive GCs */
int gcstepmul; /* GC 'granularity' */ int gcstepmul; /* GC 'granularity' */

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstring.c,v 2.49 2015/06/01 16:34:37 roberto Exp roberto $ ** $Id: lstring.c,v 2.50 2015/06/18 14:20:32 roberto Exp roberto $
** String table (keeps all strings handled by Lua) ** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -119,8 +119,7 @@ void luaS_init (lua_State *L) {
/* /*
** creates a new string object ** creates a new string object
*/ */
static TString *createstrobj (lua_State *L, const char *str, size_t l, static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {
int tag, unsigned int h) {
TString *ts; TString *ts;
GCObject *o; GCObject *o;
size_t totalsize; /* total size of TString object */ size_t totalsize; /* total size of TString object */
@ -129,12 +128,18 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l,
ts = gco2ts(o); ts = gco2ts(o);
ts->hash = h; ts->hash = h;
ts->extra = 0; ts->extra = 0;
memcpy(getaddrstr(ts), str, l * sizeof(char));
getaddrstr(ts)[l] = '\0'; /* ending 0 */ getaddrstr(ts)[l] = '\0'; /* ending 0 */
return ts; return ts;
} }
TString *luaS_createlngstrobj (lua_State *L, size_t l) {
TString *ts = createstrobj(L, l, LUA_TLNGSTR, G(L)->seed);
ts->u.lnglen = l;
return ts;
}
void luaS_remove (lua_State *L, TString *ts) { void luaS_remove (lua_State *L, TString *ts) {
stringtable *tb = &G(L)->strt; stringtable *tb = &G(L)->strt;
TString **p = &tb->hash[lmod(ts->hash, tb->size)]; TString **p = &tb->hash[lmod(ts->hash, tb->size)];
@ -166,7 +171,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
luaS_resize(L, g->strt.size * 2); luaS_resize(L, g->strt.size * 2);
list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */
} }
ts = createstrobj(L, str, l, LUA_TSHRSTR, h); ts = createstrobj(L, l, LUA_TSHRSTR, h);
memcpy(getaddrstr(ts), str, l * sizeof(char));
ts->shrlen = cast_byte(l); ts->shrlen = cast_byte(l);
ts->u.hnext = *list; ts->u.hnext = *list;
*list = ts; *list = ts;
@ -185,8 +191,8 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
TString *ts; TString *ts;
if (l >= (MAX_SIZE - sizeof(TString))/sizeof(char)) if (l >= (MAX_SIZE - sizeof(TString))/sizeof(char))
luaM_toobig(L); luaM_toobig(L);
ts = createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); ts = luaS_createlngstrobj(L, l);
ts->u.lnglen = l; memcpy(getaddrstr(ts), str, l * sizeof(char));
return ts; return ts;
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstring.h,v 1.58 2015/03/04 13:31:21 roberto Exp roberto $ ** $Id: lstring.h,v 1.59 2015/03/25 13:42:19 roberto Exp roberto $
** String table (keep all strings handled by Lua) ** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -42,6 +42,7 @@ LUAI_FUNC void luaS_remove (lua_State *L, TString *ts);
LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s);
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l);
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lundump.c,v 2.40 2014/06/19 18:27:20 roberto Exp roberto $ ** $Id: lundump.c,v 2.41 2014/11/02 19:19:04 roberto Exp roberto $
** load precompiled Lua chunks ** load precompiled Lua chunks
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -32,7 +32,6 @@
typedef struct { typedef struct {
lua_State *L; lua_State *L;
ZIO *Z; ZIO *Z;
Mbuffer *b;
const char *name; const char *name;
} LoadState; } LoadState;
@ -92,10 +91,15 @@ static TString *LoadString (LoadState *S) {
LoadVar(S, size); LoadVar(S, size);
if (size == 0) if (size == 0)
return NULL; return NULL;
else { else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */
char *s = luaZ_openspace(S->L, S->b, --size); char buff[LUAI_MAXSHORTLEN];
LoadVector(S, s, size); LoadVector(S, buff, size);
return luaS_newlstr(S->L, s, size); return luaS_newlstr(S->L, buff, size);
}
else { /* long string */
TString *ts = luaS_createlngstrobj(S->L, size);
LoadVector(S, getaddrstr(ts), size); /* load directly in final place */
return ts;
} }
} }
@ -251,8 +255,7 @@ static void checkHeader (LoadState *S) {
/* /*
** load precompiled chunk ** load precompiled chunk
*/ */
LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff, LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
const char *name) {
LoadState S; LoadState S;
LClosure *cl; LClosure *cl;
if (*name == '@' || *name == '=') if (*name == '@' || *name == '=')
@ -263,7 +266,6 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff,
S.name = name; S.name = name;
S.L = L; S.L = L;
S.Z = Z; S.Z = Z;
S.b = buff;
checkHeader(&S); checkHeader(&S);
cl = luaF_newLclosure(L, LoadByte(&S)); cl = luaF_newLclosure(L, LoadByte(&S));
setclLvalue(L, L->top, cl); setclLvalue(L, L->top, cl);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lundump.h,v 1.43 2014/04/15 14:28:20 roberto Exp roberto $ ** $Id: lundump.h,v 1.44 2014/06/19 18:27:20 roberto Exp roberto $
** load precompiled Lua chunks ** load precompiled Lua chunks
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -23,8 +23,7 @@
#define LUAC_FORMAT 0 /* this is the official format */ #define LUAC_FORMAT 0 /* this is the official format */
/* load one chunk; from lundump.c */ /* load one chunk; from lundump.c */
LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name);
const char* name);
/* dump one chunk; from ldump.c */ /* dump one chunk; from ldump.c */
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,

41
lvm.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lvm.c,v 2.249 2015/08/03 19:50:49 roberto Exp roberto $ ** $Id: lvm.c,v 2.250 2015/08/03 20:40:26 roberto Exp roberto $
** Lua virtual machine ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -445,6 +445,17 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0) #define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0)
/* copy strings in stack from top - n up to top - 1 to buffer */
static void copy2buff (StkId top, int n, char *buff) {
size_t tl = 0; /* size already copied */
do {
size_t l = vslen(top - n); /* length of string being copied */
memcpy(buff + tl, svalue(top - n), l * sizeof(char));
tl += l;
} while (--n > 0);
}
/* /*
** Main operation for concatenation: concat 'total' values in the stack, ** Main operation for concatenation: concat 'total' values in the stack,
** from 'L->top - total' up to 'L->top - 1'. ** from 'L->top - total' up to 'L->top - 1'.
@ -464,24 +475,24 @@ void luaV_concat (lua_State *L, int total) {
else { else {
/* at least two non-empty string values; get as many as possible */ /* at least two non-empty string values; get as many as possible */
size_t tl = vslen(top - 1); size_t tl = vslen(top - 1);
char *buffer; TString *ts;
int i; /* collect total length and number of strings */
/* collect total length */ for (n = 1; n < total && tostring(L, top - n - 1); n++) {
for (i = 1; i < total && tostring(L, top-i-1); i++) { size_t l = vslen(top - n - 1);
size_t l = vslen(top - i - 1);
if (l >= (MAX_SIZE/sizeof(char)) - tl) if (l >= (MAX_SIZE/sizeof(char)) - tl)
luaG_runerror(L, "string length overflow"); luaG_runerror(L, "string length overflow");
tl += l; tl += l;
} }
buffer = luaZ_openspace(L, &G(L)->buff, tl); if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */
tl = 0; char buff[LUAI_MAXSHORTLEN];
n = i; copy2buff(top, n, buff); /* copy strings to buffer */
do { /* copy all strings to buffer */ ts = luaS_newlstr(L, buff, tl);
size_t l = vslen(top - i); }
memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); else { /* long string; copy strings directly to final result */
tl += l; ts = luaS_createlngstrobj(L, tl);
} while (--i > 0); copy2buff(top, n, getaddrstr(ts));
setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); /* create result */ }
setsvalue2s(L, top - n, ts); /* create result */
} }
total -= n-1; /* got 'n' strings to create 1 new */ total -= n-1; /* got 'n' strings to create 1 new */
L->top -= n-1; /* popped 'n' strings and pushed one */ L->top -= n-1; /* popped 'n' strings and pushed one */

12
lzio.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lzio.c,v 1.35 2012/05/14 13:34:18 roberto Exp roberto $ ** $Id: lzio.c,v 1.36 2014/11/02 19:19:04 roberto Exp roberto $
** Buffered streams ** Buffered streams
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -66,13 +66,3 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
return 0; return 0;
} }
/* ------------------------------------------------------------------------ */
char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
if (n > buff->buffsize) {
if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
luaZ_resizebuffer(L, buff, n);
}
return buff->buffer;
}

3
lzio.h
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lzio.h,v 1.29 2014/12/19 13:45:40 roberto Exp roberto $ ** $Id: lzio.h,v 1.30 2014/12/19 17:26:14 roberto Exp roberto $
** Buffered streams ** Buffered streams
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -44,7 +44,6 @@ typedef struct Mbuffer {
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) #define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
void *data); void *data);
LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */