diff --git a/3rd/lua/lapi.c b/3rd/lua/lapi.c index fbfafa30..bf5e829f 100644 --- a/3rd/lua/lapi.c +++ b/3rd/lua/lapi.c @@ -28,6 +28,7 @@ #include "ltm.h" #include "lundump.h" #include "lvm.h" +#include "lfunc.h" @@ -984,6 +985,59 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, } +static Proto * cloneproto (lua_State *L, const Proto *src) { + /* copy constants and nested proto */ + int i,n; + Proto *f = luaF_newproto(L, src->sp); + n = src->sp->sizek; + 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 * str = luaS_newlstr(L,svalue(s),tsvalue(s)->len); + setsvalue2n(L,o,str); + } else { + setobj(L,o,s); + } + } + n = src->sp->sizep; + f->p=luaM_newvector(L,n,struct Proto *); + for (i=0; ip[i]=NULL; + for (i=0; ip[i]=cloneproto(L, src->p[i]); + } + return f; +} + +LUA_API void lua_clonefunction (lua_State *L, void * fp) { + LClosure *cl; + LClosure *f = cast(LClosure *, fp); + lua_lock(L); + if (f->p->sp->l_G == G(L)) { + setclLvalue(L,L->top,f); + api_incr_top(L); + lua_unlock(L); + return; + } + cl = luaF_newLclosure(L,f->nupvalues); + cl->p = cloneproto(L, f->p); + setclLvalue(L,L->top,cl); + api_incr_top(L); + luaF_initupvals(L, cl); + + if (f->nupvalues >= 1) { /* does it have an upvalue? */ + /* get global table from registry */ + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ + setobj(L, f->upvals[0]->v, gt); + luaC_upvalbarrier(L, f->upvals[0]); + } + lua_unlock(L); +} + LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { int status; TValue *o; @@ -1178,7 +1232,7 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val, case LUA_TLCL: { /* Lua closure */ LClosure *f = clLvalue(fi); TString *name; - Proto *p = f->p; + SharedProto *p = f->p->sp; if (!(1 <= n && n <= p->sizeupvalues)) return NULL; *val = f->upvals[n-1]->v; if (uv) *uv = f->upvals[n - 1]; diff --git a/3rd/lua/lcode.c b/3rd/lua/lcode.c index 5e34624b..0f0a6752 100644 --- a/3rd/lua/lcode.c +++ b/3rd/lua/lcode.c @@ -55,7 +55,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->code[fs->pc-1]; + previous = &fs->f->sp->code[fs->pc-1]; if (GET_OPCODE(*previous) == OP_LOADNIL) { int pfrom = GETARG_A(*previous); int pl = pfrom + GETARG_B(*previous); @@ -95,7 +95,7 @@ static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { static void fixjump (FuncState *fs, int pc, int dest) { - Instruction *jmp = &fs->f->code[pc]; + Instruction *jmp = &fs->f->sp->code[pc]; int offset = dest-(pc+1); lua_assert(dest != NO_JUMP); if (abs(offset) > MAXARG_sBx) @@ -115,7 +115,7 @@ int luaK_getlabel (FuncState *fs) { static int getjump (FuncState *fs, int pc) { - int offset = GETARG_sBx(fs->f->code[pc]); + int offset = GETARG_sBx(fs->f->sp->code[pc]); if (offset == NO_JUMP) /* point to itself represents end of list */ return NO_JUMP; /* end of list */ else @@ -124,7 +124,7 @@ static int getjump (FuncState *fs, int pc) { static Instruction *getjumpcontrol (FuncState *fs, int pc) { - Instruction *pi = &fs->f->code[pc]; + Instruction *pi = &fs->f->sp->code[pc]; if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) return pi-1; else @@ -197,10 +197,10 @@ void luaK_patchclose (FuncState *fs, int list, int level) { level++; /* argument is +1 to reserve 0 as non-op */ while (list != NO_JUMP) { int next = getjump(fs, list); - 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); + 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); list = next; } } @@ -230,13 +230,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->code, fs->pc, f->sizecode, Instruction, + luaM_growvector(fs->ls->L, f->sp->code, fs->pc, f->sp->sizecode, Instruction, MAX_INT, "opcodes"); - f->code[fs->pc] = i; + f->sp->code[fs->pc] = i; /* save corresponding line information */ - luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + luaM_growvector(fs->ls->L, f->sp->lineinfo, fs->pc, f->sp->sizelineinfo, int, MAX_INT, "opcodes"); - f->lineinfo[fs->pc] = fs->ls->lastline; + f->sp->lineinfo[fs->pc] = fs->ls->lastline; return fs->pc++; } @@ -277,10 +277,10 @@ 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->maxstacksize) { + if (newstack > fs->f->sp->maxstacksize) { if (newstack >= MAXREGS) luaX_syntaxerror(fs->ls, "function or expression too complex"); - fs->f->maxstacksize = cast_byte(newstack); + fs->f->sp->maxstacksize = cast_byte(newstack); } } @@ -322,13 +322,13 @@ static int addk (FuncState *fs, TValue *key, TValue *v) { return k; /* reuse index */ } /* constant not found; create a new entry */ - oldsize = f->sizek; + oldsize = f->sp->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->sizek, TValue, MAXARG_Ax, "constants"); - while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + luaM_growvector(L, f->k, k, f->sp->sizek, TValue, MAXARG_Ax, "constants"); + while (oldsize < f->sp->sizek) setnilvalue(&f->k[oldsize++]); setobj(L, &f->k[k], v); fs->nk++; luaC_barrier(L, f, v); @@ -933,7 +933,7 @@ void luaK_posfix (FuncState *fs, BinOpr op, void luaK_fixline (FuncState *fs, int line) { - fs->f->lineinfo[fs->pc - 1] = line; + fs->f->sp->lineinfo[fs->pc - 1] = line; } diff --git a/3rd/lua/lcode.h b/3rd/lua/lcode.h index 43ab86db..b4c865f9 100644 --- a/3rd/lua/lcode.h +++ b/3rd/lua/lcode.h @@ -40,7 +40,7 @@ typedef enum BinOpr { typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; -#define getcode(fs,e) ((fs)->f->code[(e)->u.info]) +#define getcode(fs,e) ((fs)->f->sp->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 6986bf0f..ab10dd99 100644 --- a/3rd/lua/ldebug.c +++ b/3rd/lua/ldebug.c @@ -98,14 +98,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->sizeupvalues, p->upvalues[uv].name); + TString *s = check_exp(uv < p->sizeupvalues, p->sp->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->numparams; + int nparams = clLvalue(ci->func)->p->sp->numparams; if (n >= ci->u.l.base - ci->func - nparams) return NULL; /* no such vararg */ else { @@ -184,7 +184,7 @@ static void funcinfo (lua_Debug *ar, Closure *cl) { ar->what = "C"; } else { - Proto *p = cl->l.p; + SharedProto *p = cl->l.p->sp; ar->source = p->source ? getstr(p->source) : "=?"; ar->linedefined = p->linedefined; ar->lastlinedefined = p->lastlinedefined; @@ -202,12 +202,12 @@ static void collectvalidlines (lua_State *L, Closure *f) { else { int i; TValue v; - int *lineinfo = f->l.p->lineinfo; + int *lineinfo = f->l.p->sp->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->sizelineinfo; i++) /* for all lines with code */ + for (i = 0; i < f->l.p->sp->sizelineinfo; i++) /* for all lines with code */ luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ } } @@ -233,8 +233,8 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, ar->nparams = 0; } else { - ar->isvararg = f->l.p->is_vararg; - ar->nparams = f->l.p->numparams; + ar->isvararg = f->l.p->sp->is_vararg; + ar->nparams = f->l.p->sp->numparams; } break; } @@ -343,7 +343,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->code[pc]; + Instruction i = p->sp->code[pc]; OpCode op = GET_OPCODE(i); int a = GETARG_A(i); switch (op) { @@ -393,7 +393,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->code[pc]; + Instruction i = p->sp->code[pc]; OpCode op = GET_OPCODE(i); switch (op) { case OP_MOVE: { @@ -419,7 +419,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->code[pc + 1]); + : GETARG_Ax(p->sp->code[pc + 1]); if (ttisstring(&p->k[b])) { *name = svalue(&p->k[b]); return "constant"; @@ -442,7 +442,7 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { TMS tm = (TMS)0; /* to avoid warnings */ Proto *p = ci_func(ci)->p; /* calling function */ int pc = currentpc(ci); /* calling instruction index */ - Instruction i = p->code[pc]; /* calling instruction */ + Instruction i = p->sp->code[pc]; /* calling instruction */ if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ *name = "?"; return "hook"; @@ -577,7 +577,7 @@ static void addinfo (lua_State *L, const char *msg) { if (isLua(ci)) { /* is Lua code? */ char buff[LUA_IDSIZE]; /* add file:line information */ int line = currentline(ci); - TString *src = ci_func(ci)->p->source; + TString *src = ci_func(ci)->p->sp->source; if (src) luaO_chunkid(buff, getstr(src), LUA_IDSIZE); else { /* no source available; use "?" instead */ diff --git a/3rd/lua/ldebug.h b/3rd/lua/ldebug.h index 0d8966ca..916ce308 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)->code) - 1) +#define pcRel(pc, p) (cast(int, (pc) - (p)->sp->code) - 1) -#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : -1) +#define getfuncline(f,pc) (((f)->sp->lineinfo) ? (f)->sp->lineinfo[pc] : -1) #define resethookcount(L) (L->hookcount = L->basehookcount) diff --git a/3rd/lua/ldo.c b/3rd/lua/ldo.c index 6159e51d..227a8b82 100644 --- a/3rd/lua/ldo.c +++ b/3rd/lua/ldo.c @@ -269,7 +269,7 @@ static void callhook (lua_State *L, CallInfo *ci) { } -static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { +static StkId adjust_varargs (lua_State *L, SharedProto *p, int actual) { int i; int nfixargs = p->numparams; StkId base, fixed; @@ -342,7 +342,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { } case LUA_TLCL: { /* Lua function: prepare its call */ StkId base; - Proto *p = clLvalue(func)->p; + SharedProto *p = clLvalue(func)->p->sp; n = cast_int(L->top - func) - 1; /* number of real arguments */ luaD_checkstack(L, p->maxstacksize); for (; n < p->numparams; n++) diff --git a/3rd/lua/ldump.c b/3rd/lua/ldump.c index b6c7114f..c4efac16 100644 --- a/3rd/lua/ldump.c +++ b/3rd/lua/ldump.c @@ -86,7 +86,7 @@ static void DumpString (const TString *s, DumpState *D) { } -static void DumpCode (const Proto *f, DumpState *D) { +static void DumpCode (const SharedProto *f, DumpState *D) { DumpInt(f->sizecode, D); DumpVector(f->code, f->sizecode, D); } @@ -96,7 +96,7 @@ static void DumpFunction(const Proto *f, TString *psource, DumpState *D); static void DumpConstants (const Proto *f, DumpState *D) { int i; - int n = f->sizek; + int n = f->sp->sizek; DumpInt(n, D); for (i = 0; i < n; i++) { const TValue *o = &f->k[i]; @@ -126,14 +126,14 @@ static void DumpConstants (const Proto *f, DumpState *D) { static void DumpProtos (const Proto *f, DumpState *D) { int i; - int n = f->sizep; + int n = f->sp->sizep; DumpInt(n, D); for (i = 0; i < n; i++) - DumpFunction(f->p[i], f->source, D); + DumpFunction(f->p[i], f->sp->source, D); } -static void DumpUpvalues (const Proto *f, DumpState *D) { +static void DumpUpvalues (const SharedProto *f, DumpState *D) { int i, n = f->sizeupvalues; DumpInt(n, D); for (i = 0; i < n; i++) { @@ -143,7 +143,7 @@ static void DumpUpvalues (const Proto *f, DumpState *D) { } -static void DumpDebug (const Proto *f, DumpState *D) { +static void DumpDebug (const SharedProto *f, DumpState *D) { int i, n; n = (D->strip) ? 0 : f->sizelineinfo; DumpInt(n, D); @@ -162,7 +162,8 @@ static void DumpDebug (const Proto *f, DumpState *D) { } -static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { +static void DumpFunction (const Proto *fp, TString *psource, DumpState *D) { + const SharedProto *f = fp->sp; if (D->strip || f->source == psource) DumpString(NULL, D); /* no debug info or same source as its parent */ else @@ -173,9 +174,9 @@ static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { DumpByte(f->is_vararg, D); DumpByte(f->maxstacksize, D); DumpCode(f, D); - DumpConstants(f, D); + DumpConstants(fp, D); DumpUpvalues(f, D); - DumpProtos(f, D); + DumpProtos(fp, D); DumpDebug(f, D); } @@ -207,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->sizeupvalues, &D); + DumpByte(f->sp->sizeupvalues, &D); DumpFunction(f, NULL, &D); return D.status; } diff --git a/3rd/lua/lfunc.c b/3rd/lua/lfunc.c index 67967dab..c1f2daf7 100644 --- a/3rd/lua/lfunc.c +++ b/3rd/lua/lfunc.c @@ -96,39 +96,52 @@ void luaF_close (lua_State *L, StkId level) { } -Proto *luaF_newproto (lua_State *L) { +Proto *luaF_newproto (lua_State *L, SharedProto *sp) { 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->sizep = 0; - f->code = NULL; f->cache = 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; + 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; + } + f->sp = sp; return f; } +static void freesharedproto (lua_State *L, SharedProto *f) { + if (f == NULL || G(L) != f->l_G) + return; + 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_free(L, f); +} + void luaF_freeproto (lua_State *L, Proto *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_freearray(L, f->p, f->sp->sizep); + luaM_freearray(L, f->k, f->sp->sizek); + freesharedproto(L, f->sp); luaM_free(L, f); } @@ -137,8 +150,9 @@ 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 *f, int local_number, int pc) { +const char *luaF_getlocalname (const Proto *fp, 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--; diff --git a/3rd/lua/lfunc.h b/3rd/lua/lfunc.h index 256d3cf9..9d02a4b3 100644 --- a/3rd/lua/lfunc.h +++ b/3rd/lua/lfunc.h @@ -40,7 +40,7 @@ struct UpVal { #define upisopen(up) ((up)->v != &(up)->u.value) -LUAI_FUNC Proto *luaF_newproto (lua_State *L); +LUAI_FUNC Proto *luaF_newproto (lua_State *L, SharedProto *sp); 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); diff --git a/3rd/lua/lgc.c b/3rd/lua/lgc.c index 8b95fb67..0be4866a 100644 --- a/3rd/lua/lgc.c +++ b/3rd/lua/lgc.c @@ -456,26 +456,32 @@ static lu_mem traversetable (global_State *g, Table *h) { sizeof(Node) * cast(size_t, sizenode(h)); } +static int marksharedproto (global_State *g, SharedProto *f) { + int i; + if (g != f->l_G) + return 0; + markobject(g, f->source); + for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ + markobject(g, f->upvalues[i].name); + for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ + markobject(g, f->locvars[i].varname); + return sizeof(Instruction) * f->sizecode + + sizeof(int) * f->sizelineinfo + + sizeof(LocVar) * f->sizelocvars + + sizeof(Upvaldesc) * f->sizeupvalues; +} static int traverseproto (global_State *g, Proto *f) { int i; if (f->cache && iswhite(f->cache)) f->cache = NULL; /* allow cache to be collected */ - markobject(g, f->source); - for (i = 0; i < f->sizek; i++) /* mark literals */ + for (i = 0; i < f->sp->sizek; i++) /* mark literals */ markvalue(g, &f->k[i]); - for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ - markobject(g, f->upvalues[i].name); - for (i = 0; i < f->sizep; i++) /* mark nested protos */ + for (i = 0; i < f->sp->sizep; i++) /* mark nested protos */ markobject(g, f->p[i]); - for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ - markobject(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; + return sizeof(Proto) + sizeof(Proto *) * f->sp->sizep + + sizeof(TValue) * f->sp->sizek + + marksharedproto(g, f->sp); } diff --git a/3rd/lua/lobject.h b/3rd/lua/lobject.h index d7d0ebf3..01f29139 100644 --- a/3rd/lua/lobject.h +++ b/3rd/lua/lobject.h @@ -392,11 +392,7 @@ typedef struct LocVar { } LocVar; -/* -** Function Prototypes -*/ -typedef struct Proto { - CommonHeader; +typedef struct SharedProto { lu_byte numparams; /* number of fixed parameters */ lu_byte is_vararg; lu_byte maxstacksize; /* maximum stack used by this function */ @@ -408,14 +404,23 @@ typedef struct Proto { int sizelocvars; int linedefined; int lastlinedefined; - TValue *k; /* constants used by the function */ + void *l_G; /* global state belongs to */ Instruction *code; - 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 */ - struct LClosure *cache; /* last created closure with this prototype */ TString *source; /* used for debug information */ +} 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; } Proto; diff --git a/3rd/lua/lparser.c b/3rd/lua/lparser.c index 9a54dfc9..0bed0dd3 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->linedefined; + int line = fs->f->sp->linedefined; const char *where = (line == 0) ? "main function" : luaO_pushfstring(L, "function at line %d", line); @@ -160,13 +160,14 @@ static void checkname (LexState *ls, expdesc *e) { static int registerlocalvar (LexState *ls, TString *varname) { FuncState *fs = ls->fs; - Proto *f = fs->f; + Proto *fp = fs->f; + SharedProto *f = fp->sp; 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, f, varname); + luaC_objbarrier(ls->L, fp, varname); return fs->nlocvars++; } @@ -194,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->locvars[idx]; + return &fs->f->sp->locvars[idx]; } @@ -216,7 +217,7 @@ static void removevars (FuncState *fs, int tolevel) { static int searchupvalue (FuncState *fs, TString *name) { int i; - Upvaldesc *up = fs->f->upvalues; + Upvaldesc *up = fs->f->sp->upvalues; for (i = 0; i < fs->nups; i++) { if (eqstr(up[i].name, name)) return i; } @@ -225,7 +226,8 @@ static int searchupvalue (FuncState *fs, TString *name) { static int newupvalue (FuncState *fs, TString *name, expdesc *v) { - Proto *f = fs->f; + Proto *fp = fs->f; + SharedProto *f = fp->sp; int oldsize = f->sizeupvalues; checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, @@ -234,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, f, name); + luaC_objbarrier(fs->ls->L, fp, name); return fs->nups++; } @@ -496,12 +498,12 @@ 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->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; + 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) f->p[oldsize++] = NULL; } - f->p[fs->np++] = clp = luaF_newproto(L); + f->p[fs->np++] = clp = luaF_newproto(L, NULL); luaC_objbarrier(L, f, clp); return clp; } @@ -521,7 +523,7 @@ static void codeclosure (LexState *ls, expdesc *v) { static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { - Proto *f; + SharedProto *f; fs->prev = ls->fs; /* linked list of funcstates */ fs->ls = ls; ls->fs = fs; @@ -536,7 +538,7 @@ 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; + f = fs->f->sp; f->source = ls->source; f->maxstacksize = 2; /* registers 0/1 are always valid */ enterblock(fs, bl, 0); @@ -547,20 +549,21 @@ static void close_func (LexState *ls) { lua_State *L = ls->L; FuncState *fs = ls->fs; Proto *f = fs->f; + SharedProto *sp = f->sp; luaK_ret(fs, 0, 0); /* final return */ leaveblock(fs); - 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; + 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->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; lua_assert(fs->bl == NULL); ls->fs = fs->prev; luaC_checkGC(L); @@ -736,8 +739,8 @@ static void constructor (LexState *ls, expdesc *t) { } while (testnext(ls, ',') || testnext(ls, ';')); check_match(ls, '}', '{', line); lastlistfield(fs, &cc); - 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 */ + 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 */ } /* }====================================================================== */ @@ -747,7 +750,7 @@ static void constructor (LexState *ls, expdesc *t) { static void parlist (LexState *ls) { /* parlist -> [ param { ',' param } ] */ FuncState *fs = ls->fs; - Proto *f = fs->f; + SharedProto *f = fs->f->sp; int nparams = 0; f->is_vararg = 0; if (ls->t.token != ')') { /* is 'parlist' not empty? */ @@ -778,7 +781,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->linedefined = line; + new_fs.f->sp->linedefined = line; open_func(ls, &new_fs, &bl); checknext(ls, '('); if (ismethod) { @@ -788,7 +791,7 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) { parlist(ls); checknext(ls, ')'); statlist(ls); - new_fs.f->lastlinedefined = ls->linenumber; + new_fs.f->sp->lastlinedefined = ls->linenumber; check_match(ls, TK_END, TK_FUNCTION, line); codeclosure(ls, e); close_func(ls); @@ -954,7 +957,7 @@ static void simpleexp (LexState *ls, expdesc *v) { } case TK_DOTS: { /* vararg */ FuncState *fs = ls->fs; - check_condition(ls, fs->f->is_vararg, + check_condition(ls, fs->f->sp->is_vararg, "cannot use '...' outside a vararg function"); init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); break; @@ -1610,7 +1613,7 @@ static void mainfunc (LexState *ls, FuncState *fs) { BlockCnt bl; expdesc v; open_func(ls, fs, &bl); - fs->f->is_vararg = 1; /* main function is always vararg */ + fs->f->sp->is_vararg = 1; /* main function is always vararg */ init_exp(&v, VLOCAL, 0); /* create and... */ newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ luaX_next(ls); /* read first token */ @@ -1630,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 */ incr_top(L); - funcstate.f = cl->p = luaF_newproto(L); - funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ + funcstate.f = cl->p = luaF_newproto(L, NULL); + funcstate.f->sp->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->source, firstchar); + luaX_setinput(L, &lexstate, z, funcstate.f->sp->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/luac.c b/3rd/lua/luac.c index c565f46a..ea2f1c8f 100644 --- a/3rd/lua/luac.c +++ b/3rd/lua/luac.c @@ -149,9 +149,9 @@ static const Proto* combine(lua_State* L, int n) for (i=0; ip[i]=toproto(L,i-n-1); - if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; + if (f->p[i]->sp->sizeupvalues>0) f->p[i]->sp->upvalues[0].instack=0; } - f->sizelineinfo=0; + f->sp->sizelineinfo=0; return f; } } @@ -282,13 +282,14 @@ static void PrintConstant(const Proto* f, int i) } } -#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") +#define UPVALNAME(x) ((f->sp->upvalues[x].name) ? getstr(f->sp->upvalues[x].name) : "-") #define MYK(x) (-1-(x)) static void PrintCode(const Proto* f) { - const Instruction* code=f->code; - int pc,n=f->sizecode; + const SharedProto *sp = f->sp; + const Instruction* code=sp->code; + int pc,n=sp->sizecode; for (pc=0; pcsource ? getstr(f->source) : "=?"; if (*s=='@' || *s=='=') @@ -414,8 +415,9 @@ static void PrintHeader(const Proto* f) static void PrintDebug(const Proto* f) { + const SharedProto *sp = f->sp; int i,n; - n=f->sizek; + n=sp->sizek; printf("constants (%d) for %p:\n",n,VOID(f)); for (i=0; isizelocvars; + n=sp->sizelocvars; printf("locals (%d) for %p:\n",n,VOID(f)); for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); + i,getstr(sp->locvars[i].varname),sp->locvars[i].startpc+1,sp->locvars[i].endpc+1); } - n=f->sizeupvalues; + n=f->sp->sizeupvalues; printf("upvalues (%d) for %p:\n",n,VOID(f)); for (i=0; iupvalues[i].instack,f->upvalues[i].idx); + i,UPVALNAME(i),sp->upvalues[i].instack,sp->upvalues[i].idx); } } static void PrintFunction(const Proto* f, int full) { - int i,n=f->sizep; - PrintHeader(f); + int i,n=f->sp->sizep; + PrintHeader(f->sp); PrintCode(f); if (full) PrintDebug(f); for (i=0; ip[i],full); diff --git a/3rd/lua/lundump.c b/3rd/lua/lundump.c index 510f3258..451c9097 100644 --- a/3rd/lua/lundump.c +++ b/3rd/lua/lundump.c @@ -100,7 +100,7 @@ static TString *LoadString (LoadState *S) { } -static void LoadCode (LoadState *S, Proto *f) { +static void LoadCode (LoadState *S, SharedProto *f) { int n = LoadInt(S); f->code = luaM_newvector(S->L, n, Instruction); f->sizecode = n; @@ -115,7 +115,7 @@ static void LoadConstants (LoadState *S, Proto *f) { int i; int n = LoadInt(S); f->k = luaM_newvector(S->L, n, TValue); - f->sizek = n; + f->sp->sizek = n; for (i = 0; i < n; i++) setnilvalue(&f->k[i]); for (i = 0; i < n; i++) { @@ -149,17 +149,17 @@ static void LoadProtos (LoadState *S, Proto *f) { int i; int n = LoadInt(S); f->p = luaM_newvector(S->L, n, Proto *); - f->sizep = n; + f->sp->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); - LoadFunction(S, f->p[i], f->source); + f->p[i] = luaF_newproto(S->L, NULL); + LoadFunction(S, f->p[i], f->sp->source); } } -static void LoadUpvalues (LoadState *S, Proto *f) { +static void LoadUpvalues (LoadState *S, SharedProto *f) { int i, n; n = LoadInt(S); f->upvalues = luaM_newvector(S->L, n, Upvaldesc); @@ -173,7 +173,7 @@ static void LoadUpvalues (LoadState *S, Proto *f) { } -static void LoadDebug (LoadState *S, Proto *f) { +static void LoadDebug (LoadState *S, SharedProto *f) { int i, n; n = LoadInt(S); f->lineinfo = luaM_newvector(S->L, n, int); @@ -195,7 +195,8 @@ static void LoadDebug (LoadState *S, Proto *f) { } -static void LoadFunction (LoadState *S, Proto *f, TString *psource) { +static void LoadFunction (LoadState *S, Proto *fp, TString *psource) { + SharedProto *f = fp->sp; f->source = LoadString(S); if (f->source == NULL) /* no source in dump? */ f->source = psource; /* reuse parent's source */ @@ -205,9 +206,9 @@ static void LoadFunction (LoadState *S, Proto *f, TString *psource) { f->is_vararg = LoadByte(S); f->maxstacksize = LoadByte(S); LoadCode(S, f); - LoadConstants(S, f); + LoadConstants(S, fp); LoadUpvalues(S, f); - LoadProtos(S, f); + LoadProtos(S, fp); LoadDebug(S, f); } @@ -268,7 +269,7 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff, cl = luaF_newLclosure(L, LoadByte(&S)); setclLvalue(L, L->top, cl); incr_top(L); - cl->p = luaF_newproto(L); + cl->p = luaF_newproto(L, NULL); LoadFunction(&S, cl->p, NULL); lua_assert(cl->nupvalues == cl->p->sizeupvalues); luai_verifycode(L, buff, cl->p); diff --git a/3rd/lua/lvm.c b/3rd/lua/lvm.c index 2ac1b02d..e7348d8b 100644 --- a/3rd/lua/lvm.c +++ b/3rd/lua/lvm.c @@ -493,8 +493,8 @@ lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { static LClosure *getcached (Proto *p, UpVal **encup, StkId base) { LClosure *c = p->cache; if (c != NULL) { /* is there a cached closure? */ - int nup = p->sizeupvalues; - Upvaldesc *uv = p->upvalues; + 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; @@ -514,8 +514,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->sizeupvalues; - Upvaldesc *uv = p->upvalues; + int nup = p->sp->sizeupvalues; + Upvaldesc *uv = p->sp->upvalues; int i; LClosure *ncl = luaF_newLclosure(L, nup); ncl->p = p; @@ -1012,10 +1012,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)->numparams; + StkId lim = nci->u.l.base + getproto(nfunc)->sp->numparams; int aux; /* close all upvalues from previous call */ - if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); + if (cl->p->sp->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); @@ -1032,7 +1032,7 @@ void luaV_execute (lua_State *L) { vmcase(OP_RETURN) { int b = GETARG_B(i); if (b != 0) L->top = ra+b-1; - if (cl->p->sizep > 0) luaF_close(L, base); + if (cl->p->sp->sizep > 0) luaF_close(L, base); b = luaD_poscall(L, ra); if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ return; /* external invocation: return */ @@ -1153,7 +1153,7 @@ void luaV_execute (lua_State *L) { vmcase(OP_VARARG) { int b = GETARG_B(i) - 1; int j; - int n = cast_int(base - ci->func) - cl->p->numparams - 1; + int n = cast_int(base - ci->func) - cl->p->sp->numparams - 1; if (b < 0) { /* B == 0? */ b = n; /* get all var. arguments */ Protect(luaD_checkstack(L, n));