Skip to content

Commit

Permalink
rewrite clonefunction
Browse files Browse the repository at this point in the history
  • Loading branch information
cloudwu committed Apr 16, 2020
1 parent 4405736 commit 0c11dc1
Show file tree
Hide file tree
Showing 27 changed files with 306 additions and 797 deletions.
85 changes: 34 additions & 51 deletions src/lapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,8 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
}
switch (ttnov(obj)) {
case LUA_TTABLE: {
if (isshared(hvalue(obj)))
luaG_runerror(L, "can't setmetatable to shared table");
hvalue(obj)->metatable = mt;
if (mt) {
luaC_objbarrier(L, gcvalue(obj), mt);
Expand Down Expand Up @@ -1013,62 +1015,15 @@ 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; i<n; i++) setnilvalue(&f->k[i]);
for (i=0; i<n; i++) {
const TValue *s=&src->k[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; i<n; i++) f->p[i]=NULL;
for (i=0; i<n; i++) {
f->p[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);
api_check(L, isshared(f->p), "Not a shared proto");
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);
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? */
Expand All @@ -1082,6 +1037,34 @@ 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))
luaG_runerror(L, "Only Lua function can share");
LClosure *f = cast(LClosure *, lua_topointer(L, index));
luaF_shareproto(f->p);
}

LUA_API void lua_sharestring (lua_State *L, int index) {
const char *str = lua_tostring(L, index);
if (str == NULL)
luaG_runerror(L, "need a string to share");

TString *ts = (TString *)(str - sizeof(UTString));
luaS_share(ts);
}

LUA_API void lua_clonetable(lua_State *L, const void * tp) {
Table *t = cast(Table *, tp);

if (!isshared(t))
luaG_runerror(L, "Not a shared table");

lua_lock(L);
sethvalue(L, L->top, t);
api_incr_top(L);
lua_unlock(L);
}

LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) {
int status;
TValue *o;
Expand Down Expand Up @@ -1276,7 +1259,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];
Expand Down Expand Up @@ -1328,7 +1311,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 */
}
Expand Down
15 changes: 8 additions & 7 deletions src/lauxlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -1067,10 +1063,14 @@ clearcache() {

static void
init() {
SPIN_INIT(&CC);
CC.L = luaL_newstate();
}

LUALIB_API void
luaL_initcodecache(void) {
SPIN_INIT(&CC);
}

static const void *
load(const char *key) {
if (CC.L == NULL)
Expand Down Expand Up @@ -1107,7 +1107,7 @@ save(const char *key, const void * proto) {
} else {
lua_pop(L,2);
}

SPIN_UNLOCK(&CC)
return result;
}
Expand Down Expand Up @@ -1181,6 +1181,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) {
Expand Down
2 changes: 2 additions & 0 deletions src/lauxlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
36 changes: 18 additions & 18 deletions src/lcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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++;
}

Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}


Expand Down
2 changes: 1 addition & 1 deletion src/lcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Loading

0 comments on commit 0c11dc1

Please sign in to comment.