use of different buffers for scanner and concatenation

This commit is contained in:
Roberto Ierusalimschy 2002-10-08 15:46:08 -03:00
parent 02afc892d5
commit b3d0682fb9
15 changed files with 136 additions and 110 deletions

7
ldo.c
View File

@ -1,5 +1,5 @@
/*
** $Id: ldo.c,v 1.193 2002/08/30 19:09:21 roberto Exp roberto $
** $Id: ldo.c,v 1.194 2002/09/02 20:00:41 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@ -420,12 +420,13 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) {
*/
struct SParser { /* data to `f_parser' */
ZIO *z;
Mbuffer buff; /* buffer to be used by the scanner */
int bin;
};
static void f_parser (lua_State *L, void *ud) {
struct SParser *p = cast(struct SParser *, ud);
Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z);
Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z, &p->buff);
Closure *cl = luaF_newLclosure(L, 0, gt(L));
cl->l.p = tf;
setclvalue(L->top, cl);
@ -439,11 +440,13 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
int status;
ptrdiff_t oldtopr = savestack(L, L->top); /* save current top */
p.z = z; p.bin = bin;
luaZ_initbuffer(L, &p.buff);
/* before parsing, give a (good) chance to GC */
if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold)
luaC_collectgarbage(L);
old_blocks = G(L)->nblocks;
status = luaD_rawrunprotected(L, f_parser, &p);
luaZ_freebuffer(L, &p.buff);
if (status == 0) {
/* add new memory to threshold (as it probably will stay) */
lua_assert(G(L)->nblocks >= old_blocks);

10
lgc.c
View File

@ -1,5 +1,5 @@
/*
** $Id: lgc.c,v 1.150 2002/09/05 19:57:40 roberto Exp roberto $
** $Id: lgc.c,v 1.151 2002/09/19 19:54:22 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@ -332,17 +332,15 @@ static void sweepstrings (lua_State *L, int all) {
}
#define MINBUFFER 256
static void checkSizes (lua_State *L) {
/* check size of string hash */
if (G(L)->strt.nuse < cast(ls_nstr, G(L)->strt.size/4) &&
G(L)->strt.size > MINSTRTABSIZE*2)
luaS_resize(L, G(L)->strt.size/2); /* table is too big */
/* check size of buffer */
if (G(L)->Mbuffsize > MINBUFFER*2) { /* is buffer too big? */
size_t newsize = G(L)->Mbuffsize/2; /* still larger than MINBUFFER */
luaM_reallocvector(L, G(L)->Mbuffer, G(L)->Mbuffsize, newsize, char);
G(L)->Mbuffsize = newsize;
if (luaZ_sizebuffer(&G(L)->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
size_t newsize = luaZ_sizebuffer(&G(L)->buff) / 2;
luaZ_resizebuffer(L, &G(L)->buff, newsize);
}
}

129
llex.c
View File

@ -1,5 +1,5 @@
/*
** $Id: llex.c,v 1.111 2002/09/05 19:45:42 roberto Exp roberto $
** $Id: llex.c,v 1.112 2002/09/19 13:03:53 roberto Exp roberto $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@ -100,7 +100,7 @@ static void luaX_lexerror (LexState *ls, const char *s, int token) {
if (token == TK_EOS)
luaX_error(ls, s, luaX_token2str(ls, token));
else
luaX_error(ls, s, cast(char *, G(ls->L)->Mbuffer));
luaX_error(ls, s, luaZ_buffer(ls->buff));
}
@ -138,146 +138,143 @@ void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) {
/* use Mbuffer to store names, literal strings and numbers */
#define EXTRABUFF 128
#define checkbuffer(L, len) \
if (((len)+10)*sizeof(char) > G(L)->Mbuffsize) \
luaO_openspace(L, (len)+EXTRABUFF)
#define EXTRABUFF 32
#define checkbuffer(LS, len) \
if (((len)+3)*sizeof(char) > luaZ_sizebuffer((LS)->buff)) \
luaZ_openspace((LS)->L, (LS)->buff, (len)+EXTRABUFF)
#define save(L, c, l) (cast(char *, G(L)->Mbuffer)[l++] = cast(char, c))
#define save_and_next(L, LS, l) (save(L, LS->current, l), next(LS))
#define save(LS, c, l) \
(cast(char *, luaZ_buffer((LS)->buff))[l++] = cast(char, c))
#define save_and_next(LS, l) (save(LS, LS->current, l), next(LS))
static size_t readname (LexState *LS) {
lua_State *L = LS->L;
size_t l = 0;
checkbuffer(L, l);
checkbuffer(LS, l);
do {
checkbuffer(L, l);
save_and_next(L, LS, l);
checkbuffer(LS, l);
save_and_next(LS, l);
} while (isalnum(LS->current) || LS->current == '_');
save(L, '\0', l);
save(LS, '\0', l);
return l-1;
}
/* LUA_NUMBER */
static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) {
lua_State *L = LS->L;
size_t l = 0;
checkbuffer(L, l);
if (comma) save(L, '.', l);
checkbuffer(LS, l);
if (comma) save(LS, '.', l);
while (isdigit(LS->current)) {
checkbuffer(L, l);
save_and_next(L, LS, l);
checkbuffer(LS, l);
save_and_next(LS, l);
}
if (LS->current == '.') {
save_and_next(L, LS, l);
save_and_next(LS, l);
if (LS->current == '.') {
save_and_next(L, LS, l);
save(L, '\0', l);
save_and_next(LS, l);
save(LS, '\0', l);
luaX_lexerror(LS,
"ambiguous syntax (decimal point x string concatenation)",
TK_NUMBER);
}
}
while (isdigit(LS->current)) {
checkbuffer(L, l);
save_and_next(L, LS, l);
checkbuffer(LS, l);
save_and_next(LS, l);
}
if (LS->current == 'e' || LS->current == 'E') {
save_and_next(L, LS, l); /* read `E' */
save_and_next(LS, l); /* read `E' */
if (LS->current == '+' || LS->current == '-')
save_and_next(L, LS, l); /* optional exponent sign */
save_and_next(LS, l); /* optional exponent sign */
while (isdigit(LS->current)) {
checkbuffer(L, l);
save_and_next(L, LS, l);
checkbuffer(LS, l);
save_and_next(LS, l);
}
}
save(L, '\0', l);
if (!luaO_str2d(cast(char *, G(L)->Mbuffer), &seminfo->r))
save(LS, '\0', l);
if (!luaO_str2d(cast(char *, luaZ_buffer(LS->buff)), &seminfo->r))
luaX_lexerror(LS, "malformed number", TK_NUMBER);
}
static void read_long_string (LexState *LS, SemInfo *seminfo) {
lua_State *L = LS->L;
int cont = 0;
size_t l = 0;
checkbuffer(L, l);
save(L, '[', l); /* save first `[' */
save_and_next(L, LS, l); /* pass the second `[' */
checkbuffer(LS, l);
save(LS, '[', l); /* save first `[' */
save_and_next(LS, l); /* pass the second `[' */
if (LS->current == '\n') /* string starts with a newline? */
inclinenumber(LS); /* skip it */
for (;;) {
checkbuffer(L, l);
checkbuffer(LS, l);
switch (LS->current) {
case EOZ:
save(L, '\0', l);
save(LS, '\0', l);
luaX_lexerror(LS, (seminfo) ? "unfinished long string" :
"unfinished long comment", TK_EOS);
break; /* to avoid warnings */
case '[':
save_and_next(L, LS, l);
save_and_next(LS, l);
if (LS->current == '[') {
cont++;
save_and_next(L, LS, l);
save_and_next(LS, l);
}
continue;
case ']':
save_and_next(L, LS, l);
save_and_next(LS, l);
if (LS->current == ']') {
if (cont == 0) goto endloop;
cont--;
save_and_next(L, LS, l);
save_and_next(LS, l);
}
continue;
case '\n':
save(L, '\n', l);
save(LS, '\n', l);
inclinenumber(LS);
if (!seminfo) l = 0; /* reset buffer to avoid wasting space */
continue;
default:
save_and_next(L, LS, l);
save_and_next(LS, l);
}
} endloop:
save_and_next(L, LS, l); /* skip the second `]' */
save(L, '\0', l);
save_and_next(LS, l); /* skip the second `]' */
save(LS, '\0', l);
if (seminfo)
seminfo->ts = luaS_newlstr(L, cast(char *, G(L)->Mbuffer)+2, l-5);
seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5);
}
static void read_string (LexState *LS, int del, SemInfo *seminfo) {
lua_State *L = LS->L;
size_t l = 0;
checkbuffer(L, l);
save_and_next(L, LS, l);
checkbuffer(LS, l);
save_and_next(LS, l);
while (LS->current != del) {
checkbuffer(L, l);
checkbuffer(LS, l);
switch (LS->current) {
case EOZ:
save(L, '\0', l);
save(LS, '\0', l);
luaX_lexerror(LS, "unfinished string", TK_EOS);
break; /* to avoid warnings */
case '\n':
save(L, '\0', l);
save(LS, '\0', l);
luaX_lexerror(LS, "unfinished string", TK_STRING);
break; /* to avoid warnings */
case '\\':
next(LS); /* do not save the `\' */
switch (LS->current) {
case 'a': save(L, '\a', l); next(LS); break;
case 'b': save(L, '\b', l); next(LS); break;
case 'f': save(L, '\f', l); next(LS); break;
case 'n': save(L, '\n', l); next(LS); break;
case 'r': save(L, '\r', l); next(LS); break;
case 't': save(L, '\t', l); next(LS); break;
case 'v': save(L, '\v', l); next(LS); break;
case '\n': save(L, '\n', l); inclinenumber(LS); break;
case 'a': save(LS, '\a', l); next(LS); break;
case 'b': save(LS, '\b', l); next(LS); break;
case 'f': save(LS, '\f', l); next(LS); break;
case 'n': save(LS, '\n', l); next(LS); break;
case 'r': save(LS, '\r', l); next(LS); break;
case 't': save(LS, '\t', l); next(LS); break;
case 'v': save(LS, '\v', l); next(LS); break;
case '\n': save(LS, '\n', l); inclinenumber(LS); break;
case EOZ: break; /* will raise an error next loop */
default: {
if (!isdigit(LS->current))
save_and_next(L, LS, l); /* handles \\, \", \', and \? */
save_and_next(LS, l); /* handles \\, \", \', and \? */
else { /* \xxx */
int c = 0;
int i = 0;
@ -286,21 +283,21 @@ static void read_string (LexState *LS, int del, SemInfo *seminfo) {
next(LS);
} while (++i<3 && isdigit(LS->current));
if (c > UCHAR_MAX) {
save(L, '\0', l);
save(LS, '\0', l);
luaX_lexerror(LS, "escape sequence too large", TK_STRING);
}
save(L, c, l);
save(LS, c, l);
}
}
}
break;
default:
save_and_next(L, LS, l);
save_and_next(LS, l);
}
}
save_and_next(L, LS, l); /* skip delimiter */
save(L, '\0', l);
seminfo->ts = luaS_newlstr(L, cast(char *, G(L)->Mbuffer)+1, l-3);
save_and_next(LS, l); /* skip delimiter */
save(LS, '\0', l);
seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3);
}
@ -388,7 +385,7 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) {
else if (isalpha(LS->current) || LS->current == '_') {
/* identifier or reserved word */
size_t l = readname(LS);
TString *ts = luaS_newlstr(LS->L, cast(char *, G(LS->L)->Mbuffer), l);
TString *ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l);
if (ts->tsv.reserved > 0) /* reserved word? */
return ts->tsv.reserved - 1 + FIRST_RESERVED;
seminfo->ts = ts;

5
llex.h
View File

@ -1,5 +1,5 @@
/*
** $Id: llex.h,v 1.43 2002/05/07 17:36:56 roberto Exp roberto $
** $Id: llex.h,v 1.44 2002/09/03 11:57:38 roberto Exp roberto $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@ -56,7 +56,8 @@ typedef struct LexState {
Token lookahead; /* look ahead token */
struct FuncState *fs; /* `FuncState' is private to the parser */
struct lua_State *L;
struct zio *z; /* input stream */
ZIO *z; /* input stream */
Mbuffer *buff; /* buffer for tokens */
TString *source; /* current source name */
} LexState;

View File

@ -1,5 +1,5 @@
/*
** $Id: llimits.h,v 1.44 2002/06/13 13:45:31 roberto Exp roberto $
** $Id: llimits.h,v 1.45 2002/07/08 20:22:08 roberto Exp roberto $
** Limits, basic types, and some other `installation-dependent' definitions
** See Copyright Notice in lua.h
*/
@ -150,4 +150,10 @@ typedef unsigned long Instruction;
#endif
/* minimum size for string buffer */
#ifndef LUA_MINBUFFER
#define LUA_MINBUFFER 32
#endif
#endif

View File

@ -1,5 +1,5 @@
/*
** $Id: lobject.c,v 1.88 2002/09/19 13:03:53 roberto Exp roberto $
** $Id: lobject.c,v 1.89 2002/10/04 14:31:03 roberto Exp roberto $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
@ -73,15 +73,6 @@ int luaO_rawequalObj (const TObject *t1, const TObject *t2) {
}
char *luaO_openspace (lua_State *L, size_t n) {
if (n > G(L)->Mbuffsize) {
luaM_reallocvector(L, G(L)->Mbuffer, G(L)->Mbuffsize, n, char);
G(L)->Mbuffsize = n;
}
return G(L)->Mbuffer;
}
int luaO_str2d (const char *s, lua_Number *result) {
char *endptr;
lua_Number res = lua_str2number(s, &endptr);

View File

@ -1,5 +1,5 @@
/*
** $Id: lobject.h,v 1.145 2002/09/02 19:54:49 roberto Exp roberto $
** $Id: lobject.h,v 1.146 2002/09/19 13:03:53 roberto Exp roberto $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@ -316,8 +316,6 @@ extern const TObject luaO_nilobject;
int luaO_log2 (unsigned int x);
char *luaO_openspace (lua_State *L, size_t n);
int luaO_rawequalObj (const TObject *t1, const TObject *t2);
int luaO_str2d (const char *s, lua_Number *result);

View File

@ -1,5 +1,5 @@
/*
** $Id: lparser.c,v 1.193 2002/08/22 19:51:08 roberto Exp roberto $
** $Id: lparser.c,v 1.194 2002/08/30 19:09:21 roberto Exp roberto $
** Lua Parser
** See Copyright Notice in lua.h
*/
@ -351,9 +351,10 @@ static void close_func (LexState *ls) {
}
Proto *luaY_parser (lua_State *L, ZIO *z) {
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) {
struct LexState lexstate;
struct FuncState funcstate;
lexstate.buff = buff;
luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z)));
open_func(&lexstate, &funcstate);
next(&lexstate); /* read first token */

View File

@ -1,5 +1,5 @@
/*
** $Id: lparser.h,v 1.43 2002/05/10 19:22:11 roberto Exp roberto $
** $Id: lparser.h,v 1.44 2002/05/14 17:52:22 roberto Exp roberto $
** Lua Parser
** See Copyright Notice in lua.h
*/
@ -65,7 +65,7 @@ typedef struct FuncState {
} FuncState;
Proto *luaY_parser (lua_State *L, ZIO *z);
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff);
#endif

View File

@ -1,5 +1,5 @@
/*
** $Id: lstate.c,v 1.104 2002/08/16 20:00:28 roberto Exp roberto $
** $Id: lstate.c,v 1.105 2002/08/30 19:09:21 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@ -61,8 +61,7 @@ static void f_luaopen (lua_State *L, void *ud) {
G(L)->strt.size = 0;
G(L)->strt.nuse = 0;
G(L)->strt.hash = NULL;
G(L)->Mbuffer = NULL;
G(L)->Mbuffsize = 0;
luaZ_initbuffer(L, &G(L)->buff);
G(L)->panic = &default_panic;
G(L)->rootgc = NULL;
G(L)->rootudata = NULL;
@ -160,7 +159,7 @@ static void close_state (lua_State *L) {
lua_assert(G(L)->rootgc == NULL);
lua_assert(G(L)->rootudata == NULL);
luaS_freeall(L);
luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char);
luaZ_freebuffer(L, &G(L)->buff);
luaM_freelem(NULL, L->l_G);
}
luaE_closethread(NULL, L);

View File

@ -1,5 +1,5 @@
/*
** $Id: lstate.h,v 1.95 2002/08/30 19:09:21 roberto Exp roberto $
** $Id: lstate.h,v 1.96 2002/09/19 13:03:53 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@ -11,6 +11,7 @@
#include "lobject.h"
#include "ltm.h"
#include "lzio.h"
/*
@ -124,8 +125,7 @@ typedef struct global_State {
GCObject *rootgc; /* list of (almost) all collectable objects */
GCObject *rootudata; /* (separated) list of all userdata */
GCObject *tmudata; /* list of userdata to be GC */
char *Mbuffer; /* global buffer */
size_t Mbuffsize; /* size of Mbuffer */
Mbuffer buff; /* temporary buffer for string concatentation */
lu_mem GCthreshold;
lu_mem nblocks; /* number of `bytes' currently allocated */
lua_CFunction panic; /* to be called in unprotected errors */

View File

@ -1,5 +1,5 @@
/*
** $Id: lundump.c,v 1.52 2002/08/12 13:37:19 roberto Exp roberto $
** $Id: lundump.c,v 1.53 2002/09/19 13:03:53 roberto Exp roberto $
** load pre-compiled Lua chunks
** See Copyright Notice in lua.h
*/
@ -99,7 +99,7 @@ static TString* LoadString (LoadState* S)
return NULL;
else
{
char* s=luaO_openspace(S->L,size);
char* s=luaZ_openspace(S->L,&G(S->L)->buff,size);
ezread(S,s,size);
return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
}

4
lvm.c
View File

@ -1,5 +1,5 @@
/*
** $Id: lvm.c,v 1.255 2002/09/19 13:03:53 roberto Exp roberto $
** $Id: lvm.c,v 1.256 2002/09/19 20:12:47 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@ -303,7 +303,7 @@ void luaV_concat (lua_State *L, int total, int last) {
n++;
}
if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow");
buffer = luaO_openspace(L, tl);
buffer = luaZ_openspace(L, &G(L)->buff, tl);
tl = 0;
for (i=n; i>0; i--) { /* concat all strings */
size_t l = tsvalue(top-i)->tsv.len;

15
lzio.c
View File

@ -1,5 +1,5 @@
/*
** $Id: lzio.c,v 1.20 2002/08/05 18:45:02 roberto Exp roberto $
** $Id: lzio.c,v 1.21 2002/08/06 17:26:45 roberto Exp roberto $
** a generic input stream interface
** See Copyright Notice in lua.h
*/
@ -10,10 +10,10 @@
#include "lua.h"
#include "llimits.h"
#include "lmem.h"
#include "lzio.h"
int luaZ_fill (ZIO *z) {
size_t size;
const char *buff = z->reader(NULL, z->data, &size);
@ -66,3 +66,14 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
return 0;
}
/* ------------------------------------------------------------------------ */
char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
if (n > buff->buffsize) {
if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
luaM_reallocvector(L, buff->buffer, buff->buffsize, n, char);
buff->buffsize = n;
}
return buff->buffer;
}

27
lzio.h
View File

@ -1,5 +1,5 @@
/*
** $Id: lzio.h,v 1.12 2002/06/06 12:40:22 roberto Exp roberto $
** $Id: lzio.h,v 1.13 2002/08/05 18:45:02 roberto Exp roberto $
** Buffered streams
** See Copyright Notice in lua.h
*/
@ -13,7 +13,7 @@
#define EOZ (-1) /* end of stream */
typedef struct zio ZIO;
typedef struct Zio ZIO;
#define zgetc(z) (((z)->n--)>0 ? \
cast(int, cast(unsigned char, *(z)->p++)) : \
@ -26,9 +26,30 @@ size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
int luaZ_lookahead (ZIO *z);
typedef struct Mbuffer {
char *buffer;
size_t buffsize;
} Mbuffer;
char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
#define luaZ_sizebuffer(buff) ((buff)->buffsize)
#define luaZ_buffer(buff) ((buff)->buffer)
#define luaZ_resizebuffer(L, buff, size) \
(luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
(buff)->buffsize = size)
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
/* --------- Private Part ------------------ */
struct zio {
struct Zio {
size_t n; /* bytes still unread */
const char *p; /* current position in buffer */
lua_Chunkreader reader;