From 2ceb642b5d62abd9de18bd13ba923e33f0a69fe4 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Tue, 16 Apr 2019 21:16:13 +0800 Subject: [PATCH] rewrite SSM and clonefunction --- 3rd/lua/lapi.c | 59 +-- 3rd/lua/lauxlib.c | 7 +- 3rd/lua/lauxlib.h | 2 + 3rd/lua/lcode.c | 36 +- 3rd/lua/lcode.h | 2 +- 3rd/lua/ldebug.c | 24 +- 3rd/lua/ldebug.h | 4 +- 3rd/lua/ldo.c | 6 +- 3rd/lua/ldump.c | 21 +- 3rd/lua/lfunc.c | 89 ++--- 3rd/lua/lfunc.h | 3 +- 3rd/lua/lgc.c | 94 ++--- 3rd/lua/lgc.h | 6 +- 3rd/lua/lobject.h | 26 +- 3rd/lua/lparser.c | 87 ++--- 3rd/lua/lstate.c | 29 +- 3rd/lua/lstate.h | 7 +- 3rd/lua/lstring.c | 796 +++++++++++++++++++++++++++----------- 3rd/lua/lstring.h | 28 +- 3rd/lua/lua.c | 4 +- 3rd/lua/lua.h | 10 +- 3rd/lua/luac.c | 30 +- 3rd/lua/lualib.h | 2 - 3rd/lua/lundump.c | 29 +- 3rd/lua/lvm.c | 58 +-- Makefile | 1 + lualib-src/lua-memory.c | 10 - lualib-src/lua-ssm.c | 72 ++++ service/bootstrap.lua | 6 +- service/debug_console.lua | 6 - skynet-src/luashrtbl.h | 21 +- skynet-src/skynet_main.c | 4 +- 32 files changed, 934 insertions(+), 645 deletions(-) create mode 100644 lualib-src/lua-ssm.c diff --git a/3rd/lua/lapi.c b/3rd/lua/lapi.c index 3d854509..ffea5e53 100644 --- a/3rd/lua/lapi.c +++ b/3rd/lua/lapi.c @@ -1013,52 +1013,11 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, return status; } -static void cloneproto (lua_State *L, Proto *f, const Proto *src) { - /* copy constants and nested proto */ - int i,n; - n = src->sp->sizek; - if (src->sp->sharedk) - f->k = src->sp->k; - else { - lu_byte sharedk = 1; - f->k=luaM_newvector(L,n,TValue); - for (i=0; ik[i]); - for (i=0; ik[i]; - TValue *o=&f->k[i]; - if (ttisstring(s)) { - TString * sstr = tsvalue(s); - if (ttisshrstring(s)) { - TString * str = luaS_clonestring(L,sstr); - setsvalue2n(L,o,str); - if (str != sstr) - sharedk = 0; - } else { - setsvalue2n(L,o,sstr); - } - } else { - setobj(L,o,s); - } - } - if (sharedk) { - luaM_freearray(L, f->k, n); - f->k = src->sp->k; - } - } - n = src->sp->sizep; - f->p=luaM_newvector(L,n,struct Proto *); - for (i=0; ip[i]=NULL; - for (i=0; ip[i]= luaF_newproto(L, src->p[i]->sp); - cloneproto(L, f->p[i], src->p[i]); - } -} - LUA_API void lua_clonefunction (lua_State *L, const void * fp) { LClosure *cl; LClosure *f = cast(LClosure *, fp); lua_lock(L); - if (f->p->sp->l_G == G(L)) { + if (f->p->l_G == G(L)) { setclLvalue(L,L->top,f); api_incr_top(L); lua_unlock(L); @@ -1067,8 +1026,7 @@ LUA_API void lua_clonefunction (lua_State *L, const void * fp) { cl = luaF_newLclosure(L,f->nupvalues); setclLvalue(L,L->top,cl); api_incr_top(L); - cl->p = luaF_newproto(L, f->p->sp); - cloneproto(L, cl->p, f->p); + cl->p = f->p; luaF_initupvals(L, cl); if (cl->nupvalues >= 1) { /* does it have an upvalue? */ @@ -1082,6 +1040,15 @@ LUA_API void lua_clonefunction (lua_State *L, const void * fp) { lua_unlock(L); } +LUA_API void lua_sharefunction (lua_State *L, int index) { + if (!lua_isfunction(L,index) || lua_iscfunction(L,index)) { + lua_pushstring(L, "Only Lua function can share"); + lua_error(L); + } + LClosure *f = cast(LClosure *, lua_topointer(L, index)); + luaF_shareproto(f->p); +} + LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { int status; TValue *o; @@ -1276,7 +1243,7 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val, case LUA_TLCL: { /* Lua closure */ LClosure *f = clLvalue(fi); TString *name; - SharedProto *p = f->p->sp; + Proto *p = f->p; if (!(1 <= n && n <= p->sizeupvalues)) return NULL; *val = f->upvals[n-1]->v; if (uv) *uv = f->upvals[n - 1]; @@ -1328,7 +1295,7 @@ static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { StkId fi = index2addr(L, fidx); api_check(L, ttisLclosure(fi), "Lua function expected"); f = clLvalue(fi); - api_check(L, (1 <= n && n <= f->p->sp->sizeupvalues), "invalid upvalue index"); + api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); if (pf) *pf = f; return &f->upvals[n - 1]; /* get its upvalue pointer */ } diff --git a/3rd/lua/lauxlib.c b/3rd/lua/lauxlib.c index b77062b4..58c6d996 100644 --- a/3rd/lua/lauxlib.c +++ b/3rd/lua/lauxlib.c @@ -699,9 +699,7 @@ static int skipcomment (LoadF *lf, int *cp) { else return 0; /* no comment */ } -LUA_API void luaS_expandshr(int n); - -static int luaL_loadfilex_ (lua_State *L, const char *filename, +LUALIB_API int luaL_loadfilex_ (lua_State *L, const char *filename, const char *mode) { LoadF lf; int status, readstatus; @@ -725,9 +723,7 @@ static int luaL_loadfilex_ (lua_State *L, const char *filename, } if (c != EOF) lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ - luaS_expandshr(4096); status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); - luaS_expandshr(-4096); readstatus = ferror(lf.f); if (filename) fclose(lf.f); /* close file (even in case of errors) */ if (readstatus) { @@ -1181,6 +1177,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, lua_close(eL); return err; } + lua_sharefunction(eL, -1); proto = lua_topointer(eL, -1); const void * oldv = save(filename, proto); if (oldv) { diff --git a/3rd/lua/lauxlib.h b/3rd/lua/lauxlib.h index 9857d3a8..f0a289dc 100644 --- a/3rd/lua/lauxlib.h +++ b/3rd/lua/lauxlib.h @@ -82,6 +82,8 @@ LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, const char *mode); +LUALIB_API int (luaL_loadfilex_) (lua_State *L, const char *filename, + const char *mode); #define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) diff --git a/3rd/lua/lcode.c b/3rd/lua/lcode.c index 6392d4b9..12619f54 100644 --- a/3rd/lua/lcode.c +++ b/3rd/lua/lcode.c @@ -65,7 +65,7 @@ void luaK_nil (FuncState *fs, int from, int n) { Instruction *previous; int l = from + n - 1; /* last register to set nil */ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ - previous = &fs->f->sp->code[fs->pc-1]; + previous = &fs->f->code[fs->pc-1]; if (GET_OPCODE(*previous) == OP_LOADNIL) { /* previous is LOADNIL? */ int pfrom = GETARG_A(*previous); /* get previous range */ int pl = pfrom + GETARG_B(*previous); @@ -88,7 +88,7 @@ void luaK_nil (FuncState *fs, int from, int n) { ** a list of jumps. */ static int getjump (FuncState *fs, int pc) { - int offset = GETARG_sBx(fs->f->sp->code[pc]); + int offset = GETARG_sBx(fs->f->code[pc]); if (offset == NO_JUMP) /* point to itself represents end of list */ return NO_JUMP; /* end of list */ else @@ -101,7 +101,7 @@ static int getjump (FuncState *fs, int pc) { ** (Jump addresses are relative in Lua) */ static void fixjump (FuncState *fs, int pc, int dest) { - Instruction *jmp = &fs->f->sp->code[pc]; + Instruction *jmp = &fs->f->code[pc]; int offset = dest - (pc + 1); lua_assert(dest != NO_JUMP); if (abs(offset) > MAXARG_sBx) @@ -177,7 +177,7 @@ int luaK_getlabel (FuncState *fs) { ** unconditional. */ static Instruction *getjumpcontrol (FuncState *fs, int pc) { - Instruction *pi = &fs->f->sp->code[pc]; + Instruction *pi = &fs->f->code[pc]; if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) return pi-1; else @@ -278,10 +278,10 @@ void luaK_patchlist (FuncState *fs, int list, int target) { void luaK_patchclose (FuncState *fs, int list, int level) { level++; /* argument is +1 to reserve 0 as non-op */ for (; list != NO_JUMP; list = getjump(fs, list)) { - lua_assert(GET_OPCODE(fs->f->sp->code[list]) == OP_JMP && - (GETARG_A(fs->f->sp->code[list]) == 0 || - GETARG_A(fs->f->sp->code[list]) >= level)); - SETARG_A(fs->f->sp->code[list], level); + lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && + (GETARG_A(fs->f->code[list]) == 0 || + GETARG_A(fs->f->code[list]) >= level)); + SETARG_A(fs->f->code[list], level); } } @@ -294,13 +294,13 @@ static int luaK_code (FuncState *fs, Instruction i) { Proto *f = fs->f; dischargejpc(fs); /* 'pc' will change */ /* put new instruction in code array */ - luaM_growvector(fs->ls->L, f->sp->code, fs->pc, f->sp->sizecode, Instruction, + luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, MAX_INT, "opcodes"); - f->sp->code[fs->pc] = i; + f->code[fs->pc] = i; /* save corresponding line information */ - luaM_growvector(fs->ls->L, f->sp->lineinfo, fs->pc, f->sp->sizelineinfo, int, + luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, MAX_INT, "opcodes"); - f->sp->lineinfo[fs->pc] = fs->ls->lastline; + f->lineinfo[fs->pc] = fs->ls->lastline; return fs->pc++; } @@ -360,11 +360,11 @@ int luaK_codek (FuncState *fs, int reg, int k) { */ void luaK_checkstack (FuncState *fs, int n) { int newstack = fs->freereg + n; - if (newstack > fs->f->sp->maxstacksize) { + if (newstack > fs->f->maxstacksize) { if (newstack >= MAXREGS) luaX_syntaxerror(fs->ls, "function or expression needs too many registers"); - fs->f->sp->maxstacksize = cast_byte(newstack); + fs->f->maxstacksize = cast_byte(newstack); } } @@ -438,13 +438,13 @@ static int addk (FuncState *fs, TValue *key, TValue *v) { return k; /* reuse index */ } /* constant not found; create a new entry */ - oldsize = f->sp->sizek; + oldsize = f->sizek; k = fs->nk; /* numerical value does not need GC barrier; table has no metatable, so it does not need to invalidate cache */ setivalue(idx, k); - luaM_growvector(L, f->k, k, f->sp->sizek, TValue, MAXARG_Ax, "constants"); - while (oldsize < f->sp->sizek) setnilvalue(&f->k[oldsize++]); + luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); setobj(L, &f->k[k], v); fs->nk++; luaC_barrier(L, f, v); @@ -1175,7 +1175,7 @@ void luaK_posfix (FuncState *fs, BinOpr op, ** Change line information associated with current position. */ void luaK_fixline (FuncState *fs, int line) { - fs->f->sp->lineinfo[fs->pc - 1] = line; + fs->f->lineinfo[fs->pc - 1] = line; } diff --git a/3rd/lua/lcode.h b/3rd/lua/lcode.h index 8aa4e98c..882dc9c1 100644 --- a/3rd/lua/lcode.h +++ b/3rd/lua/lcode.h @@ -41,7 +41,7 @@ typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; /* get (pointer to) instruction of given 'expdesc' */ -#define getinstruction(fs,e) ((fs)->f->sp->code[(e)->u.info]) +#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info]) #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) diff --git a/3rd/lua/ldebug.c b/3rd/lua/ldebug.c index aae85534..e1389296 100644 --- a/3rd/lua/ldebug.c +++ b/3rd/lua/ldebug.c @@ -125,14 +125,14 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { static const char *upvalname (Proto *p, int uv) { - TString *s = check_exp(uv < p->sp->sizeupvalues, p->sp->upvalues[uv].name); + TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); if (s == NULL) return "?"; else return getstr(s); } static const char *findvararg (CallInfo *ci, int n, StkId *pos) { - int nparams = clLvalue(ci->func)->p->sp->numparams; + int nparams = clLvalue(ci->func)->p->numparams; if (n >= cast_int(ci->u.l.base - ci->func) - nparams) return NULL; /* no such vararg */ else { @@ -216,7 +216,7 @@ static void funcinfo (lua_Debug *ar, Closure *cl) { ar->what = "C"; } else { - SharedProto *p = cl->l.p->sp; + Proto *p = cl->l.p; ar->source = p->source ? getstr(p->source) : "=?"; ar->linedefined = p->linedefined; ar->lastlinedefined = p->lastlinedefined; @@ -234,12 +234,12 @@ static void collectvalidlines (lua_State *L, Closure *f) { else { int i; TValue v; - int *lineinfo = f->l.p->sp->lineinfo; + int *lineinfo = f->l.p->lineinfo; Table *t = luaH_new(L); /* new table to store active lines */ sethvalue(L, L->top, t); /* push it on stack */ api_incr_top(L); setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ - for (i = 0; i < f->l.p->sp->sizelineinfo; i++) /* for all lines with code */ + for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ } } @@ -279,8 +279,8 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, ar->nparams = 0; } else { - ar->isvararg = f->l.p->sp->is_vararg; - ar->nparams = f->l.p->sp->numparams; + ar->isvararg = f->l.p->is_vararg; + ar->nparams = f->l.p->numparams; } break; } @@ -387,7 +387,7 @@ static int findsetreg (Proto *p, int lastpc, int reg) { int setreg = -1; /* keep last instruction that changed 'reg' */ int jmptarget = 0; /* any code before this address is conditional */ for (pc = 0; pc < lastpc; pc++) { - Instruction i = p->sp->code[pc]; + Instruction i = p->code[pc]; OpCode op = GET_OPCODE(i); int a = GETARG_A(i); switch (op) { @@ -437,7 +437,7 @@ static const char *getobjname (Proto *p, int lastpc, int reg, /* else try symbolic execution */ pc = findsetreg(p, lastpc, reg); if (pc != -1) { /* could find instruction? */ - Instruction i = p->sp->code[pc]; + Instruction i = p->code[pc]; OpCode op = GET_OPCODE(i); switch (op) { case OP_MOVE: { @@ -463,7 +463,7 @@ static const char *getobjname (Proto *p, int lastpc, int reg, case OP_LOADK: case OP_LOADKX: { int b = (op == OP_LOADK) ? GETARG_Bx(i) - : GETARG_Ax(p->sp->code[pc + 1]); + : GETARG_Ax(p->code[pc + 1]); if (ttisstring(&p->k[b])) { *name = svalue(&p->k[b]); return "constant"; @@ -493,7 +493,7 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci, TMS tm = (TMS)0; /* (initial value avoids warnings) */ Proto *p = ci_func(ci)->p; /* calling function */ int pc = currentpc(ci); /* calling instruction index */ - Instruction i = p->sp->code[pc]; /* calling instruction */ + Instruction i = p->code[pc]; /* calling instruction */ if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ *name = "?"; return "hook"; @@ -658,7 +658,7 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { msg = luaO_pushvfstring(L, fmt, argp); /* format message */ va_end(argp); if (isLua(ci)) /* if Lua function, add source:line information */ - luaG_addinfo(L, msg, ci_func(ci)->p->sp->source, currentline(ci)); + luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci)); luaG_errormsg(L); } diff --git a/3rd/lua/ldebug.h b/3rd/lua/ldebug.h index 58460533..8cea0ee0 100644 --- a/3rd/lua/ldebug.h +++ b/3rd/lua/ldebug.h @@ -11,9 +11,9 @@ #include "lstate.h" -#define pcRel(pc, p) (cast(int, (pc) - (p)->sp->code) - 1) +#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) -#define getfuncline(f,pc) (((f)->sp->lineinfo) ? (f)->sp->lineinfo[pc] : -1) +#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : -1) #define resethookcount(L) (L->hookcount = L->basehookcount) diff --git a/3rd/lua/ldo.c b/3rd/lua/ldo.c index 64795db1..316e45c8 100644 --- a/3rd/lua/ldo.c +++ b/3rd/lua/ldo.c @@ -290,7 +290,7 @@ static void callhook (lua_State *L, CallInfo *ci) { } -static StkId adjust_varargs (lua_State *L, SharedProto *p, int actual) { +static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { int i; int nfixargs = p->numparams; StkId base, fixed; @@ -439,7 +439,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { } case LUA_TLCL: { /* Lua function: prepare its call */ StkId base; - SharedProto *p = clLvalue(func)->p->sp; + Proto *p = clLvalue(func)->p; int n = cast_int(L->top - func) - 1; /* number of real arguments */ int fsize = p->maxstacksize; /* frame size */ checkstackp(L, fsize, func); @@ -775,7 +775,7 @@ static void f_parser (lua_State *L, void *ud) { checkmode(L, p->mode, "text"); cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); } - lua_assert(cl->nupvalues == cl->p->sp->sizeupvalues); + lua_assert(cl->nupvalues == cl->p->sizeupvalues); luaF_initupvals(L, cl); } diff --git a/3rd/lua/ldump.c b/3rd/lua/ldump.c index 9749c939..f025acac 100644 --- a/3rd/lua/ldump.c +++ b/3rd/lua/ldump.c @@ -87,7 +87,7 @@ static void DumpString (const TString *s, DumpState *D) { } -static void DumpCode (const SharedProto *f, DumpState *D) { +static void DumpCode (const Proto *f, DumpState *D) { DumpInt(f->sizecode, D); DumpVector(f->code, f->sizecode, D); } @@ -97,7 +97,7 @@ static void DumpFunction(const Proto *f, TString *psource, DumpState *D); static void DumpConstants (const Proto *f, DumpState *D) { int i; - int n = f->sp->sizek; + int n = f->sizek; DumpInt(n, D); for (i = 0; i < n; i++) { const TValue *o = &f->k[i]; @@ -127,14 +127,14 @@ static void DumpConstants (const Proto *f, DumpState *D) { static void DumpProtos (const Proto *f, DumpState *D) { int i; - int n = f->sp->sizep; + int n = f->sizep; DumpInt(n, D); for (i = 0; i < n; i++) - DumpFunction(f->p[i], f->sp->source, D); + DumpFunction(f->p[i], f->source, D); } -static void DumpUpvalues (const SharedProto *f, DumpState *D) { +static void DumpUpvalues (const Proto *f, DumpState *D) { int i, n = f->sizeupvalues; DumpInt(n, D); for (i = 0; i < n; i++) { @@ -144,7 +144,7 @@ static void DumpUpvalues (const SharedProto *f, DumpState *D) { } -static void DumpDebug (const SharedProto *f, DumpState *D) { +static void DumpDebug (const Proto *f, DumpState *D) { int i, n; n = (D->strip) ? 0 : f->sizelineinfo; DumpInt(n, D); @@ -163,8 +163,7 @@ static void DumpDebug (const SharedProto *f, DumpState *D) { } -static void DumpFunction (const Proto *fp, TString *psource, DumpState *D) { - const SharedProto *f = fp->sp; +static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { if (D->strip || f->source == psource) DumpString(NULL, D); /* no debug info or same source as its parent */ else @@ -175,9 +174,9 @@ static void DumpFunction (const Proto *fp, TString *psource, DumpState *D) { DumpByte(f->is_vararg, D); DumpByte(f->maxstacksize, D); DumpCode(f, D); - DumpConstants(fp, D); + DumpConstants(f, D); DumpUpvalues(f, D); - DumpProtos(fp, D); + DumpProtos(f, D); DumpDebug(f, D); } @@ -209,7 +208,7 @@ int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, D.strip = strip; D.status = 0; DumpHeader(&D); - DumpByte(f->sp->sizeupvalues, &D); + DumpByte(f->sizeupvalues, &D); DumpFunction(f, NULL, &D); return D.status; } diff --git a/3rd/lua/lfunc.c b/3rd/lua/lfunc.c index 9c0c911f..eaf100be 100644 --- a/3rd/lua/lfunc.c +++ b/3rd/lua/lfunc.c @@ -96,59 +96,39 @@ void luaF_close (lua_State *L, StkId level) { } -Proto *luaF_newproto (lua_State *L, SharedProto *sp) { +Proto *luaF_newproto (lua_State *L) { GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto)); Proto *f = gco2p(o); - f->sp = NULL; f->k = NULL; + f->sizek = 0; f->p = NULL; - f->cache = NULL; - if (sp == NULL) { - sp = luaM_new(L, SharedProto); - sp->l_G = G(L); - sp->sizek = 0; - sp->sizep = 0; - sp->code = NULL; - sp->sizecode = 0; - sp->lineinfo = NULL; - sp->sizelineinfo = 0; - sp->upvalues = NULL; - sp->sizeupvalues = 0; - sp->numparams = 0; - sp->is_vararg = 0; - sp->maxstacksize = 0; - sp->locvars = NULL; - sp->sizelocvars = 0; - sp->linedefined = 0; - sp->lastlinedefined = 0; - sp->source = NULL; - sp->k = NULL; - sp->sharedk = 0; - } - f->sp = sp; + f->sizep = 0; + f->code = NULL; + f->sizecode = 0; + f->lineinfo = NULL; + f->sizelineinfo = 0; + f->upvalues = NULL; + f->sizeupvalues = 0; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->locvars = NULL; + f->sizelocvars = 0; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + f->l_G = G(L); return f; } -static void freesharedproto (lua_State *L, Proto *pf) { - SharedProto *f = pf->sp; - if (f == NULL) - return; - if (G(L) == f->l_G) { - luaM_freearray(L, f->code, f->sizecode); - luaM_freearray(L, f->lineinfo, f->sizelineinfo); - luaM_freearray(L, f->locvars, f->sizelocvars); - luaM_freearray(L, f->upvalues, f->sizeupvalues); - luaM_freearray(L, f->k, f->sizek); - luaM_free(L, f); - } else if (pf->k != f->k) { - luaM_freearray(L, pf->k, f->sizek); - } -} - void luaF_freeproto (lua_State *L, Proto *f) { - luaM_freearray(L, f->p, f->sp->sizep); - freesharedproto(L, f); + luaM_freearray(L, f->code, f->sizecode); + luaM_freearray(L, f->p, f->sizep); + luaM_freearray(L, f->k, f->sizek); + luaM_freearray(L, f->lineinfo, f->sizelineinfo); + luaM_freearray(L, f->locvars, f->sizelocvars); + luaM_freearray(L, f->upvalues, f->sizeupvalues); luaM_free(L, f); } @@ -157,9 +137,8 @@ void luaF_freeproto (lua_State *L, Proto *f) { ** Look for n-th local variable at line 'line' in function 'func'. ** Returns NULL if not found. */ -const char *luaF_getlocalname (const Proto *fp, int local_number, int pc) { +const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { int i; - const SharedProto *f = fp->sp; for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { if (pc < f->locvars[i].endpc) { /* is variable active? */ local_number--; @@ -170,3 +149,21 @@ const char *luaF_getlocalname (const Proto *fp, int local_number, int pc) { return NULL; /* not found */ } +#define MAKESHARED(x) if ((x) && (x)->tt == LUA_TLNGSTR) makeshared(x) + +void luaF_shareproto (Proto *f) { + int i; + if (f == NULL) + return; + MAKESHARED(f->source); + for (i = 0; i < f->sizek; i++) { + if (ttype(&f->k[i]) == LUA_TSTRING) + MAKESHARED(tsvalue(&f->k[i])); + } + for (i = 0; i < f->sizeupvalues; i++) + MAKESHARED(f->upvalues[i].name); + for (i = 0; i < f->sizelocvars; i++) + MAKESHARED(f->locvars[i].varname); + for (i = 0; i < f->sizep; i++) + luaF_shareproto(f->p[i]); +} diff --git a/3rd/lua/lfunc.h b/3rd/lua/lfunc.h index 71795b41..e9512514 100644 --- a/3rd/lua/lfunc.h +++ b/3rd/lua/lfunc.h @@ -47,7 +47,7 @@ struct UpVal { #define upisopen(up) ((up)->v != &(up)->u.value) -LUAI_FUNC Proto *luaF_newproto (lua_State *L, SharedProto *sp); +LUAI_FUNC Proto *luaF_newproto (lua_State *L); LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems); LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems); LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); @@ -56,6 +56,7 @@ LUAI_FUNC void luaF_close (lua_State *L, StkId level); LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, int pc); +LUAI_FUNC void luaF_shareproto (Proto *func); #endif diff --git a/3rd/lua/lgc.c b/3rd/lua/lgc.c index a5677130..e56f2922 100644 --- a/3rd/lua/lgc.c +++ b/3rd/lua/lgc.c @@ -193,6 +193,10 @@ void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { void luaC_fix (lua_State *L, GCObject *o) { global_State *g = G(L); + if (o->tt == LUA_TSHRSTR) { + luaS_fix(g, gco2ts(o)); + return; + } if (g->allgc != o) return; /* if object is not 1st in 'allgc' list, it is in global short string table */ white2gray(o); /* they will be gray forever */ @@ -235,20 +239,22 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { */ static void reallymarkobject (global_State *g, GCObject *o) { reentry: - white2gray(o); switch (o->tt) { case LUA_TSHRSTR: { - gray2black(o); - g->GCmemtrav += sizelstring(gco2ts(o)->shrlen); + luaS_mark(g, gco2ts(o)); break; } case LUA_TLNGSTR: { - gray2black(o); - g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); + if (!isshared(o)) { + white2gray(o); + gray2black(o); + g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); + } break; } case LUA_TUSERDATA: { TValue uvalue; + white2gray(o); markobjectN(g, gco2u(o)->metatable); /* mark its metatable */ gray2black(o); g->GCmemtrav += sizeudata(gco2u(o)); @@ -260,23 +266,31 @@ static void reallymarkobject (global_State *g, GCObject *o) { break; } case LUA_TLCL: { + white2gray(o); linkgclist(gco2lcl(o), g->gray); break; } case LUA_TCCL: { + white2gray(o); linkgclist(gco2ccl(o), g->gray); break; } case LUA_TTABLE: { - linkgclist(gco2t(o), g->gray); + if (!isshared(o)) + white2gray(o); + linkgclist(gco2t(o), g->gray); break; } case LUA_TTHREAD: { + white2gray(o); linkgclist(gco2th(o), g->gray); break; } case LUA_TPROTO: { - linkgclist(gco2p(o), g->gray); + if (!isshared(o)) { + white2gray(o); + linkgclist(gco2p(o), g->gray); + } break; } default: lua_assert(0); break; @@ -471,20 +485,6 @@ static lu_mem traversetable (global_State *g, Table *h) { sizeof(Node) * cast(size_t, allocsizenode(h)); } -static int marksharedproto (global_State *g, SharedProto *f) { - int i; - if (g != f->l_G) - return 0; - markobjectN(g, f->source); - for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ - markobjectN(g, f->upvalues[i].name); - for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ - markobjectN(g, f->locvars[i].varname); - return sizeof(Instruction) * f->sizecode + - sizeof(int) * f->sizelineinfo + - sizeof(LocVar) * f->sizelocvars + - sizeof(Upvaldesc) * f->sizeupvalues; -} /* ** Traverse a prototype. (While a prototype is being build, its @@ -492,20 +492,24 @@ static int marksharedproto (global_State *g, SharedProto *f) { ** NULL, so the use of 'markobjectN') */ static int traverseproto (global_State *g, Proto *f) { - int i,nk,np; - if (f->cache && iswhite(f->cache)) - f->cache = NULL; /* allow cache to be collected */ - if (f->sp == NULL) - return sizeof(Proto); - nk = (f->k == f->sp->k && g != f->sp->l_G) ? 0 : f->sp->sizek; - np = (f->p == NULL) ? 0 : f->sp->sizep; - for (i = 0; i < nk; i++) /* mark literals */ + int i; + if (g != f->l_G) + return 0; + markobjectN(g, f->source); + for (i = 0; i < f->sizek; i++) /* mark literals */ markvalue(g, &f->k[i]); - for (i = 0; i < np; i++) /* mark nested protos */ + for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ + markobjectN(g, f->upvalues[i].name); + for (i = 0; i < f->sizep; i++) /* mark nested protos */ markobjectN(g, f->p[i]); - return sizeof(Proto) + sizeof(Proto *) * np + - sizeof(TValue) * nk + - marksharedproto(g, f->sp); + for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ + markobjectN(g, f->locvars[i].varname); + return sizeof(Proto) + sizeof(Instruction) * f->sizecode + + sizeof(Proto *) * f->sizep + + sizeof(TValue) * f->sizek + + sizeof(int) * f->sizelineinfo + + sizeof(LocVar) * f->sizelocvars + + sizeof(Upvaldesc) * f->sizeupvalues; } @@ -719,10 +723,6 @@ static void freeobj (lua_State *L, GCObject *o) { case LUA_TTABLE: luaH_free(L, gco2t(o)); break; case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; - case LUA_TSHRSTR: - luaS_remove(L, gco2ts(o)); /* remove it from hash table */ - luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); - break; case LUA_TLNGSTR: { luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); break; @@ -745,7 +745,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); */ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { global_State *g = G(L); - int ow = otherwhite(g); + int ow = otherwhite(g) | bitmask(SHAREBIT); /* shared object never dead */ int white = luaC_white(g); /* current white */ while (*p != NULL && count-- > 0) { GCObject *curr = *p; @@ -783,19 +783,6 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) { ** ======================================================= */ -/* -** If possible, shrink string table -*/ -static void checkSizes (lua_State *L, global_State *g) { - if (g->gckind != KGC_EMERGENCY) { - l_mem olddebt = g->GCdebt; - if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ - luaS_resize(L, g->strt.size / 2); /* shrink it a little */ - g->GCestimate += g->GCdebt - olddebt; /* update estimate */ - } -} - - static GCObject *udata2finalize (global_State *g) { GCObject *o = g->tobefnz; /* get first element */ lua_assert(tofinalize(o)); @@ -986,7 +973,6 @@ void luaC_freeallobjects (lua_State *L) { sweepwholelist(L, &g->finobj); sweepwholelist(L, &g->allgc); sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ - lua_assert(g->strt.nuse == 0); } @@ -1057,7 +1043,7 @@ static lu_mem singlestep (lua_State *L) { global_State *g = G(L); switch (g->gcstate) { case GCSpause: { - g->GCmemtrav = g->strt.size * sizeof(GCObject*); + g->GCmemtrav = 0; restartcollection(g); g->gcstate = GCSpropagate; return g->GCmemtrav; @@ -1089,7 +1075,6 @@ static lu_mem singlestep (lua_State *L) { } case GCSswpend: { /* finish sweeps */ makewhite(g, g->mainthread); /* sweep main thread */ - checkSizes(L, g); g->gcstate = GCScallfin; return 0; } @@ -1099,6 +1084,7 @@ static lu_mem singlestep (lua_State *L) { return (n * GCFINALIZECOST); } else { /* emergency mode or no more finalizers */ + luaS_collect(g, 0); /* send short strings set to gc thread */ g->gcstate = GCSpause; /* finish collection */ return 0; } diff --git a/3rd/lua/lgc.h b/3rd/lua/lgc.h index 425cd7ce..6977ff22 100644 --- a/3rd/lua/lgc.h +++ b/3rd/lua/lgc.h @@ -79,11 +79,13 @@ #define WHITE1BIT 1 /* object is white (type 1) */ #define BLACKBIT 2 /* object is black */ #define FINALIZEDBIT 3 /* object has been marked for finalization */ +#define SHAREBIT 4 /* object shared from other state */ /* bit 7 is currently used by tests (luaL_checkmemory) */ #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) +/* short string is always white */ #define iswhite(x) testbits((x)->marked, WHITEBITS) #define isblack(x) testbit((x)->marked, BLACKBIT) #define isgray(x) /* neither white nor black */ \ @@ -91,9 +93,11 @@ #define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) +#define isshared(x) testbit((x)->marked, SHAREBIT) +#define makeshared(x) l_setbit((x)->marked, SHAREBIT) #define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) -#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) +#define isdead(g,v) isdeadm(otherwhite(g) | bitmask(SHAREBIT), (v)->marked) #define changewhite(x) ((x)->marked ^= WHITEBITS) #define gray2black(x) l_setbit((x)->marked, BLACKBIT) diff --git a/3rd/lua/lobject.h b/3rd/lua/lobject.h index b537d392..c99e0f63 100644 --- a/3rd/lua/lobject.h +++ b/3rd/lua/lobject.h @@ -307,7 +307,7 @@ typedef struct TString { unsigned int hash; union { size_t lnglen; /* length for long strings */ - struct TString *hnext; /* linked list for hash table */ + size_t ref; /* reference count for short strings */ } u; } TString; @@ -400,11 +400,15 @@ typedef struct LocVar { int endpc; /* first point where variable is dead */ } LocVar; -typedef struct SharedProto { + +/* +** Function Prototypes +*/ +typedef struct Proto { + CommonHeader; lu_byte numparams; /* number of fixed parameters */ lu_byte is_vararg; lu_byte maxstacksize; /* number of registers needed by this function */ - lu_byte sharedk; /* constants can be shared directly */ int sizeupvalues; /* size of 'upvalues' */ int sizek; /* size of 'k' */ int sizecode; @@ -413,25 +417,15 @@ typedef struct SharedProto { int sizelocvars; int linedefined; /* debug information */ int lastlinedefined; /* debug information */ - void *l_G; /* global state belongs to */ + TValue *k; /* constants used by the function */ Instruction *code; /* opcodes */ + struct Proto **p; /* functions defined inside the function */ int *lineinfo; /* map from opcodes to source lines (debug information) */ LocVar *locvars; /* information about local variables (debug information) */ Upvaldesc *upvalues; /* upvalue information */ TString *source; /* used for debug information */ - TValue *k; /* Shared constants */ -} SharedProto; - -/* -** Function Prototypes -*/ -typedef struct Proto { - CommonHeader; - struct SharedProto *sp; - TValue *k; /* constants used by the function */ - struct Proto **p; /* functions defined inside the function */ - struct LClosure *cache; /* last-created closure with this prototype */ GCObject *gclist; + void *l_G; /* global state belongs to */ } Proto; diff --git a/3rd/lua/lparser.c b/3rd/lua/lparser.c index 9e0af8bc..cc54de43 100644 --- a/3rd/lua/lparser.c +++ b/3rd/lua/lparser.c @@ -79,7 +79,7 @@ static l_noret error_expected (LexState *ls, int token) { static l_noret errorlimit (FuncState *fs, int limit, const char *what) { lua_State *L = fs->ls->L; const char *msg; - int line = fs->f->sp->linedefined; + int line = fs->f->linedefined; const char *where = (line == 0) ? "main function" : luaO_pushfstring(L, "function at line %d", line); @@ -160,15 +160,14 @@ static void checkname (LexState *ls, expdesc *e) { static int registerlocalvar (LexState *ls, TString *varname) { FuncState *fs = ls->fs; - Proto *fp = fs->f; - SharedProto *f = fp->sp; + Proto *f = fs->f; int oldsize = f->sizelocvars; luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, LocVar, SHRT_MAX, "local variables"); while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; f->locvars[fs->nlocvars].varname = varname; - luaC_objbarrier(ls->L, fp, varname); + luaC_objbarrier(ls->L, f, varname); return fs->nlocvars++; } @@ -196,7 +195,7 @@ static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { static LocVar *getlocvar (FuncState *fs, int i) { int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; lua_assert(idx < fs->nlocvars); - return &fs->f->sp->locvars[idx]; + return &fs->f->locvars[idx]; } @@ -218,7 +217,7 @@ static void removevars (FuncState *fs, int tolevel) { static int searchupvalue (FuncState *fs, TString *name) { int i; - Upvaldesc *up = fs->f->sp->upvalues; + Upvaldesc *up = fs->f->upvalues; for (i = 0; i < fs->nups; i++) { if (eqstr(up[i].name, name)) return i; } @@ -227,8 +226,7 @@ static int searchupvalue (FuncState *fs, TString *name) { static int newupvalue (FuncState *fs, TString *name, expdesc *v) { - Proto *fp = fs->f; - SharedProto *f = fp->sp; + Proto *f = fs->f; int oldsize = f->sizeupvalues; checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, @@ -238,7 +236,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { f->upvalues[fs->nups].instack = (v->k == VLOCAL); f->upvalues[fs->nups].idx = cast_byte(v->u.info); f->upvalues[fs->nups].name = name; - luaC_objbarrier(fs->ls->L, fp, name); + luaC_objbarrier(fs->ls->L, f, name); return fs->nups++; } @@ -503,13 +501,13 @@ static Proto *addprototype (LexState *ls) { lua_State *L = ls->L; FuncState *fs = ls->fs; Proto *f = fs->f; /* prototype of current function */ - if (fs->np >= f->sp->sizep) { - int oldsize = f->sp->sizep; - luaM_growvector(L, f->p, fs->np, f->sp->sizep, Proto *, MAXARG_Bx, "functions"); - while (oldsize < f->sp->sizep) + if (fs->np >= f->sizep) { + int oldsize = f->sizep; + luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); + while (oldsize < f->sizep) f->p[oldsize++] = NULL; } - f->p[fs->np++] = clp = luaF_newproto(L, NULL); + f->p[fs->np++] = clp = luaF_newproto(L); luaC_objbarrier(L, f, clp); return clp; } @@ -529,7 +527,7 @@ static void codeclosure (LexState *ls, expdesc *v) { static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { - SharedProto *f; + Proto *f; fs->prev = ls->fs; /* linked list of funcstates */ fs->ls = ls; ls->fs = fs; @@ -544,42 +542,31 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { fs->nactvar = 0; fs->firstlocal = ls->dyd->actvar.n; fs->bl = NULL; - f = fs->f->sp; + f = fs->f; f->source = ls->source; f->maxstacksize = 2; /* registers 0/1 are always valid */ enterblock(fs, bl, 0); } -static lu_byte check_shortstring(const TValue *k, int sizek) { - int i; - for (i=0;iL; FuncState *fs = ls->fs; Proto *f = fs->f; - SharedProto *sp = f->sp; luaK_ret(fs, 0, 0); /* final return */ leaveblock(fs); - luaM_reallocvector(L, sp->code, sp->sizecode, fs->pc, Instruction); - sp->sizecode = fs->pc; - luaM_reallocvector(L, sp->lineinfo, sp->sizelineinfo, fs->pc, int); - sp->sizelineinfo = fs->pc; - luaM_reallocvector(L, f->k, sp->sizek, fs->nk, TValue); - sp->sharedk = check_shortstring(f->k, fs->nk); - sp->k = f->k; - sp->sizek = fs->nk; - luaM_reallocvector(L, f->p, sp->sizep, fs->np, Proto *); - sp->sizep = fs->np; - luaM_reallocvector(L, sp->locvars, sp->sizelocvars, fs->nlocvars, LocVar); - sp->sizelocvars = fs->nlocvars; - luaM_reallocvector(L, sp->upvalues, sp->sizeupvalues, fs->nups, Upvaldesc); - sp->sizeupvalues = fs->nups; + luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); + f->sizecode = fs->pc; + luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); + f->sizelineinfo = fs->pc; + luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); + f->sizek = fs->nk; + luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); + f->sizep = fs->np; + luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); + f->sizelocvars = fs->nlocvars; + luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); + f->sizeupvalues = fs->nups; lua_assert(fs->bl == NULL); ls->fs = fs->prev; luaC_checkGC(L); @@ -755,8 +742,8 @@ static void constructor (LexState *ls, expdesc *t) { } while (testnext(ls, ',') || testnext(ls, ';')); check_match(ls, '}', '{', line); lastlistfield(fs, &cc); - SETARG_B(fs->f->sp->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ - SETARG_C(fs->f->sp->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ + SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ + SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ } /* }====================================================================== */ @@ -766,7 +753,7 @@ static void constructor (LexState *ls, expdesc *t) { static void parlist (LexState *ls) { /* parlist -> [ param { ',' param } ] */ FuncState *fs = ls->fs; - SharedProto *f = fs->f->sp; + Proto *f = fs->f; int nparams = 0; f->is_vararg = 0; if (ls->t.token != ')') { /* is 'parlist' not empty? */ @@ -797,7 +784,7 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) { FuncState new_fs; BlockCnt bl; new_fs.f = addprototype(ls); - new_fs.f->sp->linedefined = line; + new_fs.f->linedefined = line; open_func(ls, &new_fs, &bl); checknext(ls, '('); if (ismethod) { @@ -807,7 +794,7 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) { parlist(ls); checknext(ls, ')'); statlist(ls); - new_fs.f->sp->lastlinedefined = ls->linenumber; + new_fs.f->lastlinedefined = ls->linenumber; check_match(ls, TK_END, TK_FUNCTION, line); codeclosure(ls, e); close_func(ls); @@ -973,7 +960,7 @@ static void simpleexp (LexState *ls, expdesc *v) { } case TK_DOTS: { /* vararg */ FuncState *fs = ls->fs; - check_condition(ls, fs->f->sp->is_vararg, + check_condition(ls, fs->f->is_vararg, "cannot use '...' outside a vararg function"); init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); break; @@ -1609,7 +1596,7 @@ static void statement (LexState *ls) { break; } } - lua_assert(ls->fs->f->sp->maxstacksize >= ls->fs->freereg && + lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && ls->fs->freereg >= ls->fs->nactvar); ls->fs->freereg = ls->fs->nactvar; /* free registers */ leavelevel(ls); @@ -1626,7 +1613,7 @@ static void mainfunc (LexState *ls, FuncState *fs) { BlockCnt bl; expdesc v; open_func(ls, fs, &bl); - fs->f->sp->is_vararg = 1; /* main function is always declared vararg */ + fs->f->is_vararg = 1; /* main function is always declared vararg */ init_exp(&v, VLOCAL, 0); /* create and... */ newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ luaX_next(ls); /* read first token */ @@ -1646,13 +1633,13 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, lexstate.h = luaH_new(L); /* create table for scanner */ sethvalue(L, L->top, lexstate.h); /* anchor it */ luaD_inctop(L); - funcstate.f = cl->p = luaF_newproto(L, NULL); - funcstate.f->sp->source = luaS_new(L, name); /* create and anchor TString */ + funcstate.f = cl->p = luaF_newproto(L); + funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ lua_assert(iswhite(funcstate.f)); /* do not need barrier here */ lexstate.buff = buff; lexstate.dyd = dyd; dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; - luaX_setinput(L, &lexstate, z, funcstate.f->sp->source, firstchar); + luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); mainfunc(&lexstate, &funcstate); lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); /* all scopes should be correctly finished */ diff --git a/3rd/lua/lstate.c b/3rd/lua/lstate.c index c1a76643..d0cd5e75 100644 --- a/3rd/lua/lstate.c +++ b/3rd/lua/lstate.c @@ -70,27 +70,6 @@ typedef struct LG { #define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) -/* -** Compute an initial seed as random as possible. Rely on Address Space -** Layout Randomization (if present) to increase randomness.. -*/ -#define addbuff(b,p,e) \ - { size_t t = cast(size_t, e); \ - memcpy(b + p, &t, sizeof(t)); p += sizeof(t); } - -static unsigned int makeseed (lua_State *L) { - char buff[4 * sizeof(size_t)]; - unsigned int h = luai_makeseed(); - int p = 0; - addbuff(buff, p, L); /* heap variable */ - addbuff(buff, p, &h); /* local variable */ - addbuff(buff, p, luaO_nilobject); /* global variable */ - addbuff(buff, p, &lua_newstate); /* public function */ - lua_assert(p == sizeof(buff)); - return luaS_hash(buff, p, h); -} - - /* ** set GCdebt to a new value keeping the value (totalbytes + GCdebt) ** invariant (and avoiding underflows in 'totalbytes') @@ -245,7 +224,7 @@ static void close_state (lua_State *L) { luaC_freeallobjects(L); /* collect all objects */ if (g->version) /* closing a fully built state? */ luai_userstateclose(L); - luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); + luaS_collect(g, 1); /* clear short strings */ freestack(L); lua_assert(gettotalbytes(g) == sizeof(LG)); (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ @@ -308,11 +287,8 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->frealloc = f; g->ud = ud; g->mainthread = L; - g->seed = makeseed(L); g->gcrunning = 0; /* no GC while building state */ g->GCestimate = 0; - g->strt.size = g->strt.nuse = 0; - g->strt.hash = NULL; setnilvalue(&g->l_registry); g->panic = NULL; g->version = NULL; @@ -328,6 +304,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->gcfinnum = 0; g->gcpause = LUAI_GCPAUSE; g->gcstepmul = LUAI_GCMUL; + g->strsave = NULL; + g->strmark = NULL; + g->strfix = NULL; for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { /* memory allocation error: free partial state */ diff --git a/3rd/lua/lstate.h b/3rd/lua/lstate.h index 56b37410..5ccf7bac 100644 --- a/3rd/lua/lstate.h +++ b/3rd/lua/lstate.h @@ -130,6 +130,8 @@ typedef struct CallInfo { #define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) #define getoah(st) ((st) & CIST_OAH) +/* SSM (short string map) See lstring.c */ +struct ssm_ref; /* ** 'global state', shared by all threads of this state @@ -141,9 +143,7 @@ typedef struct global_State { l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ lu_mem GCmemtrav; /* memory traversed by the GC */ lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ - stringtable strt; /* hash table for strings */ TValue l_registry; - unsigned int seed; /* randomized seed for hashes */ lu_byte currentwhite; lu_byte gcstate; /* state of garbage collector */ lu_byte gckind; /* kind of GC running */ @@ -169,6 +169,9 @@ typedef struct global_State { TString *tmname[TM_N]; /* array with tag-method names */ struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ + struct ssm_ref *strsave; + struct ssm_ref *strmark; + struct ssm_ref *strfix; } global_State; diff --git a/3rd/lua/lstring.c b/3rd/lua/lstring.c index 095771e1..5368bde0 100644 --- a/3rd/lua/lstring.c +++ b/3rd/lua/lstring.c @@ -9,7 +9,6 @@ #include "lprefix.h" - #include #include #include "lua.h" @@ -21,6 +20,9 @@ #include "lstate.h" #include "lstring.h" +static unsigned int STRSEED; + +#define STRFIXSIZE 64 #define MEMERRMSG "not enough memory" @@ -65,37 +67,6 @@ unsigned int luaS_hashlongstr (TString *ts) { } -/* -** resizes the string table -*/ -void luaS_resize (lua_State *L, int newsize) { - int i; - stringtable *tb = &G(L)->strt; - if (newsize > tb->size) { /* grow table if needed */ - luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); - for (i = tb->size; i < newsize; i++) - tb->hash[i] = NULL; - } - for (i = 0; i < tb->size; i++) { /* rehash */ - TString *p = tb->hash[i]; - tb->hash[i] = NULL; - while (p) { /* for each node in the list */ - TString *hnext = p->u.hnext; /* save next */ - unsigned int h = lmod(p->hash, newsize); /* new position */ - p->u.hnext = tb->hash[h]; /* chain it */ - tb->hash[h] = p; - p = hnext; - } - } - if (newsize < tb->size) { /* shrink table if needed */ - /* vanishing slice should be empty */ - lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); - luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); - } - tb->size = newsize; -} - - /* ** Clear API string cache. (Entries cannot be empty, so fill them with ** a non-collectable string.) @@ -104,11 +75,12 @@ void luaS_clearcache (global_State *g) { int i, j; for (i = 0; i < STRCACHE_N; i++) for (j = 0; j < STRCACHE_M; j++) { - if (iswhite(g->strcache[i][j])) /* will entry be collected? */ + if (!isshared(g->strcache[i][j]) && iswhite(g->strcache[i][j])) /* will entry be collected? */ g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */ } } +static struct ssm_ref * newref(int size); /* ** Initialize the string table and the string cache @@ -116,7 +88,8 @@ void luaS_clearcache (global_State *g) { void luaS_init (lua_State *L) { global_State *g = G(L); int i, j; - luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + g->strsave = newref(MINSTRTABSIZE); + g->strmark = newref(MINSTRTABSIZE); /* pre-create memory-error message */ g->memerrmsg = luaS_newliteral(L, MEMERRMSG); luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ @@ -143,71 +116,12 @@ static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) { return ts; } -static unsigned int LNGSTR_SEED; -static unsigned int make_lstr_seed() { - size_t buff[4]; - unsigned int h = time(NULL); - buff[0] = cast(size_t, h); - buff[1] = cast(size_t, &LNGSTR_SEED); - buff[2] = cast(size_t, &make_lstr_seed); - buff[3] = cast(size_t, &luaS_createlngstrobj); - return luaS_hash((const char*)buff, sizeof(buff), h); -} - TString *luaS_createlngstrobj (lua_State *L, size_t l) { - TString *ts = createstrobj(L, l, LUA_TLNGSTR, LNGSTR_SEED); + TString *ts = createstrobj(L, l, LUA_TLNGSTR, STRSEED); ts->u.lnglen = l; return ts; } - -void luaS_remove (lua_State *L, TString *ts) { - stringtable *tb = &G(L)->strt; - TString **p = &tb->hash[lmod(ts->hash, tb->size)]; - while (*p != ts) /* find previous element */ - p = &(*p)->u.hnext; - *p = (*p)->u.hnext; /* remove element from its list */ - tb->nuse--; -} - - -/* -** checks whether short string exists and reuses it or creates a new one -*/ -static TString *queryshrstr (lua_State *L, const char *str, size_t l, unsigned int h) { - TString *ts; - global_State *g = G(L); - TString **list = &g->strt.hash[lmod(h, g->strt.size)]; - lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ - for (ts = *list; ts != NULL; ts = ts->u.hnext) { - if (l == ts->shrlen && - (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { - /* found! */ - if (isdead(g, ts)) /* dead (but not collected yet)? */ - changewhite(ts); /* resurrect it */ - return ts; - } - } - return NULL; -} - -static TString *addshrstr (lua_State *L, const char *str, size_t l, unsigned int h) { - TString *ts; - global_State *g = G(L); - TString **list = &g->strt.hash[lmod(h, g->strt.size)]; - if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) { - luaS_resize(L, g->strt.size * 2); - list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ - } - ts = createstrobj(L, l, LUA_TSHRSTR, h); - memcpy(getstr(ts), str, l * sizeof(char)); - ts->shrlen = cast_byte(l); - ts->u.hnext = *list; - *list = ts; - g->strt.nuse++; - return ts; -} - static TString *internshrstr (lua_State *L, const char *str, size_t l); /* @@ -268,29 +182,453 @@ Udata *luaS_newudata (lua_State *L, size_t s) { */ #include "rwlock.h" +#include "spinlock.h" #include "atomic.h" #include +#include -#define getaddrstr(ts) (cast(char *, (ts)) + sizeof(UTString)) #define SHRSTR_INITSIZE 0x10000 +/* prime is better for hash */ +#define VMHASHSLOTS 4093 + struct shrmap_slot { struct rwlock lock; TString *str; }; +struct ssm_ref { + TString **hash; + TString **array; + int nuse; /* number of elements */ + int hsize; + int asize; + int acap; +}; + +struct collect_queue { + struct collect_queue *next; + void * key; + struct ssm_ref *strsave; + struct ssm_ref *strmark; + struct ssm_ref *strfix; +}; + struct shrmap { struct rwlock lock; - int n; - int mask; + int rwslots; int total; int roslots; struct shrmap_slot * readwrite; struct shrmap_slot * readonly; + struct spinlock qlock; + struct collect_queue * head; + struct collect_queue * tail; + struct collect_queue * vm[VMHASHSLOTS]; }; static struct shrmap SSM; +#define ADD_SREF(ts) ATOM_INC(&((ts)->u.ref)) +#define DEC_SREF(ts) ATOM_DEC(&((ts)->u.ref)) +#define ZERO_SREF(ts) ((ts)->u.ref == 0) + +static struct ssm_ref * +newref(int size) { + /* size must be must be power of 2 */ + lua_assert( (size&(size-1))==0 ); + struct ssm_ref *r = (struct ssm_ref *)malloc(sizeof(*r)); + if (r == NULL) + return NULL; + TString **hash = (TString **)malloc(sizeof(TString *) * size); + if (hash == NULL) { + free(r); + return NULL; + } + memset(r, 0, sizeof(*r)); + memset(hash, 0, sizeof(TString *) * size); + r->hsize = size; + r->hash = hash; + return r; +} + +static void +expand_ref(struct ssm_ref *r, int changeref) { + int hsize = r->hsize * 2; + TString ** hash = (TString **)malloc(sizeof(TString *) * hsize); + if (hash == NULL) + return; + memset(hash, 0, sizeof(TString *) * hsize); + int i; + for (i=0;ihsize;i++) { + TString *s = r->hash[i]; + if (s) { + hash[lmod(s->hash, hsize)] = s; + } + } + free(r->hash); + r->hash = hash; + r->hsize = hsize; + + for (i=0;iasize;) { + TString *s = r->array[i]; + int slot = lmod(s->hash, hsize); + TString *hs = hash[slot]; + if (hs == s || hs == NULL) { + if (hs == NULL) + hash[slot] = s; + else { + --r->nuse; + if (changeref) + DEC_SREF(s); + } + --r->asize; + r->array[i] = r->array[r->asize]; + } else { + ++i; + } + } +} + +static void +insert_ref(struct ssm_ref *r, TString *s) { + if (r->asize >= r->acap) { + r->acap = r->asize * 2; + if (r->acap == 0) { + r->acap = r->hsize / 2; + } + TString ** array = (TString **)realloc(r->array, r->acap * sizeof(TString *)); + lua_assert(array != NULL); + r->array = array; + } + r->array[r->asize++] = s; +} + +static void +shrink_ref(struct ssm_ref *r) { + int hsize = r->hsize / 2; + if (hsize < MINSTRTABSIZE) + return; + TString ** hash = (TString **)malloc(sizeof(TString *) * hsize); + if (hash == NULL) + return; + memset(hash, 0, sizeof(TString *) * hsize); + int i; + for (i=0;ihsize;i++) { + TString *s = r->hash[i]; + if (s) { + int h = lmod(s->hash, hsize); + if (hash[h] == NULL) + hash[h] = s; + else + insert_ref(r, s); + } + } + free(r->hash); + r->hash = hash; + r->hsize = hsize; +} + +static void +markref(struct ssm_ref *r, TString *s, int changeref) { + unsigned int h = s->hash; + int slot = lmod(h, r->hsize); + TString * hs = r->hash[slot]; + if (hs == s) + return; + ++r->nuse; + if (r->nuse >= r->hsize && r->hsize <= MAX_INT/2) { + expand_ref(r, changeref); + slot = lmod(h, r->hsize); + hs = r->hash[slot]; + } + if (hs != NULL) { + if (hs == s) { + --r->nuse; + return; + } + insert_ref(r, hs); + } + r->hash[slot] = s; +} + +void +luaS_mark(global_State *g, TString *s) { + markref(g->strmark, s, 0); +} + +void +luaS_fix(global_State *g, TString *s) { + if (g->strfix == NULL) + g->strfix = newref(STRFIXSIZE); + markref(g->strfix, s, 0); +} + +static void +delete_ref(struct ssm_ref *r) { + if (r == NULL) + return; + free(r->hash); + free(r->array); + free(r); +} + +static void +delete_cqueue(struct collect_queue *cqueue) { + delete_ref(cqueue->strsave); + delete_ref(cqueue->strmark); + delete_ref(cqueue->strfix); + free(cqueue); +} + +static void +free_cqueue(struct collect_queue *cqueue) { + while (cqueue) { + struct collect_queue * next = cqueue->next; + delete_cqueue(cqueue); + cqueue = next; + } +} + +static void +remove_duplicate(struct ssm_ref *r, int decref) { + int i = 0; + while (i < r->asize) { + TString *s = r->array[i]; + if (r->hash[lmod(s->hash, r->hsize)] == s) { + --r->nuse; + --r->asize; + r->array[i] = r->array[r->asize]; + if (decref) { + DEC_SREF(s); + } + } else { + ++i; + } + } +} + +static struct ssm_ref * +mergeset(struct ssm_ref *set, struct ssm_ref * rset, int changeref) { + if (set == NULL) + return rset; + else if (rset == NULL) + return set; + int total = set->nuse + rset->nuse; + if (total * 2 <= set->hsize) { + shrink_ref(set); + } else if (total > set->hsize) { + expand_ref(set, changeref); + } + int i; + for (i=0;ihsize;i++) { + TString * s = rset->hash[i]; + if (s) { + insert_ref(set, s); + } + } + for (i=0;iasize;i++) { + TString * s = rset->array[i]; + insert_ref(set, s); + } + delete_ref(rset); + remove_duplicate(set, changeref); + return set; +} + +static void +merge_last(struct collect_queue * c) { + void *key = c->key; + int hash = (int)((uintptr_t)key % VMHASHSLOTS); + struct shrmap * s = &SSM; + struct collect_queue * slot = s->vm[hash]; + if (slot == NULL) { + s->vm[hash] = c; + c->next = NULL; + return; + } + + if (slot->key == key) { + // remove head + s->vm[hash] = slot->next; + } else { + for (;;) { + struct collect_queue * next = slot->next; + if (next == NULL) { + // not found, insert head + c->next = s->vm[hash]; + s->vm[hash] = c; + return; + } else if (next->key == key) { + // remove next + slot->next = next->next; + slot = next; + break; + } + slot = next; + } + } + // merge slot (last) into c + c->strsave = mergeset(slot->strsave, c->strsave, 1); + c->strfix = mergeset(slot->strfix, c->strfix, 0); + c->next = s->vm[hash]; + s->vm[hash] = c; + free(slot); +} + +static void +clear_vm(struct collect_queue * c) { + void *key = c->key; + int hash = (int)((uintptr_t)key % VMHASHSLOTS); + struct shrmap * s = &SSM; + struct collect_queue * slot = s->vm[hash]; + lua_assert(slot == c); + s->vm[hash] = slot->next; + delete_cqueue(slot); +} + +static int +compar_tstring(const void *a, const void *b) { + return memcmp(a,b, sizeof(TString *)); +} + +static void +sortset(struct ssm_ref *set) { + qsort(set->array, set->asize,sizeof(TString *),compar_tstring); +} + +static int +exist(struct ssm_ref *r, TString *s) { + int slot = lmod(s->hash, r->hsize); + TString *hs = r->hash[slot]; + if (hs == s) + return 1; + int begin = 0, end = r->asize-1; + while (begin <= end) { + int mid = (begin + end) / 2; + TString *t = r->array[mid]; + if (t == s) + return 1; + if (s > t) + begin = mid + 1; + else + end = mid - 1; + } + return 0; +} + +static int +collectref(struct collect_queue * c) { + int i; + int total = 0; + merge_last(c); + struct ssm_ref *mark = c->strmark; + struct ssm_ref * save = c->strsave; + c->strmark = NULL; + if (mark) { + struct ssm_ref * fix = c->strfix; + sortset(mark); + sortset(fix); + + for (i=0;ihsize;i++) { + TString * s = save->hash[i]; + if (s) { + if (!exist(mark, s) && !exist(fix, s)) { + save->hash[i] = NULL; + DEC_SREF(s); + ++total; + } + } + } + + for (i=0;iasize;) { + TString * s = save->array[i]; + if (!exist(mark, s) && !exist(fix, s)) { + --save->asize; + save->array[i] = save->array[save->asize]; + DEC_SREF(s); + ++total; + } else { + ++i; + } + } + delete_ref(mark); + } else { + for (i=0;ihsize;i++) { + TString * s = save->hash[i]; + if (s) { + DEC_SREF(s); + ++total; + } + } + for (i=0;iasize;i++) { + TString * s = save->array[i]; + DEC_SREF(s); + ++total; + } + clear_vm(c); + } + return total; +} + +static int +pow2size(struct ssm_ref *r) { + if (r->nuse <= MINSTRTABSIZE) + return MINSTRTABSIZE; + int hsize = r->hsize; + while (hsize / 2 > r->nuse) { + hsize /= 2; + } + return hsize; +} + +void +luaS_collect(global_State *g, int closed) { + if (closed) { + delete_ref(g->strmark); + g->strmark = NULL; + } + struct shrmap * s = &SSM; + struct collect_queue *cqueue = (struct collect_queue *)malloc(sizeof(*cqueue)); + if (cqueue == NULL) { + /* OOM, give up */ + return; + } + cqueue->key = g; + cqueue->strsave = g->strsave; + cqueue->strmark = g->strmark; + cqueue->strfix = g->strfix; + cqueue->next = NULL; + + g->strfix = NULL; + if (closed) { + g->strsave = NULL; + g->strmark = NULL; + } else { + g->strsave = newref(pow2size(g->strsave)); + g->strmark = newref(pow2size(g->strmark)); + } + + spinlock_lock(&s->qlock); + if (s->head) { + s->tail->next = cqueue; + s->tail = cqueue; + } else { + s->head = s->tail = cqueue; + } + spinlock_unlock(&s->qlock); +} + +static unsigned int make_str_seed() { + size_t buff[4]; + unsigned int h = time(NULL); + buff[0] = cast(size_t, h); + buff[1] = cast(size_t, &STRSEED); + buff[2] = cast(size_t, &make_str_seed); + buff[3] = cast(size_t, SHRSTR_INITSIZE); + return luaS_hash((const char*)buff, sizeof(buff), h); +} + static struct shrmap_slot * shrstr_newpage(int sz) { int i; @@ -311,7 +649,7 @@ shrstr_deletepage(struct shrmap_slot *s, int sz) { for (i=0;iu.hnext; + TString * next = (TString *)str->next; free(str); str = next; } @@ -324,12 +662,12 @@ static int shrstr_allocpage(struct shrmap * s, int osz, int sz, struct shrmap_slot * newpage) { if (s->readonly != NULL) return 0; - if ((s->mask + 1) != osz) + if (s->rwslots != osz) return 0; s->readonly = s->readwrite; s->readwrite = newpage; - s->roslots = s->mask + 1; - s->mask = sz - 1; + s->roslots = s->rwslots; + s->rwslots = sz; return 1; } @@ -340,13 +678,18 @@ shrstr_rehash(struct shrmap *s, int slotid) { rwlock_wlock(&slot->lock); TString *str = slot->str; while (str) { - TString * next = str->u.hnext; - int newslotid = str->hash & s->mask; - struct shrmap_slot *newslot = &s->readwrite[newslotid]; - rwlock_wlock(&newslot->lock); - str->u.hnext = newslot->str; - newslot->str = str; - rwlock_wunlock(&newslot->lock); + TString * next = (TString *)str->next; + if (ZERO_SREF(str)) { + free(str); + ATOM_DEC(&SSM.total); + } else { + int newslotid = lmod(str->hash, s->rwslots); + struct shrmap_slot *newslot = &s->readwrite[newslotid]; + rwlock_wlock(&newslot->lock); + str->next = (GCObject *)newslot->str; + newslot->str = str; + rwlock_wunlock(&newslot->lock); + } str = next; } @@ -363,17 +706,15 @@ shrstr_rehash(struct shrmap *s, int slotid) { 6. remove temporary readonly (writelock SSM) */ static void -shrstr_expandpage(int cap) { +expandssm() { struct shrmap * s = &SSM; if (s->readonly) return; - int osz = s->mask + 1; + int osz = s->rwslots; int sz = osz * 2; - while (sz < cap) { + if (sz < osz) { // overflow check - if (sz <= 0) - return; - sz = sz * 2; + return; } struct shrmap_slot * newpage = shrstr_newpage(sz); if (newpage == NULL) @@ -396,50 +737,105 @@ shrstr_expandpage(int cap) { shrstr_deletepage(oldpage, osz); } -LUA_API void -luaS_initshr() { +/* call it in a separate thread */ +LUA_API int +luaS_collectssm(struct ssm_collect *info) { struct shrmap * s = &SSM; - rwlock_init(&s->lock); - s->n = 0; - s->mask = SHRSTR_INITSIZE - 1; - s->readwrite = shrstr_newpage(SHRSTR_INITSIZE); - s->readonly = NULL; - LNGSTR_SEED = make_lstr_seed(); + if (s->total * 5 / 4 > s->rwslots) { + expandssm(); + } + if (s->head) { + struct collect_queue * cqueue; + spinlock_lock(&s->qlock); + cqueue = s->head; + s->head = cqueue->next; + spinlock_unlock(&s->qlock); + if (cqueue) { + if (info) { + info->key = cqueue->key; + } + int n = collectref(cqueue); + if (info) { + info->n = n; + } + } + return 1; + } + return 0; } LUA_API void -luaS_exitshr() { +luaS_initssm() { + struct shrmap * s = &SSM; + rwlock_init(&s->lock); + s->rwslots = SHRSTR_INITSIZE; + s->readwrite = shrstr_newpage(SHRSTR_INITSIZE); + s->readonly = NULL; + s->head = NULL; + s->tail = NULL; + spinlock_init(&s->qlock); + STRSEED = make_str_seed(); +} + +LUA_API void +luaS_exitssm() { struct shrmap * s = &SSM; rwlock_wlock(&s->lock); - int sz = s->mask + 1; + int sz = s->rwslots; shrstr_deletepage(s->readwrite, sz); shrstr_deletepage(s->readonly, s->roslots); s->readwrite = NULL; s->readonly = NULL; + free_cqueue(s->head); + s->head = NULL; + s->tail = NULL; + int i; + for (i=0;ivm[i]); + s->vm[i] = NULL; + } } static TString * -find_string(TString *t, struct shrmap_slot * slot, unsigned int h, const char *str, lu_byte l) { +find_string(struct shrmap_slot * slot, unsigned int h, const char *str, lu_byte l) { TString *ts = slot->str; - if (t) { - while (ts) { - if (ts == t) - break; - ts = ts->u.hnext; + while (ts) { + if (ts->hash == h && + ts->shrlen == l && + memcmp(str, ts+1, l) == 0) { + ADD_SREF(ts); + break; } - } else { - while (ts) { - if (ts->hash == h && - ts->shrlen == l && - memcmp(str, ts+1, l) == 0) { - break; - } - ts = ts->u.hnext; + ts = (TString *)ts->next; + } + return ts; +} + +static TString * +find_and_collect(struct shrmap_slot * slot, unsigned int h, const char *str, lu_byte l) { + TString **ref = &slot->str; + TString *ts = *ref; + while (ts) { + if (ts->hash == h && + ts->shrlen == l && + memcmp(str, ts+1, l) == 0) { + ADD_SREF(ts); + break; + } + if (ZERO_SREF(ts)) { + *ref = (TString *)ts->next; + free(ts); + ts = *ref; + ATOM_DEC(&SSM.total); + } else { + ref = (TString **)&(ts->next); + ts = *ref; } } return ts; } + /* 1. readlock SSM 2. find string in readwrite page @@ -447,19 +843,19 @@ find_string(TString *t, struct shrmap_slot * slot, unsigned int h, const char *s 4. unlock SSM */ static TString * -query_string(TString *t, unsigned int h, const char *str, lu_byte l) { +query_string(unsigned int h, const char *str, lu_byte l) { struct shrmap * s = &SSM; TString *ts = NULL; rwlock_rlock(&s->lock); - struct shrmap_slot *slot = &s->readwrite[h & s->mask]; + struct shrmap_slot *slot = &s->readwrite[lmod(h, s->rwslots)]; rwlock_rlock(&slot->lock); - ts = find_string(t, slot, h, str, l); + ts = find_string(slot, h, str, l); rwlock_runlock(&slot->lock); if (ts == NULL && s->readonly != NULL) { int mask = s->roslots - 1; slot = &s->readonly[h & mask]; rwlock_rlock(&slot->lock); - ts = find_string(t, slot, h, str, l); + ts = find_string(slot, h, str, l); rwlock_runlock(&slot->lock); } rwlock_runlock(&s->lock); @@ -471,9 +867,13 @@ new_string(unsigned int h, const char *str, lu_byte l) { size_t sz = sizelstring(l); TString *ts = malloc(sz); memset(ts, 0, sz); + setbits(ts->marked, WHITEBITS); + gray2black(ts); + makeshared(ts); ts->tt = LUA_TSHRSTR; ts->hash = h; ts->shrlen = l; + ts->u.ref = 1; memcpy(ts+1, str, l); return ts; } @@ -485,14 +885,19 @@ shrstr_exist(struct shrmap * s, unsigned int h, const char *str, lu_byte l) { unsigned int mask = s->roslots - 1; struct shrmap_slot *slot = &s->readonly[h & mask]; rwlock_rlock(&slot->lock); - found = find_string(NULL, slot, h, str, l); + found = find_string(slot, h, str, l); rwlock_runlock(&slot->lock); if (found) return found; } - struct shrmap_slot *slot = &s->readwrite[h & s->mask]; + struct shrmap_slot *slot = &s->readwrite[lmod(h, s->rwslots)]; rwlock_wlock(&slot->lock); - found = find_string(NULL, slot, h, str, l); + if (s->readonly) { + // Don't collect during expanding + found = find_string(slot, h, str, l); + } else { + found = find_and_collect(slot, h, str, l); + } if (found) { rwlock_wunlock(&slot->lock); return found; @@ -511,9 +916,9 @@ add_string(unsigned int h, const char *str, lu_byte l) { // string is create by other thread, so free tmp free(tmp); } else { - struct shrmap_slot *slot = &s->readwrite[h & s->mask]; + struct shrmap_slot *slot = &s->readwrite[lmod(h, s->rwslots)]; ts = tmp; - ts->u.hnext = slot->str; + ts->next = (GCObject *)slot->str; slot->str = ts; rwlock_wunlock(&slot->lock); ATOM_INC(&SSM.total); @@ -523,76 +928,20 @@ add_string(unsigned int h, const char *str, lu_byte l) { } static TString * -internshrstr (lua_State *L, const char *str, size_t l) { - TString *ts; - global_State *g = G(L); - unsigned int h = luaS_hash(str, l, g->seed); - unsigned int h0; - // lookup global state of this L first - ts = queryshrstr (L, str, l, h); - if (ts) - return ts; - // lookup SSM again - h0 = luaS_hash(str, l, 0); - ts = query_string(NULL, h0, str, l); - if (ts) - return ts; - // If SSM.n greate than 0, add it to SSM - if (SSM.n > 0) { - ATOM_DEC(&SSM.n); - return add_string(h0, str, l); - } - // Else add it to global state (local) - return addshrstr (L, str, l, h); -} - -LUA_API void -luaS_expandshr(int n) { - struct shrmap * s = &SSM; - if (n < 0) { - if (-n > s->n) { - n = -s->n; - } +internshrstr(lua_State *L, const char *str, size_t l) { + TString *ts; + unsigned int h = luaS_hash(str, l, STRSEED); + ts = query_string(h, str, l); + if (ts == NULL) { + ts = add_string(h, str, l); } - ATOM_ADD(&s->n, n); - if (n > 0) { - int t = (s->total + s->n) * 5 / 4; - if (t > s->mask) { - shrstr_expandpage(t); - } - } -} - -LUAI_FUNC TString * -luaS_clonestring(lua_State *L, TString *ts) { - unsigned int h; - int l; - const char * str = getaddrstr(ts); - global_State *g = G(L); - TString *result; - if (ts->tt == LUA_TLNGSTR) - return luaS_newlstr(L, str, ts->u.lnglen); - // look up global state of this L first - l = ts->shrlen; - h = luaS_hash(str, l, g->seed); - result = queryshrstr (L, str, l, h); - if (result) - return result; - // look up SSM by ptr - result = query_string(ts, ts->hash, NULL, 0); - if (result) - return result; - h = luaS_hash(str, l, 0); - result = query_string(NULL, h, str, l); - if (result) - return result; - // ts is not in SSM, so recalc hash, and add it to SSM - return add_string(h, str, l); + markref(G(L)->strsave, ts, 1); + return ts; } struct slotinfo { int len; - int size; + size_t size; }; static void @@ -603,12 +952,11 @@ getslot(struct shrmap_slot *s, struct slotinfo *info) { while (ts) { ++info->len; info->size += sizelstring(ts->shrlen); - ts = ts->u.hnext; + ts = (TString *)ts->next; } rwlock_runlock(&s->lock); } - struct variance { int count; double mean; @@ -625,8 +973,8 @@ variance_update(struct variance *v, int newValue_) { v->m2 += delta * delta2; } -LUA_API int -luaS_shrinfo(lua_State *L) { +LUA_API void +luaS_infossm(struct ssm_info *info) { struct slotinfo total; struct slotinfo tmp; memset(&total, 0, sizeof(total)); @@ -635,7 +983,7 @@ luaS_shrinfo(lua_State *L) { int slots = 0; rwlock_rlock(&s->lock); int i; - int sz = s->mask + 1; + int sz = s->rwslots; for (i=0;ireadwrite[i]; getslot(slot, &tmp); @@ -663,15 +1011,13 @@ luaS_shrinfo(lua_State *L) { } } rwlock_runlock(&s->lock); - lua_pushinteger(L, SSM.total); // count - lua_pushinteger(L, total.size); // total size - lua_pushinteger(L, total.len); // longest - lua_pushinteger(L, SSM.n); // space - lua_pushinteger(L, slots); // slots + info->total = SSM.total; + info->size = total.size; + info->longest = total.len; + info->slots = slots; if (v.count > 1) { - lua_pushnumber(L, v.m2 / v.count); // variance + info->variance = v.m2 / v.count; } else { - lua_pushnumber(L, 0); // variance + info->variance = 0; } - return 6; } diff --git a/3rd/lua/lstring.h b/3rd/lua/lstring.h index e6a38b88..22525adf 100644 --- a/3rd/lua/lstring.h +++ b/3rd/lua/lstring.h @@ -36,10 +36,8 @@ LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts); LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); -LUAI_FUNC void luaS_resize (lua_State *L, int newsize); LUAI_FUNC void luaS_clearcache (global_State *g); LUAI_FUNC void luaS_init (lua_State *L); -LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); 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_new (lua_State *L, const char *str); @@ -47,10 +45,26 @@ LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); #define ENABLE_SHORT_STRING_TABLE -LUA_API void luaS_initshr(); -LUA_API void luaS_exitshr(); -LUA_API void luaS_expandshr(int n); -LUAI_FUNC TString *luaS_clonestring(lua_State *L, TString *); -LUA_API int luaS_shrinfo(lua_State *L); +struct ssm_info { + int total; + int longest; + int slots; + size_t size; + double variance; +}; + +struct ssm_collect { + void *key; + int n; +}; + +LUA_API void luaS_initssm(); +LUA_API void luaS_exitssm(); +LUA_API void luaS_infossm(struct ssm_info *info); +LUA_API int luaS_collectssm(struct ssm_collect *info); + +LUAI_FUNC void luaS_mark(global_State *g, TString *s); +LUAI_FUNC void luaS_fix(global_State *g, TString *s); +LUAI_FUNC void luaS_collect(global_State *g, int closed); #endif diff --git a/3rd/lua/lua.c b/3rd/lua/lua.c index 23217967..cad0d9f4 100644 --- a/3rd/lua/lua.c +++ b/3rd/lua/lua.c @@ -597,7 +597,7 @@ static int pmain (lua_State *L) { int main (int argc, char **argv) { int status, result; lua_State *L; - luaS_initshr(); /* init global short string table */ + luaS_initssm(); L = luaL_newstate(); /* create state */ if (L == NULL) { l_message(argv[0], "cannot create state: not enough memory"); @@ -610,7 +610,7 @@ int main (int argc, char **argv) { result = lua_toboolean(L, -1); /* get result */ report(L, status); lua_close(L); - luaS_exitshr(); + luaS_exitssm(); return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/3rd/lua/lua.h b/3rd/lua/lua.h index 7bf639f1..a944404b 100644 --- a/3rd/lua/lua.h +++ b/3rd/lua/lua.h @@ -233,7 +233,8 @@ LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); LUA_API void (lua_pushboolean) (lua_State *L, int b); LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); LUA_API int (lua_pushthread) (lua_State *L); - +LUA_API void (lua_clonefunction) (lua_State *L, const void * fp); +LUA_API void (lua_sharefunction) (lua_State *L, int index); /* ** get functions (Lua -> stack) @@ -282,8 +283,6 @@ LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); -LUA_API void (lua_clonefunction) (lua_State *L, const void *eL); - /* ** coroutine functions @@ -460,11 +459,6 @@ struct lua_Debug { /* }====================================================================== */ -/* Add by skynet */ - -LUA_API lua_State * skynet_sig_L; -LUA_API void (lua_checksig_)(lua_State *L); -#define lua_checksig(L) if (skynet_sig_L) { lua_checksig_(L); } /****************************************************************************** * Copyright (C) 1994-2018 Lua.org, PUC-Rio. diff --git a/3rd/lua/luac.c b/3rd/lua/luac.c index 46dda035..62a0509b 100644 --- a/3rd/lua/luac.c +++ b/3rd/lua/luac.c @@ -150,9 +150,9 @@ static const Proto* combine(lua_State* L, int n) for (i=0; ip[i]=toproto(L,i-n-1); - if (f->p[i]->sp->sizeupvalues>0) f->p[i]->sp->upvalues[0].instack=0; + if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; } - f->sp->sizelineinfo=0; + f->sizelineinfo=0; return f; } } @@ -193,10 +193,10 @@ static int pmain(lua_State* L) int main(int argc, char* argv[]) { lua_State* L; + luaS_initssm(); int i=doargs(argc,argv); argc-=i; argv+=i; if (argc<=0) usage("no input files given"); - luaS_initshr(); L=luaL_newstate(); if (L==NULL) fatal("cannot create state: not enough memory"); lua_pushcfunction(L,&pmain); @@ -204,6 +204,7 @@ int main(int argc, char* argv[]) lua_pushlightuserdata(L,argv); if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); lua_close(L); + luaS_exitssm(); return EXIT_SUCCESS; } @@ -284,13 +285,13 @@ static void PrintConstant(const Proto* f, int i) } } -#define UPVALNAME(x) ((f->sp->upvalues[x].name) ? getstr(f->sp->upvalues[x].name) : "-") +#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") #define MYK(x) (-1-(x)) static void PrintCode(const Proto* f) { - const Instruction* code=f->sp->code; - int pc,n=f->sp->sizecode; + const Instruction* code=f->code; + int pc,n=f->sizecode; for (pc=0; pcsource ? getstr(f->source) : "=?"; if (*s=='@' || *s=='=') @@ -417,9 +418,8 @@ static void PrintHeader(const SharedProto* f) static void PrintDebug(const Proto* f) { - const SharedProto *sp = f->sp; int i,n; - n=sp->sizek; + n=f->sizek; printf("constants (%d) for %p:\n",n,VOID(f)); for (i=0; isizelocvars; + n=f->sizelocvars; printf("locals (%d) for %p:\n",n,VOID(f)); for (i=0; ilocvars[i].varname),sp->locvars[i].startpc+1,sp->locvars[i].endpc+1); + i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); } - n=f->sp->sizeupvalues; + n=f->sizeupvalues; printf("upvalues (%d) for %p:\n",n,VOID(f)); for (i=0; iupvalues[i].instack,sp->upvalues[i].idx); + i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx); } } static void PrintFunction(const Proto* f, int full) { - int i,n=f->sp->sizep; - PrintHeader(f->sp); + int i,n=f->sizep; + PrintHeader(f); PrintCode(f); if (full) PrintDebug(f); for (i=0; ip[i],full); diff --git a/3rd/lua/lualib.h b/3rd/lua/lualib.h index 422b9ea5..f5304aa0 100644 --- a/3rd/lua/lualib.h +++ b/3rd/lua/lualib.h @@ -47,8 +47,6 @@ LUAMOD_API int (luaopen_debug) (lua_State *L); #define LUA_LOADLIBNAME "package" LUAMOD_API int (luaopen_package) (lua_State *L); -#define LUA_CACHELIB -LUAMOD_API int (luaopen_cache) (lua_State *L); /* open all previous libraries */ LUALIB_API void (luaL_openlibs) (lua_State *L); diff --git a/3rd/lua/lundump.c b/3rd/lua/lundump.c index 86057037..7a67d75a 100644 --- a/3rd/lua/lundump.c +++ b/3rd/lua/lundump.c @@ -104,7 +104,7 @@ static TString *LoadString (LoadState *S) { } -static void LoadCode (LoadState *S, SharedProto *f) { +static void LoadCode (LoadState *S, Proto *f) { int n = LoadInt(S); f->code = luaM_newvector(S->L, n, Instruction); f->sizecode = n; @@ -119,9 +119,7 @@ static void LoadConstants (LoadState *S, Proto *f) { int i; int n = LoadInt(S); f->k = luaM_newvector(S->L, n, TValue); - f->sp->k = f->k; - f->sp->sizek = n; - f->sp->sharedk = 1; + f->sizek = n; for (i = 0; i < n; i++) setnilvalue(&f->k[i]); for (i = 0; i < n; i++) { @@ -141,8 +139,6 @@ static void LoadConstants (LoadState *S, Proto *f) { setivalue(o, LoadInteger(S)); break; case LUA_TSHRSTR: - f->sp->sharedk = 0; - //fall-through case LUA_TLNGSTR: setsvalue2n(S->L, o, LoadString(S)); break; @@ -157,17 +153,17 @@ static void LoadProtos (LoadState *S, Proto *f) { int i; int n = LoadInt(S); f->p = luaM_newvector(S->L, n, Proto *); - f->sp->sizep = n; + f->sizep = n; for (i = 0; i < n; i++) f->p[i] = NULL; for (i = 0; i < n; i++) { - f->p[i] = luaF_newproto(S->L, NULL); - LoadFunction(S, f->p[i], f->sp->source); + f->p[i] = luaF_newproto(S->L); + LoadFunction(S, f->p[i], f->source); } } -static void LoadUpvalues (LoadState *S, SharedProto *f) { +static void LoadUpvalues (LoadState *S, Proto *f) { int i, n; n = LoadInt(S); f->upvalues = luaM_newvector(S->L, n, Upvaldesc); @@ -181,7 +177,7 @@ static void LoadUpvalues (LoadState *S, SharedProto *f) { } -static void LoadDebug (LoadState *S, SharedProto *f) { +static void LoadDebug (LoadState *S, Proto *f) { int i, n; n = LoadInt(S); f->lineinfo = luaM_newvector(S->L, n, int); @@ -203,8 +199,7 @@ static void LoadDebug (LoadState *S, SharedProto *f) { } -static void LoadFunction (LoadState *S, Proto *fp, TString *psource) { - SharedProto *f = fp->sp; +static void LoadFunction (LoadState *S, Proto *f, TString *psource) { f->source = LoadString(S); if (f->source == NULL) /* no source in dump? */ f->source = psource; /* reuse parent's source */ @@ -214,9 +209,9 @@ static void LoadFunction (LoadState *S, Proto *fp, TString *psource) { f->is_vararg = LoadByte(S); f->maxstacksize = LoadByte(S); LoadCode(S, f); - LoadConstants(S, fp); + LoadConstants(S, f); LoadUpvalues(S, f); - LoadProtos(S, fp); + LoadProtos(S, f); LoadDebug(S, f); } @@ -275,9 +270,9 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { cl = luaF_newLclosure(L, LoadByte(&S)); setclLvalue(L, L->top, cl); luaD_inctop(L); - cl->p = luaF_newproto(L, NULL); + cl->p = luaF_newproto(L); LoadFunction(&S, cl->p, NULL); - lua_assert(cl->nupvalues == cl->p->sp->sizeupvalues); + lua_assert(cl->nupvalues == cl->p->sizeupvalues); luai_verifycode(L, buff, cl->p); return cl; } diff --git a/3rd/lua/lvm.c b/3rd/lua/lvm.c index f968ba01..a2888848 100644 --- a/3rd/lua/lvm.c +++ b/3rd/lua/lvm.c @@ -63,17 +63,7 @@ #endif -/* Add by skynet */ -lua_State * skynet_sig_L = NULL; -LUA_API void -lua_checksig_(lua_State *L) { - if (skynet_sig_L == G(L)->mainthread) { - skynet_sig_L = NULL; - lua_pushnil(L); - lua_error(L); - } -} /* ** Try to convert a value to a float. The float case is already handled @@ -612,27 +602,6 @@ lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { } -/* -** check whether cached closure in prototype 'p' may be reused, that is, -** whether there is a cached closure with the same upvalues needed by -** new closure to be created. -*/ -static LClosure *getcached (Proto *p, UpVal **encup, StkId base) { - LClosure *c = p->cache; - if (c != NULL) { /* is there a cached closure? */ - int nup = p->sp->sizeupvalues; - Upvaldesc *uv = p->sp->upvalues; - int i; - for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ - TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; - if (c->upvals[i]->v != v) - return NULL; /* wrong upvalue; cannot reuse closure */ - } - } - return c; /* return cached closure (or NULL if no cached closure) */ -} - - /* ** create a new Lua closure, push it in the stack, and initialize ** its upvalues. Note that the closure is not cached if prototype is @@ -641,8 +610,8 @@ static LClosure *getcached (Proto *p, UpVal **encup, StkId base) { */ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, StkId ra) { - int nup = p->sp->sizeupvalues; - Upvaldesc *uv = p->sp->upvalues; + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; int i; LClosure *ncl = luaF_newLclosure(L, nup); ncl->p = p; @@ -655,8 +624,6 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, ncl->upvals[i]->refcount++; /* new closure is white, so we do not need a barrier here */ } - if (!isblack(p)) /* cache will not break GC invariant? */ - p->cache = ncl; /* save it on cache for reuse */ } @@ -1088,7 +1055,6 @@ void luaV_execute (lua_State *L) { vmbreak; } vmcase(OP_JMP) { - lua_checksig(L); dojump(ci, i, 0); vmbreak; } @@ -1141,7 +1107,6 @@ void luaV_execute (lua_State *L) { vmcase(OP_CALL) { int b = GETARG_B(i); int nresults = GETARG_C(i) - 1; - lua_checksig(L); if (b != 0) L->top = ra+b; /* else previous instruction set top */ if (luaD_precall(L, ra, nresults)) { /* C function? */ if (nresults >= 0) @@ -1156,7 +1121,6 @@ void luaV_execute (lua_State *L) { } vmcase(OP_TAILCALL) { int b = GETARG_B(i); - lua_checksig(L); if (b != 0) L->top = ra+b; /* else previous instruction set top */ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ @@ -1169,10 +1133,10 @@ void luaV_execute (lua_State *L) { StkId nfunc = nci->func; /* called function */ StkId ofunc = oci->func; /* caller function */ /* last stack slot filled by 'precall' */ - StkId lim = nci->u.l.base + getproto(nfunc)->sp->numparams; + StkId lim = nci->u.l.base + getproto(nfunc)->numparams; int aux; /* close all upvalues from previous call */ - if (cl->p->sp->sizep > 0) luaF_close(L, oci->u.l.base); + if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); /* move new frame into old one */ for (aux = 0; nfunc + aux < lim; aux++) setobjs2s(L, ofunc + aux, nfunc + aux); @@ -1181,14 +1145,14 @@ void luaV_execute (lua_State *L) { oci->u.l.savedpc = nci->u.l.savedpc; oci->callstatus |= CIST_TAIL; /* function was tail called */ ci = L->ci = oci; /* remove new frame */ - lua_assert(L->top == oci->u.l.base + getproto(ofunc)->sp->maxstacksize); + lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); goto newframe; /* restart luaV_execute over new Lua function */ } vmbreak; } vmcase(OP_RETURN) { int b = GETARG_B(i); - if (cl->p->sp->sizep > 0) luaF_close(L, base); + if (cl->p->sizep > 0) luaF_close(L, base); b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */ return; /* external invocation: return */ @@ -1201,7 +1165,6 @@ void luaV_execute (lua_State *L) { } } vmcase(OP_FORLOOP) { - lua_checksig(L); if (ttisinteger(ra)) { /* integer loop? */ lua_Integer step = ivalue(ra + 2); lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */ @@ -1268,7 +1231,6 @@ void luaV_execute (lua_State *L) { } vmcase(OP_TFORLOOP) { l_tforloop: - lua_checksig(L); if (!ttisnil(ra + 1)) { /* continue loop? */ setobjs2s(L, ra, ra + 1); /* save control variable */ ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ @@ -1299,18 +1261,14 @@ void luaV_execute (lua_State *L) { } vmcase(OP_CLOSURE) { Proto *p = cl->p->p[GETARG_Bx(i)]; - LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ - if (ncl == NULL) /* no match? */ - pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ - else - setclLvalue(L, ra, ncl); /* push cashed closure */ + pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ checkGC(L, ra + 1); vmbreak; } vmcase(OP_VARARG) { int b = GETARG_B(i) - 1; /* required results */ int j; - int n = cast_int(base - ci->func) - cl->p->sp->numparams - 1; + int n = cast_int(base - ci->func) - cl->p->numparams - 1; if (n < 0) /* less arguments than parameters? */ n = 0; /* no vararg arguments */ if (b < 0) { /* B == 0? */ diff --git a/Makefile b/Makefile index 004aabb9..f2b7df0d 100644 --- a/Makefile +++ b/Makefile @@ -69,6 +69,7 @@ LUA_CLIB_SKYNET = \ lua-stm.c \ lua-debugchannel.c \ lua-datasheet.c \ + lua-ssm.c \ \ SKYNET_SRC = skynet_main.c skynet_handle.c skynet_module.c skynet_mq.c \ diff --git a/lualib-src/lua-memory.c b/lualib-src/lua-memory.c index 426acf18..b9b07a61 100644 --- a/lualib-src/lua-memory.c +++ b/lualib-src/lua-memory.c @@ -4,7 +4,6 @@ #include #include "malloc_hook.h" -#include "luashrtbl.h" static int ltotal(lua_State *L) { @@ -36,13 +35,6 @@ ldump(lua_State *L) { return 0; } -static int -lexpandshrtbl(lua_State *L) { - int n = luaL_checkinteger(L, 1); - luaS_expandshr(n); - return 0; -} - static int lcurrent(lua_State *L) { lua_pushinteger(L, malloc_current_memory()); @@ -79,8 +71,6 @@ luaopen_skynet_memory(lua_State *L) { { "dumpinfo", ldumpinfo }, { "dump", ldump }, { "info", dump_mem_lua }, - { "ssinfo", luaS_shrinfo }, - { "ssexpand", lexpandshrtbl }, { "current", lcurrent }, { "dumpheap", ldumpheap }, { "profactive", lprofactive }, diff --git a/lualib-src/lua-ssm.c b/lualib-src/lua-ssm.c new file mode 100644 index 00000000..4988057d --- /dev/null +++ b/lualib-src/lua-ssm.c @@ -0,0 +1,72 @@ +#define LUA_LIB + +#include +#include +#include + +#include "lstring.h" + +static int +linfo(lua_State *L) { + struct ssm_info info; + memset(&info, 0, sizeof(info)); + luaS_infossm(&info); + lua_createtable(L, 0, 5); + lua_pushinteger(L, info.total); + lua_setfield(L, -2, "n"); + lua_pushinteger(L, info.longest); + lua_setfield(L, -2, "longest"); + lua_pushinteger(L, info.slots); + lua_setfield(L, -2, "slots"); + lua_pushinteger(L, info.size); + lua_setfield(L, -2, "size"); + lua_pushnumber(L, info.variance); + lua_setfield(L, -2, "variance"); + + return 1; +} + +static int +lcollect(lua_State *L) { + int loop = lua_toboolean(L, 1); + if (loop) { + int n = 0; + struct ssm_collect info; + while (luaS_collectssm(&info)) { + n+=info.n; + } + lua_pushinteger(L, n); + return 1; + } else { + struct ssm_collect info; + int again = luaS_collectssm(&info); + if (again && lua_istable(L, 2)) { + lua_pushinteger(L, info.n); + lua_setfield(L, 2, "n"); + lua_pushlightuserdata(L, info.key); + lua_setfield(L, 2, "key"); + } + lua_pushboolean(L, again); + return 1; + } +} + +LUAMOD_API int +luaopen_skynet_ssm(lua_State *L) { + luaL_checkversion(L); + + luaL_Reg l[] = { + { "info", linfo }, + { "collect", lcollect }, + { NULL, NULL }, + }; + + luaL_newlib(L,l); + +#ifndef ENABLE_SHORT_STRING_TABLE + lua_pushboolean(L, 1); + lua_setfield(L, -2, "disable"); +#endif + return 1; +} + diff --git a/service/bootstrap.lua b/service/bootstrap.lua index 3dabfd8a..195544b7 100644 --- a/service/bootstrap.lua +++ b/service/bootstrap.lua @@ -1,17 +1,15 @@ local skynet = require "skynet" local harbor = require "skynet.harbor" require "skynet.manager" -- import skynet.launch, ... -local memory = require "skynet.memory" skynet.start(function() - local sharestring = tonumber(skynet.getenv "sharestring" or 4096) - memory.ssexpand(sharestring) - local standalone = skynet.getenv "standalone" local launcher = assert(skynet.launch("snlua","launcher")) skynet.name(".launcher", launcher) + skynet.newservice "garbagecollect" + local harbor_id = tonumber(skynet.getenv "harbor" or 0) if harbor_id == 0 then assert(standalone == nil) diff --git a/service/debug_console.lua b/service/debug_console.lua index 0323c215..2ed44f79 100644 --- a/service/debug_console.lua +++ b/service/debug_console.lua @@ -155,7 +155,6 @@ function COMMAND.help() debug = "debug address : debug a lua service", signal = "signal address sig", cmem = "Show C memory info", - shrtbl = "Show shared short string table info", ping = "ping address", call = "call address ...", trace = "trace address [proto] [on|off]", @@ -337,11 +336,6 @@ function COMMAND.cmem() return tmp end -function COMMAND.shrtbl() - local n, total, longest, space, slots, variance = memory.ssinfo() - return { n = n, total = total, longest = longest, space = space, slots = slots, average = n / slots, variace = variance } -end - function COMMAND.ping(address) address = adjust_address(address) local ti = skynet.now() diff --git a/skynet-src/luashrtbl.h b/skynet-src/luashrtbl.h index a9485ccd..0dcb2799 100644 --- a/skynet-src/luashrtbl.h +++ b/skynet-src/luashrtbl.h @@ -6,10 +6,23 @@ // If you use modified lua, this macro would be defined in lstring.h #ifndef ENABLE_SHORT_STRING_TABLE -static inline int luaS_shrinfo(lua_State *L) { return 0; } -static inline void luaS_initshr() {} -static inline void luaS_exitshr() {} -static inline void luaS_expandshr(int n) {} +struct ssm_info { + int total; + int longest; + int slots; + size_t size; + double variance; +}; + +struct ssm_collect { + void *key; + int n; +}; + +static inline void luaS_initssm(); +static inline void luaS_exitssm(); +static inline void luaS_infossm(struct ssm_info *info) {} +static inline int luaS_collectssm(struct ssm_collect *info) { return 0; } #endif diff --git a/skynet-src/skynet_main.c b/skynet-src/skynet_main.c index 3e394d11..d9aef78a 100644 --- a/skynet-src/skynet_main.c +++ b/skynet-src/skynet_main.c @@ -126,7 +126,7 @@ main(int argc, char *argv[]) { return 1; } - luaS_initshr(); + luaS_initssm(); skynet_globalinit(); skynet_env_init(); @@ -162,7 +162,7 @@ main(int argc, char *argv[]) { skynet_start(&config); skynet_globalexit(); - luaS_exitshr(); + luaS_exitssm(); return 0; }