Skip to content

Commit 5d91421

Browse files
committed
patch lua_clonefunction
1 parent 2086e13 commit 5d91421

18 files changed

+364
-160
lines changed

3rd/lua/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
PLAT= none
88

99
CC= gcc -std=gnu99
10-
CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_2 $(SYSCFLAGS) $(MYCFLAGS)
10+
CFLAGS= -O2 -Wall -Wextra $(SYSCFLAGS) $(MYCFLAGS)
1111
LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS)
1212
LIBS= -lm $(SYSLIBS) $(MYLIBS)
1313

3rd/lua/lapi.c

+54-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "ltm.h"
2929
#include "lundump.h"
3030
#include "lvm.h"
31+
#include "lfunc.h"
3132

3233

3334

@@ -988,6 +989,58 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
988989
return status;
989990
}
990991

992+
static Proto * cloneproto (lua_State *L, const Proto *src) {
993+
/* copy constants and nested proto */
994+
int i,n;
995+
Proto *f = luaF_newproto(L, src->sp);
996+
n = src->sp->sizek;
997+
f->k=luaM_newvector(L,n,TValue);
998+
for (i=0; i<n; i++) setnilvalue(&f->k[i]);
999+
for (i=0; i<n; i++) {
1000+
const TValue *s=&src->k[i];
1001+
TValue *o=&f->k[i];
1002+
if (ttisstring(s)) {
1003+
TString * str = luaS_newlstr(L,svalue(s),vslen(s));
1004+
setsvalue2n(L,o,str);
1005+
} else {
1006+
setobj(L,o,s);
1007+
}
1008+
}
1009+
n = src->sp->sizep;
1010+
f->p=luaM_newvector(L,n,struct Proto *);
1011+
for (i=0; i<n; i++) f->p[i]=NULL;
1012+
for (i=0; i<n; i++) {
1013+
f->p[i]=cloneproto(L, src->p[i]);
1014+
}
1015+
return f;
1016+
}
1017+
1018+
LUA_API void lua_clonefunction (lua_State *L, const void * fp) {
1019+
LClosure *cl;
1020+
LClosure *f = cast(LClosure *, fp);
1021+
lua_lock(L);
1022+
if (f->p->sp->l_G == G(L)) {
1023+
setclLvalue(L,L->top,f);
1024+
api_incr_top(L);
1025+
lua_unlock(L);
1026+
return;
1027+
}
1028+
cl = luaF_newLclosure(L,f->nupvalues);
1029+
cl->p = cloneproto(L, f->p);
1030+
setclLvalue(L,L->top,cl);
1031+
api_incr_top(L);
1032+
luaF_initupvals(L, cl);
1033+
1034+
if (cl->nupvalues >= 1) { /* does it have an upvalue? */
1035+
/* get global table from registry */
1036+
Table *reg = hvalue(&G(L)->l_registry);
1037+
const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
1038+
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
1039+
setobj(L, cl->upvals[0]->v, gt);
1040+
luaC_upvalbarrier(L, cl->upvals[0]);
1041+
}
1042+
lua_unlock(L);
1043+
}
9911044

9921045
LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) {
9931046
int status;
@@ -1183,7 +1236,7 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val,
11831236
case LUA_TLCL: { /* Lua closure */
11841237
LClosure *f = clLvalue(fi);
11851238
TString *name;
1186-
Proto *p = f->p;
1239+
SharedProto *p = f->p->sp;
11871240
if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
11881241
*val = f->upvals[n-1]->v;
11891242
if (uv) *uv = f->upvals[n - 1];

3rd/lua/lauxlib.c

+121-1
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ static int skipcomment (LoadF *lf, int *cp) {
638638
}
639639

640640

641-
LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
641+
static int luaL_loadfilex_ (lua_State *L, const char *filename,
642642
const char *mode) {
643643
LoadF lf;
644644
int status, readstatus;
@@ -970,3 +970,123 @@ LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
970970
ver, *v);
971971
}
972972

973+
// use clonefunction
974+
975+
#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
976+
#define UNLOCK(q) __sync_lock_release(&(q)->lock);
977+
978+
struct codecache {
979+
int lock;
980+
lua_State *L;
981+
};
982+
983+
static struct codecache CC = { 0 , NULL };
984+
985+
static void
986+
clearcache() {
987+
if (CC.L == NULL)
988+
return;
989+
LOCK(&CC)
990+
lua_close(CC.L);
991+
CC.L = luaL_newstate();
992+
UNLOCK(&CC)
993+
}
994+
995+
static void
996+
init() {
997+
CC.lock = 0;
998+
CC.L = luaL_newstate();
999+
}
1000+
1001+
static const void *
1002+
load(const char *key) {
1003+
if (CC.L == NULL)
1004+
return NULL;
1005+
LOCK(&CC)
1006+
lua_State *L = CC.L;
1007+
lua_pushstring(L, key);
1008+
lua_rawget(L, LUA_REGISTRYINDEX);
1009+
const void * result = lua_touserdata(L, -1);
1010+
lua_pop(L, 1);
1011+
UNLOCK(&CC)
1012+
1013+
return result;
1014+
}
1015+
1016+
static const void *
1017+
save(const char *key, const void * proto) {
1018+
lua_State *L;
1019+
const void * result = NULL;
1020+
1021+
LOCK(&CC)
1022+
if (CC.L == NULL) {
1023+
init();
1024+
L = CC.L;
1025+
} else {
1026+
L = CC.L;
1027+
lua_pushstring(L, key);
1028+
lua_pushvalue(L, -1);
1029+
lua_rawget(L, LUA_REGISTRYINDEX);
1030+
result = lua_touserdata(L, -1); /* stack: key oldvalue */
1031+
if (result == NULL) {
1032+
lua_pop(L,1);
1033+
lua_pushlightuserdata(L, (void *)proto);
1034+
lua_rawset(L, LUA_REGISTRYINDEX);
1035+
} else {
1036+
lua_pop(L,2);
1037+
}
1038+
}
1039+
UNLOCK(&CC)
1040+
return result;
1041+
}
1042+
1043+
LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
1044+
const char *mode) {
1045+
const void * proto = load(filename);
1046+
if (proto) {
1047+
lua_clonefunction(L, proto);
1048+
return LUA_OK;
1049+
}
1050+
lua_State * eL = luaL_newstate();
1051+
if (eL == NULL) {
1052+
lua_pushliteral(L, "New state failed");
1053+
return LUA_ERRMEM;
1054+
}
1055+
int err = luaL_loadfilex_(eL, filename, mode);
1056+
if (err != LUA_OK) {
1057+
size_t sz = 0;
1058+
const char * msg = lua_tolstring(eL, -1, &sz);
1059+
lua_pushlstring(L, msg, sz);
1060+
lua_close(eL);
1061+
return err;
1062+
}
1063+
proto = lua_topointer(eL, -1);
1064+
const void * oldv = save(filename, proto);
1065+
if (oldv) {
1066+
lua_close(eL);
1067+
lua_clonefunction(L, oldv);
1068+
} else {
1069+
lua_clonefunction(L, proto);
1070+
/* Never close it. notice: memory leak */
1071+
}
1072+
1073+
return LUA_OK;
1074+
}
1075+
1076+
static int
1077+
cache_clear(lua_State *L) {
1078+
(void)(L);
1079+
clearcache();
1080+
return 0;
1081+
}
1082+
1083+
LUAMOD_API int luaopen_cache(lua_State *L) {
1084+
luaL_Reg l[] = {
1085+
{ "clear", cache_clear },
1086+
{ NULL, NULL },
1087+
};
1088+
luaL_newlib(L,l);
1089+
lua_getglobal(L, "loadfile");
1090+
lua_setfield(L, -2, "loadfile");
1091+
return 1;
1092+
}

3rd/lua/lcode.c

+18-18
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ void luaK_nil (FuncState *fs, int from, int n) {
5555
Instruction *previous;
5656
int l = from + n - 1; /* last register to set nil */
5757
if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
58-
previous = &fs->f->code[fs->pc-1];
58+
previous = &fs->f->sp->code[fs->pc-1];
5959
if (GET_OPCODE(*previous) == OP_LOADNIL) {
6060
int pfrom = GETARG_A(*previous);
6161
int pl = pfrom + GETARG_B(*previous);
@@ -95,7 +95,7 @@ static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
9595

9696

9797
static void fixjump (FuncState *fs, int pc, int dest) {
98-
Instruction *jmp = &fs->f->code[pc];
98+
Instruction *jmp = &fs->f->sp->code[pc];
9999
int offset = dest-(pc+1);
100100
lua_assert(dest != NO_JUMP);
101101
if (abs(offset) > MAXARG_sBx)
@@ -115,7 +115,7 @@ int luaK_getlabel (FuncState *fs) {
115115

116116

117117
static int getjump (FuncState *fs, int pc) {
118-
int offset = GETARG_sBx(fs->f->code[pc]);
118+
int offset = GETARG_sBx(fs->f->sp->code[pc]);
119119
if (offset == NO_JUMP) /* point to itself represents end of list */
120120
return NO_JUMP; /* end of list */
121121
else
@@ -124,7 +124,7 @@ static int getjump (FuncState *fs, int pc) {
124124

125125

126126
static Instruction *getjumpcontrol (FuncState *fs, int pc) {
127-
Instruction *pi = &fs->f->code[pc];
127+
Instruction *pi = &fs->f->sp->code[pc];
128128
if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
129129
return pi-1;
130130
else
@@ -197,10 +197,10 @@ void luaK_patchclose (FuncState *fs, int list, int level) {
197197
level++; /* argument is +1 to reserve 0 as non-op */
198198
while (list != NO_JUMP) {
199199
int next = getjump(fs, list);
200-
lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP &&
201-
(GETARG_A(fs->f->code[list]) == 0 ||
202-
GETARG_A(fs->f->code[list]) >= level));
203-
SETARG_A(fs->f->code[list], level);
200+
lua_assert(GET_OPCODE(fs->f->sp->code[list]) == OP_JMP &&
201+
(GETARG_A(fs->f->sp->code[list]) == 0 ||
202+
GETARG_A(fs->f->sp->code[list]) >= level));
203+
SETARG_A(fs->f->sp->code[list], level);
204204
list = next;
205205
}
206206
}
@@ -230,13 +230,13 @@ static int luaK_code (FuncState *fs, Instruction i) {
230230
Proto *f = fs->f;
231231
dischargejpc(fs); /* 'pc' will change */
232232
/* put new instruction in code array */
233-
luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction,
233+
luaM_growvector(fs->ls->L, f->sp->code, fs->pc, f->sp->sizecode, Instruction,
234234
MAX_INT, "opcodes");
235-
f->code[fs->pc] = i;
235+
f->sp->code[fs->pc] = i;
236236
/* save corresponding line information */
237-
luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
237+
luaM_growvector(fs->ls->L, f->sp->lineinfo, fs->pc, f->sp->sizelineinfo, int,
238238
MAX_INT, "opcodes");
239-
f->lineinfo[fs->pc] = fs->ls->lastline;
239+
f->sp->lineinfo[fs->pc] = fs->ls->lastline;
240240
return fs->pc++;
241241
}
242242

@@ -277,11 +277,11 @@ int luaK_codek (FuncState *fs, int reg, int k) {
277277

278278
void luaK_checkstack (FuncState *fs, int n) {
279279
int newstack = fs->freereg + n;
280-
if (newstack > fs->f->maxstacksize) {
280+
if (newstack > fs->f->sp->maxstacksize) {
281281
if (newstack >= MAXREGS)
282282
luaX_syntaxerror(fs->ls,
283283
"function or expression needs too many registers");
284-
fs->f->maxstacksize = cast_byte(newstack);
284+
fs->f->sp->maxstacksize = cast_byte(newstack);
285285
}
286286
}
287287

@@ -323,13 +323,13 @@ static int addk (FuncState *fs, TValue *key, TValue *v) {
323323
return k; /* reuse index */
324324
}
325325
/* constant not found; create a new entry */
326-
oldsize = f->sizek;
326+
oldsize = f->sp->sizek;
327327
k = fs->nk;
328328
/* numerical value does not need GC barrier;
329329
table has no metatable, so it does not need to invalidate cache */
330330
setivalue(idx, k);
331-
luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants");
332-
while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
331+
luaM_growvector(L, f->k, k, f->sp->sizek, TValue, MAXARG_Ax, "constants");
332+
while (oldsize < f->sp->sizek) setnilvalue(&f->k[oldsize++]);
333333
setobj(L, &f->k[k], v);
334334
fs->nk++;
335335
luaC_barrier(L, f, v);
@@ -934,7 +934,7 @@ void luaK_posfix (FuncState *fs, BinOpr op,
934934

935935

936936
void luaK_fixline (FuncState *fs, int line) {
937-
fs->f->lineinfo[fs->pc - 1] = line;
937+
fs->f->sp->lineinfo[fs->pc - 1] = line;
938938
}
939939

940940

3rd/lua/lcode.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ typedef enum BinOpr {
4040
typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
4141

4242

43-
#define getcode(fs,e) ((fs)->f->code[(e)->u.info])
43+
#define getcode(fs,e) ((fs)->f->sp->code[(e)->u.info])
4444

4545
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
4646

0 commit comments

Comments
 (0)