mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-22 02:53:09 +00:00
update lua
This commit is contained in:
@@ -114,13 +114,8 @@ LUA_API int lua_checkstack (lua_State *L, int n) {
|
||||
api_check(L, n >= 0, "negative 'n'");
|
||||
if (L->stack_last - L->top > n) /* stack large enough? */
|
||||
res = 1; /* yes; check is OK */
|
||||
else { /* no; need to grow stack */
|
||||
int inuse = cast_int(L->top - L->stack) + EXTRA_STACK;
|
||||
if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */
|
||||
res = 0; /* no */
|
||||
else /* try to grow stack */
|
||||
res = luaD_growstack(L, n, 0);
|
||||
}
|
||||
else /* need to grow stack */
|
||||
res = luaD_growstack(L, n, 0);
|
||||
if (res && ci->top < L->top + n)
|
||||
ci->top = L->top + n; /* adjust frame top */
|
||||
lua_unlock(L);
|
||||
@@ -202,7 +197,7 @@ LUA_API void lua_settop (lua_State *L, int idx) {
|
||||
newtop = L->top + diff;
|
||||
if (diff < 0 && L->tbclist >= newtop) {
|
||||
lua_assert(hastocloseCfunc(ci->nresults));
|
||||
luaF_close(L, newtop, CLOSEKTOP, 0);
|
||||
newtop = luaF_close(L, newtop, CLOSEKTOP, 0);
|
||||
}
|
||||
L->top = newtop; /* correct top only after closing any upvalue */
|
||||
lua_unlock(L);
|
||||
@@ -215,8 +210,7 @@ LUA_API void lua_closeslot (lua_State *L, int idx) {
|
||||
level = index2stack(L, idx);
|
||||
api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist == level,
|
||||
"no variable to close at given level");
|
||||
luaF_close(L, level, CLOSEKTOP, 0);
|
||||
level = index2stack(L, idx); /* stack may be moved */
|
||||
level = luaF_close(L, level, CLOSEKTOP, 0);
|
||||
setnilvalue(s2v(level));
|
||||
lua_unlock(L);
|
||||
}
|
||||
@@ -1129,16 +1123,18 @@ LUA_API void lua_clonefunction (lua_State *L, const void * fp) {
|
||||
}
|
||||
|
||||
LUA_API void lua_sharefunction (lua_State *L, int index) {
|
||||
LClosure *f;
|
||||
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));
|
||||
f = cast(LClosure *, lua_topointer(L, index));
|
||||
luaF_shareproto(f->p);
|
||||
}
|
||||
|
||||
LUA_API void lua_sharestring (lua_State *L, int index) {
|
||||
TString *ts;
|
||||
if (lua_type(L,index) != LUA_TSTRING)
|
||||
luaG_runerror(L, "need a string to share");
|
||||
TString *ts = tsvalue(index2value(L,index));
|
||||
ts = tsvalue(index2value(L,index));
|
||||
luaS_share(ts);
|
||||
}
|
||||
|
||||
|
||||
@@ -526,7 +526,8 @@ static void newbox (lua_State *L) {
|
||||
|
||||
/*
|
||||
** Compute new size for buffer 'B', enough to accommodate extra 'sz'
|
||||
** bytes.
|
||||
** bytes. (The test for "double is not big enough" also gets the
|
||||
** case when the multiplication by 2 overflows.)
|
||||
*/
|
||||
static size_t newbuffsize (luaL_Buffer *B, size_t sz) {
|
||||
size_t newsize = B->size * 2; /* double buffer size */
|
||||
@@ -611,7 +612,7 @@ LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) {
|
||||
** box (if existent) is not on the top of the stack. So, instead of
|
||||
** calling 'luaL_addlstring', it replicates the code using -2 as the
|
||||
** last argument to 'prepbuffsize', signaling that the box is (or will
|
||||
** be) bellow the string being added to the buffer. (Box creation can
|
||||
** be) below the string being added to the buffer. (Box creation can
|
||||
** trigger an emergency GC, so we should not remove the string from the
|
||||
** stack before we have the space guaranteed.)
|
||||
*/
|
||||
@@ -739,17 +740,18 @@ static int errfile (lua_State *L, const char *what, int fnameindex) {
|
||||
}
|
||||
|
||||
|
||||
static int skipBOM (LoadF *lf) {
|
||||
const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */
|
||||
int c;
|
||||
lf->n = 0;
|
||||
do {
|
||||
c = getc(lf->f);
|
||||
if (c == EOF || c != *(const unsigned char *)p++) return c;
|
||||
lf->buff[lf->n++] = c; /* to be read by the parser */
|
||||
} while (*p != '\0');
|
||||
lf->n = 0; /* prefix matched; discard it */
|
||||
return getc(lf->f); /* return next character */
|
||||
/*
|
||||
** Skip an optional BOM at the start of a stream. If there is an
|
||||
** incomplete BOM (the first character is correct but the rest is
|
||||
** not), returns the first character anyway to force an error
|
||||
** (as no chunk can start with 0xEF).
|
||||
*/
|
||||
static int skipBOM (FILE *f) {
|
||||
int c = getc(f); /* read first character */
|
||||
if (c == 0xEF && getc(f) == 0xBB && getc(f) == 0xBF) /* correct BOM? */
|
||||
return getc(f); /* ignore BOM and return next char */
|
||||
else /* no (valid) BOM */
|
||||
return c; /* return first character */
|
||||
}
|
||||
|
||||
|
||||
@@ -760,13 +762,13 @@ static int skipBOM (LoadF *lf) {
|
||||
** first "valid" character of the file (after the optional BOM and
|
||||
** a first-line comment).
|
||||
*/
|
||||
static int skipcomment (LoadF *lf, int *cp) {
|
||||
int c = *cp = skipBOM(lf);
|
||||
static int skipcomment (FILE *f, int *cp) {
|
||||
int c = *cp = skipBOM(f);
|
||||
if (c == '#') { /* first line is a comment (Unix exec. file)? */
|
||||
do { /* skip first line */
|
||||
c = getc(lf->f);
|
||||
c = getc(f);
|
||||
} while (c != EOF && c != '\n');
|
||||
*cp = getc(lf->f); /* skip end-of-line, if present */
|
||||
*cp = getc(f); /* next character after comment, if present */
|
||||
return 1; /* there was a comment */
|
||||
}
|
||||
else return 0; /* no comment */
|
||||
@@ -788,12 +790,16 @@ LUALIB_API int luaL_loadfilex_ (lua_State *L, const char *filename,
|
||||
lf.f = fopen(filename, "r");
|
||||
if (lf.f == NULL) return errfile(L, "open", fnameindex);
|
||||
}
|
||||
if (skipcomment(&lf, &c)) /* read initial portion */
|
||||
lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */
|
||||
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
|
||||
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
|
||||
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
|
||||
skipcomment(&lf, &c); /* re-read initial portion */
|
||||
lf.n = 0;
|
||||
if (skipcomment(lf.f, &c)) /* read initial portion */
|
||||
lf.buff[lf.n++] = '\n'; /* add newline to correct line numbers */
|
||||
if (c == LUA_SIGNATURE[0]) { /* binary file? */
|
||||
lf.n = 0; /* remove possible newline */
|
||||
if (filename) { /* "real" file? */
|
||||
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
|
||||
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
|
||||
skipcomment(lf.f, &c); /* re-read initial portion */
|
||||
}
|
||||
}
|
||||
if (c != EOF)
|
||||
lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */
|
||||
@@ -1116,7 +1122,7 @@ struct codecache {
|
||||
static struct codecache CC;
|
||||
|
||||
static void
|
||||
clearcache() {
|
||||
clearcache(void) {
|
||||
if (CC.L == NULL)
|
||||
return;
|
||||
SPIN_LOCK(&CC)
|
||||
@@ -1126,10 +1132,13 @@ clearcache() {
|
||||
}
|
||||
|
||||
static void
|
||||
init() {
|
||||
init(void) {
|
||||
CC.L = luaL_newstate();
|
||||
}
|
||||
|
||||
|
||||
void luaL_initcodecache(void);
|
||||
|
||||
LUALIB_API void
|
||||
luaL_initcodecache(void) {
|
||||
SPIN_INIT(&CC);
|
||||
@@ -1137,13 +1146,15 @@ luaL_initcodecache(void) {
|
||||
|
||||
static const void *
|
||||
load_proto(const char *key) {
|
||||
lua_State *L;
|
||||
const void * result;
|
||||
if (CC.L == NULL)
|
||||
return NULL;
|
||||
SPIN_LOCK(&CC)
|
||||
lua_State *L = CC.L;
|
||||
L = CC.L;
|
||||
lua_pushstring(L, key);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
const void * result = lua_touserdata(L, -1);
|
||||
result = lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
SPIN_UNLOCK(&CC)
|
||||
|
||||
@@ -1199,9 +1210,10 @@ static int cache_mode(lua_State *L) {
|
||||
"ON",
|
||||
NULL,
|
||||
};
|
||||
int t,r;
|
||||
if (lua_isnoneornil(L,1)) {
|
||||
int t = lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key);
|
||||
int r = lua_tointeger(L, -1);
|
||||
t = lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key);
|
||||
r = lua_tointeger(L, -1);
|
||||
if (t == LUA_TNUMBER) {
|
||||
if (r < 0 || r >= CACHE_ON) {
|
||||
r = CACHE_ON;
|
||||
@@ -1212,7 +1224,7 @@ static int cache_mode(lua_State *L) {
|
||||
lua_pushstring(L, lst[r]);
|
||||
return 1;
|
||||
}
|
||||
int t = luaL_checkoption(L, 1, "OFF" , lst);
|
||||
t = luaL_checkoption(L, 1, "OFF" , lst);
|
||||
lua_pushinteger(L, t);
|
||||
lua_rawsetp(L, LUA_REGISTRYINDEX, &cache_key);
|
||||
return 0;
|
||||
@@ -1221,10 +1233,14 @@ static int cache_mode(lua_State *L) {
|
||||
LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
|
||||
const char *mode) {
|
||||
int level = cache_level(L);
|
||||
if (level == CACHE_OFF || filename == NULL) {
|
||||
const void * proto;
|
||||
lua_State * eL;
|
||||
int err;
|
||||
const void * oldv;
|
||||
if (level == CACHE_OFF) {
|
||||
return luaL_loadfilex_(L, filename, mode);
|
||||
}
|
||||
const void * proto = load_proto(filename);
|
||||
proto = load_proto(filename);
|
||||
if (proto) {
|
||||
lua_clonefunction(L, proto);
|
||||
return LUA_OK;
|
||||
@@ -1232,12 +1248,12 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
|
||||
if (level == CACHE_EXIST) {
|
||||
return luaL_loadfilex_(L, filename, mode);
|
||||
}
|
||||
lua_State * eL = luaL_newstate();
|
||||
eL = luaL_newstate();
|
||||
if (eL == NULL) {
|
||||
lua_pushliteral(L, "New state failed");
|
||||
return LUA_ERRMEM;
|
||||
}
|
||||
int err = luaL_loadfilex_(eL, filename, mode);
|
||||
err = luaL_loadfilex_(eL, filename, mode);
|
||||
if (err != LUA_OK) {
|
||||
size_t sz = 0;
|
||||
const char * msg = lua_tolstring(eL, -1, &sz);
|
||||
@@ -1247,7 +1263,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
|
||||
}
|
||||
lua_sharefunction(eL, -1);
|
||||
proto = lua_topointer(eL, -1);
|
||||
const void * oldv = save_proto(filename, proto);
|
||||
oldv = save_proto(filename, proto);
|
||||
if (oldv) {
|
||||
lua_close(eL);
|
||||
lua_clonefunction(L, oldv);
|
||||
@@ -1266,6 +1282,8 @@ cache_clear(lua_State *L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int luaopen_cache(lua_State *L);
|
||||
|
||||
LUAMOD_API int luaopen_cache(lua_State *L) {
|
||||
luaL_Reg l[] = {
|
||||
{ "clear", cache_clear },
|
||||
|
||||
@@ -1391,7 +1391,10 @@ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2,
|
||||
*/
|
||||
static void codebinexpval (FuncState *fs, OpCode op,
|
||||
expdesc *e1, expdesc *e2, int line) {
|
||||
int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */
|
||||
int v2 = luaK_exp2anyreg(fs, e2); /* make sure 'e2' is in a register */
|
||||
/* 'e1' must be already in a register or it is a constant */
|
||||
lua_assert((VNIL <= e1->k && e1->k <= VKSTR) ||
|
||||
e1->k == VNONRELOC || e1->k == VRELOC);
|
||||
lua_assert(OP_ADD <= op && op <= OP_SHR);
|
||||
finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN,
|
||||
cast(TMS, (op - OP_ADD) + TM_ADD));
|
||||
@@ -1410,6 +1413,18 @@ static void codebini (FuncState *fs, OpCode op,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Code binary operators with K operand.
|
||||
*/
|
||||
static void codebinK (FuncState *fs, BinOpr opr,
|
||||
expdesc *e1, expdesc *e2, int flip, int line) {
|
||||
TMS event = cast(TMS, opr + TM_ADD);
|
||||
int v2 = e2->u.info; /* K index */
|
||||
OpCode op = cast(OpCode, opr + OP_ADDK);
|
||||
finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event);
|
||||
}
|
||||
|
||||
|
||||
/* Try to code a binary operator negating its second operand.
|
||||
** For the metamethod, 2nd operand must keep its original value.
|
||||
*/
|
||||
@@ -1437,24 +1452,28 @@ static void swapexps (expdesc *e1, expdesc *e2) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Code binary operators with no constant operand.
|
||||
*/
|
||||
static void codebinNoK (FuncState *fs, BinOpr opr,
|
||||
expdesc *e1, expdesc *e2, int flip, int line) {
|
||||
OpCode op = cast(OpCode, opr + OP_ADD);
|
||||
if (flip)
|
||||
swapexps(e1, e2); /* back to original order */
|
||||
codebinexpval(fs, op, e1, e2, line); /* use standard operators */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Code arithmetic operators ('+', '-', ...). If second operand is a
|
||||
** constant in the proper range, use variant opcodes with K operands.
|
||||
*/
|
||||
static void codearith (FuncState *fs, BinOpr opr,
|
||||
expdesc *e1, expdesc *e2, int flip, int line) {
|
||||
TMS event = cast(TMS, opr + TM_ADD);
|
||||
if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */
|
||||
int v2 = e2->u.info; /* K index */
|
||||
OpCode op = cast(OpCode, opr + OP_ADDK);
|
||||
finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event);
|
||||
}
|
||||
else { /* 'e2' is neither an immediate nor a K operand */
|
||||
OpCode op = cast(OpCode, opr + OP_ADD);
|
||||
if (flip)
|
||||
swapexps(e1, e2); /* back to original order */
|
||||
codebinexpval(fs, op, e1, e2, line); /* use standard operators */
|
||||
}
|
||||
if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) /* K operand? */
|
||||
codebinK(fs, opr, e1, e2, flip, line);
|
||||
else /* 'e2' is neither an immediate nor a K operand */
|
||||
codebinNoK(fs, opr, e1, e2, flip, line);
|
||||
}
|
||||
|
||||
|
||||
@@ -1478,28 +1497,20 @@ static void codecommutative (FuncState *fs, BinOpr op,
|
||||
|
||||
|
||||
/*
|
||||
** Code bitwise operations; they are all associative, so the function
|
||||
** Code bitwise operations; they are all commutative, so the function
|
||||
** tries to put an integer constant as the 2nd operand (a K operand).
|
||||
*/
|
||||
static void codebitwise (FuncState *fs, BinOpr opr,
|
||||
expdesc *e1, expdesc *e2, int line) {
|
||||
int flip = 0;
|
||||
int v2;
|
||||
OpCode op;
|
||||
if (e1->k == VKINT && luaK_exp2RK(fs, e1)) {
|
||||
if (e1->k == VKINT) {
|
||||
swapexps(e1, e2); /* 'e2' will be the constant operand */
|
||||
flip = 1;
|
||||
}
|
||||
else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */
|
||||
op = cast(OpCode, opr + OP_ADD);
|
||||
codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */
|
||||
return;
|
||||
}
|
||||
v2 = e2->u.info; /* index in K array */
|
||||
op = cast(OpCode, opr + OP_ADDK);
|
||||
lua_assert(ttisinteger(&fs->f->k[v2]));
|
||||
finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK,
|
||||
cast(TMS, opr + TM_ADD));
|
||||
if (e2->k == VKINT && luaK_exp2K(fs, e2)) /* K operand? */
|
||||
codebinK(fs, opr, e1, e2, flip, line);
|
||||
else /* no constants */
|
||||
codebinNoK(fs, opr, e1, e2, flip, line);
|
||||
}
|
||||
|
||||
|
||||
@@ -1551,7 +1562,7 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
|
||||
op = OP_EQI;
|
||||
r2 = im; /* immediate operand */
|
||||
}
|
||||
else if (luaK_exp2RK(fs, e2)) { /* 1st expression is constant? */
|
||||
else if (luaK_exp2RK(fs, e2)) { /* 2nd expression is constant? */
|
||||
op = OP_EQK;
|
||||
r2 = e2->u.info; /* constant index */
|
||||
}
|
||||
@@ -1611,7 +1622,8 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
|
||||
case OPR_SHL: case OPR_SHR: {
|
||||
if (!tonumeral(v, NULL))
|
||||
luaK_exp2anyreg(fs, v);
|
||||
/* else keep numeral, which may be folded with 2nd operand */
|
||||
/* else keep numeral, which may be folded or used as an immediate
|
||||
operand */
|
||||
break;
|
||||
}
|
||||
case OPR_EQ: case OPR_NE: {
|
||||
|
||||
@@ -824,8 +824,11 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
|
||||
va_start(argp, fmt);
|
||||
msg = luaO_pushvfstring(L, fmt, argp); /* format message */
|
||||
va_end(argp);
|
||||
if (isLua(ci)) /* if Lua function, add source:line information */
|
||||
if (isLua(ci)) { /* if Lua function, add source:line information */
|
||||
luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci));
|
||||
setobjs2s(L, L->top - 2, L->top - 1); /* remove 'msg' from the stack */
|
||||
L->top--;
|
||||
}
|
||||
luaG_errormsg(L);
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
|
||||
|
||||
|
||||
/*
|
||||
** Try to grow the stack by at least 'n' elements. when 'raiseerror'
|
||||
** Try to grow the stack by at least 'n' elements. When 'raiseerror'
|
||||
** is true, raises any error; otherwise, return 0 in case of errors.
|
||||
*/
|
||||
int luaD_growstack (lua_State *L, int n, int raiseerror) {
|
||||
@@ -227,7 +227,7 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) {
|
||||
luaD_throw(L, LUA_ERRERR); /* error inside message handler */
|
||||
return 0; /* if not 'raiseerror', just signal it */
|
||||
}
|
||||
else {
|
||||
else if (n < LUAI_MAXSTACK) { /* avoids arithmetic overflows */
|
||||
int newsize = 2 * size; /* tentative new size */
|
||||
int needed = cast_int(L->top - L->stack) + n;
|
||||
if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */
|
||||
@@ -236,17 +236,20 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) {
|
||||
newsize = needed;
|
||||
if (l_likely(newsize <= LUAI_MAXSTACK))
|
||||
return luaD_reallocstack(L, newsize, raiseerror);
|
||||
else { /* stack overflow */
|
||||
/* add extra size to be able to handle the error message */
|
||||
luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror);
|
||||
if (raiseerror)
|
||||
luaG_runerror(L, "stack overflow");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* else stack overflow */
|
||||
/* add extra size to be able to handle the error message */
|
||||
luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror);
|
||||
if (raiseerror)
|
||||
luaG_runerror(L, "stack overflow");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Compute how much of the stack is being used, by computing the
|
||||
** maximum top of all call frames in the stack and the current top.
|
||||
*/
|
||||
static int stackinuse (lua_State *L) {
|
||||
CallInfo *ci;
|
||||
int res;
|
||||
@@ -254,7 +257,7 @@ static int stackinuse (lua_State *L) {
|
||||
for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
||||
if (lim < ci->top) lim = ci->top;
|
||||
}
|
||||
lua_assert(lim <= L->stack_last);
|
||||
lua_assert(lim <= L->stack_last + EXTRA_STACK);
|
||||
res = cast_int(lim - L->stack) + 1; /* part of stack in use */
|
||||
if (res < LUA_MINSTACK)
|
||||
res = LUA_MINSTACK; /* ensure a minimum size */
|
||||
@@ -427,14 +430,15 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) {
|
||||
break;
|
||||
default: /* two/more results and/or to-be-closed variables */
|
||||
if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */
|
||||
ptrdiff_t savedres = savestack(L, res);
|
||||
L->ci->callstatus |= CIST_CLSRET; /* in case of yields */
|
||||
L->ci->u2.nres = nres;
|
||||
luaF_close(L, res, CLOSEKTOP, 1);
|
||||
res = luaF_close(L, res, CLOSEKTOP, 1);
|
||||
L->ci->callstatus &= ~CIST_CLSRET;
|
||||
if (L->hookmask) /* if needed, call hook after '__close's */
|
||||
if (L->hookmask) { /* if needed, call hook after '__close's */
|
||||
ptrdiff_t savedres = savestack(L, res);
|
||||
rethook(L, L->ci, nres);
|
||||
res = restorestack(L, savedres); /* close and hook can move stack */
|
||||
res = restorestack(L, savedres); /* hook can move stack */
|
||||
}
|
||||
wanted = decodeNresults(wanted);
|
||||
if (wanted == LUA_MULTRET)
|
||||
wanted = nres; /* we want all results */
|
||||
@@ -598,12 +602,17 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||
** Call a function (C or Lua) through C. 'inc' can be 1 (increment
|
||||
** number of recursive invocations in the C stack) or nyci (the same
|
||||
** plus increment number of non-yieldable calls).
|
||||
** This function can be called with some use of EXTRA_STACK, so it should
|
||||
** check the stack before doing anything else. 'luaD_precall' already
|
||||
** does that.
|
||||
*/
|
||||
l_sinline void ccall (lua_State *L, StkId func, int nResults, int inc) {
|
||||
CallInfo *ci;
|
||||
L->nCcalls += inc;
|
||||
if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
|
||||
if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) {
|
||||
checkstackp(L, 0, func); /* free any use of EXTRA_STACK */
|
||||
luaE_checkcstack(L);
|
||||
}
|
||||
if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */
|
||||
ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */
|
||||
luaV_execute(L, ci); /* call it */
|
||||
@@ -651,8 +660,7 @@ static int finishpcallk (lua_State *L, CallInfo *ci) {
|
||||
else { /* error */
|
||||
StkId func = restorestack(L, ci->u2.funcidx);
|
||||
L->allowhook = getoah(ci->callstatus); /* restore 'allowhook' */
|
||||
luaF_close(L, func, status, 1); /* can yield or raise an error */
|
||||
func = restorestack(L, ci->u2.funcidx); /* stack may be moved */
|
||||
func = luaF_close(L, func, status, 1); /* can yield or raise an error */
|
||||
luaD_seterrorobj(L, status, func);
|
||||
luaD_shrinkstack(L); /* restore stack size in case of overflow */
|
||||
setcistrecst(ci, LUA_OK); /* clear original status */
|
||||
|
||||
@@ -37,6 +37,13 @@
|
||||
|
||||
|
||||
/* macro to check stack size, preserving 'p' */
|
||||
#define checkstackp(L,n,p) \
|
||||
luaD_checkstackaux(L, n, \
|
||||
ptrdiff_t t__ = savestack(L, p), /* save 'p' */ \
|
||||
p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
|
||||
|
||||
|
||||
/* macro to check stack size and GC, preserving 'p' */
|
||||
#define checkstackGCp(L,n,p) \
|
||||
luaD_checkstackaux(L, n, \
|
||||
ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \
|
||||
@@ -58,7 +65,8 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
|
||||
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,
|
||||
int fTransfer, int nTransfer);
|
||||
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
|
||||
LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1, int delta);
|
||||
LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
|
||||
int narg1, int delta);
|
||||
LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
|
||||
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
||||
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
|
||||
|
||||
@@ -210,7 +210,7 @@ void luaF_closeupval (lua_State *L, StkId level) {
|
||||
|
||||
|
||||
/*
|
||||
** Remove firt element from the tbclist plus its dummy nodes.
|
||||
** Remove first element from the tbclist plus its dummy nodes.
|
||||
*/
|
||||
static void poptbclist (lua_State *L) {
|
||||
StkId tbc = L->tbclist;
|
||||
@@ -224,9 +224,9 @@ static void poptbclist (lua_State *L) {
|
||||
|
||||
/*
|
||||
** Close all upvalues and to-be-closed variables up to the given stack
|
||||
** level.
|
||||
** level. Return restored 'level'.
|
||||
*/
|
||||
void luaF_close (lua_State *L, StkId level, int status, int yy) {
|
||||
StkId luaF_close (lua_State *L, StkId level, int status, int yy) {
|
||||
ptrdiff_t levelrel = savestack(L, level);
|
||||
luaF_closeupval(L, level); /* first, close the upvalues */
|
||||
while (L->tbclist >= level) { /* traverse tbc's down to that level */
|
||||
@@ -235,6 +235,7 @@ void luaF_close (lua_State *L, StkId level, int status, int yy) {
|
||||
prepcallclosemth(L, tbc, status, yy); /* close variable */
|
||||
level = restorestack(L, levelrel);
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
|
||||
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
|
||||
LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level);
|
||||
LUAI_FUNC void luaF_closeupval (lua_State *L, StkId level);
|
||||
LUAI_FUNC void luaF_close (lua_State *L, StkId level, int status, int yy);
|
||||
LUAI_FUNC StkId luaF_close (lua_State *L, StkId level, int status, int yy);
|
||||
LUAI_FUNC void luaF_unlinkupval (UpVal *uv);
|
||||
LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
|
||||
LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
|
||||
|
||||
@@ -1043,7 +1043,25 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
static void setpause (global_State *g);
|
||||
|
||||
/*
|
||||
** Set the "time" to wait before starting a new GC cycle; cycle will
|
||||
** start when memory use hits the threshold of ('estimate' * pause /
|
||||
** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero,
|
||||
** because Lua cannot even start with less than PAUSEADJ bytes).
|
||||
*/
|
||||
static void setpause (global_State *g) {
|
||||
l_mem threshold, debt;
|
||||
int pause = getgcparam(g->gcpause);
|
||||
l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */
|
||||
lua_assert(estimate > 0);
|
||||
threshold = (pause < MAX_LMEM / estimate) /* overflow? */
|
||||
? estimate * pause /* no overflow */
|
||||
: MAX_LMEM; /* overflow; truncate to maximum */
|
||||
debt = gettotalbytes(g) - threshold;
|
||||
if (debt > 0) debt = 0;
|
||||
luaE_setdebt(g, debt);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -1291,6 +1309,15 @@ static void atomic2gen (lua_State *L, global_State *g) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Set debt for the next minor collection, which will happen when
|
||||
** memory grows 'genminormul'%.
|
||||
*/
|
||||
static void setminordebt (global_State *g) {
|
||||
luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Enter generational mode. Must go until the end of an atomic cycle
|
||||
** to ensure that all objects are correctly marked and weak tables
|
||||
@@ -1303,6 +1330,7 @@ static lu_mem entergen (lua_State *L, global_State *g) {
|
||||
luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
|
||||
numobjs = atomic(L); /* propagates all and then do the atomic stuff */
|
||||
atomic2gen(L, g);
|
||||
setminordebt(g); /* set debt assuming next cycle will be minor */
|
||||
return numobjs;
|
||||
}
|
||||
|
||||
@@ -1348,15 +1376,6 @@ static lu_mem fullgen (lua_State *L, global_State *g) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Set debt for the next minor collection, which will happen when
|
||||
** memory grows 'genminormul'%.
|
||||
*/
|
||||
static void setminordebt (global_State *g) {
|
||||
luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Does a major collection after last collection was a "bad collection".
|
||||
**
|
||||
@@ -1428,8 +1447,8 @@ static void genstep (lua_State *L, global_State *g) {
|
||||
lu_mem numobjs = fullgen(L, g); /* do a major collection */
|
||||
if (gettotalbytes(g) < majorbase + (majorinc / 2)) {
|
||||
/* collected at least half of memory growth since last major
|
||||
collection; keep doing minor collections */
|
||||
setminordebt(g);
|
||||
collection; keep doing minor collections. */
|
||||
lua_assert(g->lastatomic == 0);
|
||||
}
|
||||
else { /* bad collection */
|
||||
g->lastatomic = numobjs; /* signal that last collection was bad */
|
||||
@@ -1455,26 +1474,6 @@ static void genstep (lua_State *L, global_State *g) {
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** Set the "time" to wait before starting a new GC cycle; cycle will
|
||||
** start when memory use hits the threshold of ('estimate' * pause /
|
||||
** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero,
|
||||
** because Lua cannot even start with less than PAUSEADJ bytes).
|
||||
*/
|
||||
static void setpause (global_State *g) {
|
||||
l_mem threshold, debt;
|
||||
int pause = getgcparam(g->gcpause);
|
||||
l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */
|
||||
lua_assert(estimate > 0);
|
||||
threshold = (pause < MAX_LMEM / estimate) /* overflow? */
|
||||
? estimate * pause /* no overflow */
|
||||
: MAX_LMEM; /* overflow; truncate to maximum */
|
||||
debt = gettotalbytes(g) - threshold;
|
||||
if (debt > 0) debt = 0;
|
||||
luaE_setdebt(g, debt);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Enter first sweep phase.
|
||||
** The call to 'sweeptolive' makes the pointer point to an object
|
||||
|
||||
@@ -708,8 +708,13 @@ static const luaL_Reg ll_funcs[] = {
|
||||
|
||||
|
||||
static void createsearcherstable (lua_State *L) {
|
||||
static const lua_CFunction searchers[] =
|
||||
{searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
|
||||
static const lua_CFunction searchers[] = {
|
||||
searcher_preload,
|
||||
searcher_Lua,
|
||||
searcher_C,
|
||||
searcher_Croot,
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
/* create 'searchers' table */
|
||||
lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
|
||||
|
||||
@@ -386,29 +386,39 @@ void luaO_tostring (lua_State *L, TValue *obj) {
|
||||
** ===================================================================
|
||||
*/
|
||||
|
||||
/* size for buffer space used by 'luaO_pushvfstring' */
|
||||
#define BUFVFS 200
|
||||
/*
|
||||
** Size for buffer space used by 'luaO_pushvfstring'. It should be
|
||||
** (LUA_IDSIZE + MAXNUMBER2STR) + a minimal space for basic messages,
|
||||
** so that 'luaG_addinfo' can work directly on the buffer.
|
||||
*/
|
||||
#define BUFVFS (LUA_IDSIZE + MAXNUMBER2STR + 95)
|
||||
|
||||
/* buffer used by 'luaO_pushvfstring' */
|
||||
typedef struct BuffFS {
|
||||
lua_State *L;
|
||||
int pushed; /* number of string pieces already on the stack */
|
||||
int pushed; /* true if there is a part of the result on the stack */
|
||||
int blen; /* length of partial string in 'space' */
|
||||
char space[BUFVFS]; /* holds last part of the result */
|
||||
} BuffFS;
|
||||
|
||||
|
||||
/*
|
||||
** Push given string to the stack, as part of the buffer, and
|
||||
** join the partial strings in the stack into one.
|
||||
** Push given string to the stack, as part of the result, and
|
||||
** join it to previous partial result if there is one.
|
||||
** It may call 'luaV_concat' while using one slot from EXTRA_STACK.
|
||||
** This call cannot invoke metamethods, as both operands must be
|
||||
** strings. It can, however, raise an error if the result is too
|
||||
** long. In that case, 'luaV_concat' frees the extra slot before
|
||||
** raising the error.
|
||||
*/
|
||||
static void pushstr (BuffFS *buff, const char *str, size_t l) {
|
||||
static void pushstr (BuffFS *buff, const char *str, size_t lstr) {
|
||||
lua_State *L = buff->L;
|
||||
setsvalue2s(L, L->top, luaS_newlstr(L, str, l));
|
||||
L->top++; /* may use one extra slot */
|
||||
buff->pushed++;
|
||||
luaV_concat(L, buff->pushed); /* join partial results into one */
|
||||
buff->pushed = 1;
|
||||
setsvalue2s(L, L->top, luaS_newlstr(L, str, lstr));
|
||||
L->top++; /* may use one slot from EXTRA_STACK */
|
||||
if (!buff->pushed) /* no previous string on the stack? */
|
||||
buff->pushed = 1; /* now there is one */
|
||||
else /* join previous string with new one */
|
||||
luaV_concat(L, 2);
|
||||
}
|
||||
|
||||
|
||||
@@ -454,7 +464,7 @@ static void addstr2buff (BuffFS *buff, const char *str, size_t slen) {
|
||||
|
||||
|
||||
/*
|
||||
** Add a number to the buffer.
|
||||
** Add a numeral to the buffer.
|
||||
*/
|
||||
static void addnum2buff (BuffFS *buff, TValue *num) {
|
||||
char *numbuff = getbuff(buff, MAXNUMBER2STR);
|
||||
|
||||
@@ -52,6 +52,8 @@ typedef union Value {
|
||||
lua_CFunction f; /* light C functions */
|
||||
lua_Integer i; /* integer numbers */
|
||||
lua_Number n; /* float numbers */
|
||||
/* not used, but may avoid warnings for uninitialized value */
|
||||
lu_byte ub;
|
||||
} Value;
|
||||
|
||||
|
||||
|
||||
@@ -468,6 +468,7 @@ static void singlevar (LexState *ls, expdesc *var) {
|
||||
expdesc key;
|
||||
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
|
||||
lua_assert(var->k != VVOID); /* this one must exist */
|
||||
luaK_exp2anyregup(fs, var); /* but could be a constant */
|
||||
codestring(&key, varname); /* key is variable name */
|
||||
luaK_indexed(fs, var, &key); /* env[varname] */
|
||||
}
|
||||
@@ -673,19 +674,19 @@ static void leaveblock (FuncState *fs) {
|
||||
LexState *ls = fs->ls;
|
||||
int hasclose = 0;
|
||||
int stklevel = reglevel(fs, bl->nactvar); /* level outside the block */
|
||||
if (bl->isloop) /* fix pending breaks? */
|
||||
removevars(fs, bl->nactvar); /* remove block locals */
|
||||
lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */
|
||||
if (bl->isloop) /* has to fix pending breaks? */
|
||||
hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0);
|
||||
if (!hasclose && bl->previous && bl->upval)
|
||||
if (!hasclose && bl->previous && bl->upval) /* still need a 'close'? */
|
||||
luaK_codeABC(fs, OP_CLOSE, stklevel, 0, 0);
|
||||
fs->bl = bl->previous;
|
||||
removevars(fs, bl->nactvar);
|
||||
lua_assert(bl->nactvar == fs->nactvar);
|
||||
fs->freereg = stklevel; /* free registers */
|
||||
ls->dyd->label.n = bl->firstlabel; /* remove local labels */
|
||||
if (bl->previous) /* inner block? */
|
||||
movegotosout(fs, bl); /* update pending gotos to outer block */
|
||||
fs->bl = bl->previous; /* current block now is previous one */
|
||||
if (bl->previous) /* was it a nested block? */
|
||||
movegotosout(fs, bl); /* update pending gotos to enclosing block */
|
||||
else {
|
||||
if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */
|
||||
if (bl->firstgoto < ls->dyd->gt.n) /* still pending gotos? */
|
||||
undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,9 +43,10 @@ int luaS_eqlngstr (TString *a, TString *b) {
|
||||
}
|
||||
|
||||
int luaS_eqshrstr (TString *a, TString *b) {
|
||||
int r;
|
||||
lu_byte len = a->shrlen;
|
||||
lua_assert(b->tt == LUA_VSHRSTR);
|
||||
int r = len == b->shrlen && (memcmp(getstr(a), getstr(b), len) == 0);
|
||||
r = len == b->shrlen && (memcmp(getstr(a), getstr(b), len) == 0);
|
||||
if (r) {
|
||||
if (a->id < b->id) {
|
||||
a->id = b->id;
|
||||
@@ -161,10 +162,11 @@ static unsigned int luai_makeseed(lua_State *L) {
|
||||
void luaS_init (lua_State *L) {
|
||||
global_State *g = G(L);
|
||||
int i, j;
|
||||
stringtable *tb;
|
||||
if (STRSEED == 0) {
|
||||
STRSEED = luai_makeseed(L);
|
||||
}
|
||||
stringtable *tb = &G(L)->strt;
|
||||
tb = &G(L)->strt;
|
||||
tb->hash = luaM_newvector(L, MINSTRTABSIZE, TString*);
|
||||
tablerehash(tb->hash, 0, MINSTRTABSIZE); /* clear array */
|
||||
tb->size = MINSTRTABSIZE;
|
||||
|
||||
@@ -177,10 +177,11 @@ static void print_version (void) {
|
||||
** to the script (everything after 'script') go to positive indices;
|
||||
** other arguments (before the script name) go to negative indices.
|
||||
** If there is no script name, assume interpreter's name as base.
|
||||
** (If there is no interpreter's name either, 'script' is -1, so
|
||||
** table sizes are zero.)
|
||||
*/
|
||||
static void createargtable (lua_State *L, char **argv, int argc, int script) {
|
||||
int i, narg;
|
||||
if (script == argc) script = 0; /* no script name? */
|
||||
narg = argc - (script + 1); /* number of positive indices */
|
||||
lua_createtable(L, narg, script + 1);
|
||||
for (i = 0; i < argc; i++) {
|
||||
@@ -268,14 +269,23 @@ static int handle_script (lua_State *L, char **argv) {
|
||||
|
||||
/*
|
||||
** Traverses all arguments from 'argv', returning a mask with those
|
||||
** needed before running any Lua code (or an error code if it finds
|
||||
** any invalid argument). 'first' returns the first not-handled argument
|
||||
** (either the script name or a bad argument in case of error).
|
||||
** needed before running any Lua code or an error code if it finds any
|
||||
** invalid argument. In case of error, 'first' is the index of the bad
|
||||
** argument. Otherwise, 'first' is -1 if there is no program name,
|
||||
** 0 if there is no script name, or the index of the script name.
|
||||
*/
|
||||
static int collectargs (char **argv, int *first) {
|
||||
int args = 0;
|
||||
int i;
|
||||
for (i = 1; argv[i] != NULL; i++) {
|
||||
if (argv[0] != NULL) { /* is there a program name? */
|
||||
if (argv[0][0]) /* not empty? */
|
||||
progname = argv[0]; /* save it */
|
||||
}
|
||||
else { /* no program name */
|
||||
*first = -1;
|
||||
return 0;
|
||||
}
|
||||
for (i = 1; argv[i] != NULL; i++) { /* handle arguments */
|
||||
*first = i;
|
||||
if (argv[i][0] != '-') /* not an option? */
|
||||
return args; /* stop handling options */
|
||||
@@ -316,7 +326,7 @@ static int collectargs (char **argv, int *first) {
|
||||
return has_error;
|
||||
}
|
||||
}
|
||||
*first = i; /* no script name */
|
||||
*first = 0; /* no script name */
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -609,8 +619,8 @@ static int pmain (lua_State *L) {
|
||||
char **argv = (char **)lua_touserdata(L, 2);
|
||||
int script;
|
||||
int args = collectargs(argv, &script);
|
||||
int optlim = (script > 0) ? script : argc; /* first argv not an option */
|
||||
luaL_checkversion(L); /* check that interpreter has correct version */
|
||||
if (argv[0] && argv[0][0]) progname = argv[0];
|
||||
if (args == has_error) { /* bad arg? */
|
||||
print_usage(argv[script]); /* 'script' has index of bad arg. */
|
||||
return 0;
|
||||
@@ -628,14 +638,15 @@ static int pmain (lua_State *L) {
|
||||
if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */
|
||||
return 0; /* error running LUA_INIT */
|
||||
}
|
||||
if (!runargs(L, argv, script)) /* execute arguments -e and -l */
|
||||
if (!runargs(L, argv, optlim)) /* execute arguments -e and -l */
|
||||
return 0; /* something failed */
|
||||
if (script < argc && /* execute main script (if there is one) */
|
||||
handle_script(L, argv + script) != LUA_OK)
|
||||
return 0;
|
||||
if (script > 0) { /* execute main script (if there is one) */
|
||||
if (handle_script(L, argv + script) != LUA_OK)
|
||||
return 0; /* interrupt in case of error */
|
||||
}
|
||||
if (args & has_i) /* -i option? */
|
||||
doREPL(L); /* do read-eval-print loop */
|
||||
else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */
|
||||
else if (script < 1 && !(args & (has_e | has_v))) { /* no active option? */
|
||||
if (lua_stdin_is_tty()) { /* running in interactive mode? */
|
||||
print_version();
|
||||
doREPL(L); /* do read-eval-print loop */
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
|
||||
#define LUA_VERSION_MAJOR "5"
|
||||
#define LUA_VERSION_MINOR "4"
|
||||
#define LUA_VERSION_RELEASE "4"
|
||||
#define LUA_VERSION_RELEASE "5"
|
||||
|
||||
#define LUA_VERSION_NUM 504
|
||||
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 4)
|
||||
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 5)
|
||||
|
||||
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
|
||||
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
|
||||
|
||||
@@ -728,7 +728,7 @@
|
||||
** CHANGE it if you need a different limit. This limit is arbitrary;
|
||||
** its only purpose is to stop Lua from consuming unlimited stack
|
||||
** space (and to reserve some numbers for pseudo-indices).
|
||||
** (It must fit into max(size_t)/32.)
|
||||
** (It must fit into max(size_t)/32 and max(int)/2.)
|
||||
*/
|
||||
#if LUAI_IS32INT
|
||||
#define LUAI_MAXSTACK 1000000
|
||||
|
||||
133
3rd/lua/lvm.c
133
3rd/lua/lvm.c
@@ -645,7 +645,7 @@ void luaV_concat (lua_State *L, int total) {
|
||||
int n = 2; /* number of elements handled in this pass (at least 2) */
|
||||
if (!(ttisstring(s2v(top - 2)) || cvt2str(s2v(top - 2))) ||
|
||||
!tostring(L, s2v(top - 1)))
|
||||
luaT_tryconcatTM(L);
|
||||
luaT_tryconcatTM(L); /* may invalidate 'top' */
|
||||
else if (isemptystr(s2v(top - 1))) /* second operand is empty? */
|
||||
cast_void(tostring(L, s2v(top - 2))); /* result is first operand */
|
||||
else if (isemptystr(s2v(top - 2))) { /* first operand is empty string? */
|
||||
@@ -658,8 +658,10 @@ void luaV_concat (lua_State *L, int total) {
|
||||
/* collect total length and number of strings */
|
||||
for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
|
||||
size_t l = vslen(s2v(top - n - 1));
|
||||
if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl))
|
||||
if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) {
|
||||
L->top = top - total; /* pop strings to avoid wasting stack */
|
||||
luaG_runerror(L, "string length overflow");
|
||||
}
|
||||
tl += l;
|
||||
}
|
||||
if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */
|
||||
@@ -673,8 +675,8 @@ void luaV_concat (lua_State *L, int total) {
|
||||
}
|
||||
setsvalue2s(L, top - n, ts); /* create result */
|
||||
}
|
||||
total -= n-1; /* got 'n' strings to create 1 new */
|
||||
L->top -= n-1; /* popped 'n' strings and pushed one */
|
||||
total -= n - 1; /* got 'n' strings to create one new */
|
||||
L->top -= n - 1; /* popped 'n' strings and pushed one */
|
||||
} while (total > 1); /* repeat until only 1 result left */
|
||||
}
|
||||
|
||||
@@ -900,6 +902,7 @@ void luaV_finishOp (lua_State *L) {
|
||||
** operation, 'fop' is the float operation.
|
||||
*/
|
||||
#define op_arithI(L,iop,fop) { \
|
||||
StkId ra = RA(i); \
|
||||
TValue *v1 = vRB(i); \
|
||||
int imm = GETARG_sC(i); \
|
||||
if (ttisinteger(v1)) { \
|
||||
@@ -928,6 +931,7 @@ void luaV_finishOp (lua_State *L) {
|
||||
** Arithmetic operations over floats and others with register operands.
|
||||
*/
|
||||
#define op_arithf(L,fop) { \
|
||||
StkId ra = RA(i); \
|
||||
TValue *v1 = vRB(i); \
|
||||
TValue *v2 = vRC(i); \
|
||||
op_arithf_aux(L, v1, v2, fop); }
|
||||
@@ -937,6 +941,7 @@ void luaV_finishOp (lua_State *L) {
|
||||
** Arithmetic operations with K operands for floats.
|
||||
*/
|
||||
#define op_arithfK(L,fop) { \
|
||||
StkId ra = RA(i); \
|
||||
TValue *v1 = vRB(i); \
|
||||
TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \
|
||||
op_arithf_aux(L, v1, v2, fop); }
|
||||
@@ -946,6 +951,7 @@ void luaV_finishOp (lua_State *L) {
|
||||
** Arithmetic operations over integers and floats.
|
||||
*/
|
||||
#define op_arith_aux(L,v1,v2,iop,fop) { \
|
||||
StkId ra = RA(i); \
|
||||
if (ttisinteger(v1) && ttisinteger(v2)) { \
|
||||
lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \
|
||||
pc++; setivalue(s2v(ra), iop(L, i1, i2)); \
|
||||
@@ -975,6 +981,7 @@ void luaV_finishOp (lua_State *L) {
|
||||
** Bitwise operations with constant operand.
|
||||
*/
|
||||
#define op_bitwiseK(L,op) { \
|
||||
StkId ra = RA(i); \
|
||||
TValue *v1 = vRB(i); \
|
||||
TValue *v2 = KC(i); \
|
||||
lua_Integer i1; \
|
||||
@@ -988,6 +995,7 @@ void luaV_finishOp (lua_State *L) {
|
||||
** Bitwise operations with register operands.
|
||||
*/
|
||||
#define op_bitwise(L,op) { \
|
||||
StkId ra = RA(i); \
|
||||
TValue *v1 = vRB(i); \
|
||||
TValue *v2 = vRC(i); \
|
||||
lua_Integer i1; lua_Integer i2; \
|
||||
@@ -1002,18 +1010,19 @@ void luaV_finishOp (lua_State *L) {
|
||||
** integers.
|
||||
*/
|
||||
#define op_order(L,opi,opn,other) { \
|
||||
int cond; \
|
||||
TValue *rb = vRB(i); \
|
||||
if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \
|
||||
lua_Integer ia = ivalue(s2v(ra)); \
|
||||
lua_Integer ib = ivalue(rb); \
|
||||
cond = opi(ia, ib); \
|
||||
} \
|
||||
else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \
|
||||
cond = opn(s2v(ra), rb); \
|
||||
else \
|
||||
Protect(cond = other(L, s2v(ra), rb)); \
|
||||
docondjump(); }
|
||||
StkId ra = RA(i); \
|
||||
int cond; \
|
||||
TValue *rb = vRB(i); \
|
||||
if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \
|
||||
lua_Integer ia = ivalue(s2v(ra)); \
|
||||
lua_Integer ib = ivalue(rb); \
|
||||
cond = opi(ia, ib); \
|
||||
} \
|
||||
else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \
|
||||
cond = opn(s2v(ra), rb); \
|
||||
else \
|
||||
Protect(cond = other(L, s2v(ra), rb)); \
|
||||
docondjump(); }
|
||||
|
||||
|
||||
/*
|
||||
@@ -1021,20 +1030,21 @@ void luaV_finishOp (lua_State *L) {
|
||||
** always small enough to have an exact representation as a float.)
|
||||
*/
|
||||
#define op_orderI(L,opi,opf,inv,tm) { \
|
||||
int cond; \
|
||||
int im = GETARG_sB(i); \
|
||||
if (ttisinteger(s2v(ra))) \
|
||||
cond = opi(ivalue(s2v(ra)), im); \
|
||||
else if (ttisfloat(s2v(ra))) { \
|
||||
lua_Number fa = fltvalue(s2v(ra)); \
|
||||
lua_Number fim = cast_num(im); \
|
||||
cond = opf(fa, fim); \
|
||||
} \
|
||||
else { \
|
||||
int isf = GETARG_C(i); \
|
||||
Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \
|
||||
} \
|
||||
docondjump(); }
|
||||
StkId ra = RA(i); \
|
||||
int cond; \
|
||||
int im = GETARG_sB(i); \
|
||||
if (ttisinteger(s2v(ra))) \
|
||||
cond = opi(ivalue(s2v(ra)), im); \
|
||||
else if (ttisfloat(s2v(ra))) { \
|
||||
lua_Number fa = fltvalue(s2v(ra)); \
|
||||
lua_Number fim = cast_num(im); \
|
||||
cond = opf(fa, fim); \
|
||||
} \
|
||||
else { \
|
||||
int isf = GETARG_C(i); \
|
||||
Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \
|
||||
} \
|
||||
docondjump(); }
|
||||
|
||||
/* }================================================================== */
|
||||
|
||||
@@ -1130,7 +1140,6 @@ void luaV_finishOp (lua_State *L) {
|
||||
updatebase(ci); /* correct stack */ \
|
||||
} \
|
||||
i = *(pc++); \
|
||||
ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \
|
||||
}
|
||||
|
||||
#define vmdispatch(o) switch(o)
|
||||
@@ -1166,56 +1175,64 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
/* main loop of interpreter */
|
||||
for (;;) {
|
||||
Instruction i; /* instruction being executed */
|
||||
StkId ra; /* instruction's A register */
|
||||
vmfetch();
|
||||
#if 0
|
||||
/* low-level line tracing for debugging Lua */
|
||||
printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p)));
|
||||
#endif
|
||||
lua_assert(base == ci->func + 1);
|
||||
lua_assert(base <= L->top && L->top < L->stack_last);
|
||||
lua_assert(base <= L->top && L->top <= L->stack_last);
|
||||
/* invalidate top for instructions not expecting it */
|
||||
lua_assert(isIT(i) || (cast_void(L->top = base), 1));
|
||||
vmdispatch (GET_OPCODE(i)) {
|
||||
vmcase(OP_MOVE) {
|
||||
StkId ra = RA(i);
|
||||
setobjs2s(L, ra, RB(i));
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_LOADI) {
|
||||
StkId ra = RA(i);
|
||||
lua_Integer b = GETARG_sBx(i);
|
||||
setivalue(s2v(ra), b);
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_LOADF) {
|
||||
StkId ra = RA(i);
|
||||
int b = GETARG_sBx(i);
|
||||
setfltvalue(s2v(ra), cast_num(b));
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_LOADK) {
|
||||
StkId ra = RA(i);
|
||||
TValue *rb = k + GETARG_Bx(i);
|
||||
setobj2s(L, ra, rb);
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_LOADKX) {
|
||||
StkId ra = RA(i);
|
||||
TValue *rb;
|
||||
rb = k + GETARG_Ax(*pc); pc++;
|
||||
setobj2s(L, ra, rb);
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_LOADFALSE) {
|
||||
StkId ra = RA(i);
|
||||
setbfvalue(s2v(ra));
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_LFALSESKIP) {
|
||||
StkId ra = RA(i);
|
||||
setbfvalue(s2v(ra));
|
||||
pc++; /* skip next instruction */
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_LOADTRUE) {
|
||||
StkId ra = RA(i);
|
||||
setbtvalue(s2v(ra));
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_LOADNIL) {
|
||||
StkId ra = RA(i);
|
||||
int b = GETARG_B(i);
|
||||
do {
|
||||
setnilvalue(s2v(ra++));
|
||||
@@ -1223,17 +1240,20 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_GETUPVAL) {
|
||||
StkId ra = RA(i);
|
||||
int b = GETARG_B(i);
|
||||
setobj2s(L, ra, cl->upvals[b]->v);
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_SETUPVAL) {
|
||||
StkId ra = RA(i);
|
||||
UpVal *uv = cl->upvals[GETARG_B(i)];
|
||||
setobj(L, uv->v, s2v(ra));
|
||||
luaC_barrier(L, uv, s2v(ra));
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_GETTABUP) {
|
||||
StkId ra = RA(i);
|
||||
const TValue *slot;
|
||||
TValue *upval = cl->upvals[GETARG_B(i)]->v;
|
||||
TValue *rc = KC(i);
|
||||
@@ -1246,6 +1266,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_GETTABLE) {
|
||||
StkId ra = RA(i);
|
||||
const TValue *slot;
|
||||
TValue *rb = vRB(i);
|
||||
TValue *rc = vRC(i);
|
||||
@@ -1260,6 +1281,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_GETI) {
|
||||
StkId ra = RA(i);
|
||||
const TValue *slot;
|
||||
TValue *rb = vRB(i);
|
||||
int c = GETARG_C(i);
|
||||
@@ -1274,6 +1296,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_GETFIELD) {
|
||||
StkId ra = RA(i);
|
||||
const TValue *slot;
|
||||
TValue *rb = vRB(i);
|
||||
TValue *rc = KC(i);
|
||||
@@ -1299,6 +1322,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_SETTABLE) {
|
||||
StkId ra = RA(i);
|
||||
const TValue *slot;
|
||||
TValue *rb = vRB(i); /* key (table is in 'ra') */
|
||||
TValue *rc = RKC(i); /* value */
|
||||
@@ -1313,6 +1337,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_SETI) {
|
||||
StkId ra = RA(i);
|
||||
const TValue *slot;
|
||||
int c = GETARG_B(i);
|
||||
TValue *rc = RKC(i);
|
||||
@@ -1327,6 +1352,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_SETFIELD) {
|
||||
StkId ra = RA(i);
|
||||
const TValue *slot;
|
||||
TValue *rb = KB(i);
|
||||
TValue *rc = RKC(i);
|
||||
@@ -1339,6 +1365,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_NEWTABLE) {
|
||||
StkId ra = RA(i);
|
||||
int b = GETARG_B(i); /* log2(hash size) + 1 */
|
||||
int c = GETARG_C(i); /* array size */
|
||||
Table *t;
|
||||
@@ -1357,6 +1384,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_SELF) {
|
||||
StkId ra = RA(i);
|
||||
const TValue *slot;
|
||||
TValue *rb = vRB(i);
|
||||
TValue *rc = RKC(i);
|
||||
@@ -1414,6 +1442,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_SHRI) {
|
||||
StkId ra = RA(i);
|
||||
TValue *rb = vRB(i);
|
||||
int ic = GETARG_sC(i);
|
||||
lua_Integer ib;
|
||||
@@ -1423,6 +1452,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_SHLI) {
|
||||
StkId ra = RA(i);
|
||||
TValue *rb = vRB(i);
|
||||
int ic = GETARG_sC(i);
|
||||
lua_Integer ib;
|
||||
@@ -1480,6 +1510,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_MMBIN) {
|
||||
StkId ra = RA(i);
|
||||
Instruction pi = *(pc - 2); /* original arith. expression */
|
||||
TValue *rb = vRB(i);
|
||||
TMS tm = (TMS)GETARG_C(i);
|
||||
@@ -1489,6 +1520,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_MMBINI) {
|
||||
StkId ra = RA(i);
|
||||
Instruction pi = *(pc - 2); /* original arith. expression */
|
||||
int imm = GETARG_sB(i);
|
||||
TMS tm = (TMS)GETARG_C(i);
|
||||
@@ -1498,6 +1530,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_MMBINK) {
|
||||
StkId ra = RA(i);
|
||||
Instruction pi = *(pc - 2); /* original arith. expression */
|
||||
TValue *imm = KB(i);
|
||||
TMS tm = (TMS)GETARG_C(i);
|
||||
@@ -1507,6 +1540,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_UNM) {
|
||||
StkId ra = RA(i);
|
||||
TValue *rb = vRB(i);
|
||||
lua_Number nb;
|
||||
if (ttisinteger(rb)) {
|
||||
@@ -1521,6 +1555,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_BNOT) {
|
||||
StkId ra = RA(i);
|
||||
TValue *rb = vRB(i);
|
||||
lua_Integer ib;
|
||||
if (tointegerns(rb, &ib)) {
|
||||
@@ -1531,6 +1566,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_NOT) {
|
||||
StkId ra = RA(i);
|
||||
TValue *rb = vRB(i);
|
||||
if (l_isfalse(rb))
|
||||
setbtvalue(s2v(ra));
|
||||
@@ -1539,10 +1575,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_LEN) {
|
||||
StkId ra = RA(i);
|
||||
Protect(luaV_objlen(L, ra, vRB(i)));
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_CONCAT) {
|
||||
StkId ra = RA(i);
|
||||
int n = GETARG_B(i); /* number of elements to concatenate */
|
||||
L->top = ra + n; /* mark the end of concat operands */
|
||||
ProtectNT(luaV_concat(L, n));
|
||||
@@ -1550,10 +1588,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_CLOSE) {
|
||||
StkId ra = RA(i);
|
||||
Protect(luaF_close(L, ra, LUA_OK, 1));
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_TBC) {
|
||||
StkId ra = RA(i);
|
||||
/* create new to-be-closed upvalue */
|
||||
halfProtect(luaF_newtbcupval(L, ra));
|
||||
vmbreak;
|
||||
@@ -1563,6 +1603,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_EQ) {
|
||||
StkId ra = RA(i);
|
||||
int cond;
|
||||
TValue *rb = vRB(i);
|
||||
Protect(cond = luaV_equalobj(L, s2v(ra), rb));
|
||||
@@ -1578,6 +1619,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_EQK) {
|
||||
StkId ra = RA(i);
|
||||
TValue *rb = KB(i);
|
||||
/* basic types do not use '__eq'; we can use raw equality */
|
||||
int cond = luaV_rawequalobj(s2v(ra), rb);
|
||||
@@ -1585,6 +1627,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_EQI) {
|
||||
StkId ra = RA(i);
|
||||
int cond;
|
||||
int im = GETARG_sB(i);
|
||||
if (ttisinteger(s2v(ra)))
|
||||
@@ -1613,11 +1656,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_TEST) {
|
||||
StkId ra = RA(i);
|
||||
int cond = !l_isfalse(s2v(ra));
|
||||
docondjump();
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_TESTSET) {
|
||||
StkId ra = RA(i);
|
||||
TValue *rb = vRB(i);
|
||||
if (l_isfalse(rb) == GETARG_k(i))
|
||||
pc++;
|
||||
@@ -1628,6 +1673,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_CALL) {
|
||||
StkId ra = RA(i);
|
||||
CallInfo *newci;
|
||||
int b = GETARG_B(i);
|
||||
int nresults = GETARG_C(i) - 1;
|
||||
@@ -1644,6 +1690,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_TAILCALL) {
|
||||
StkId ra = RA(i);
|
||||
int b = GETARG_B(i); /* number of arguments + 1 (function) */
|
||||
int n; /* number of results when calling a C function */
|
||||
int nparams1 = GETARG_C(i);
|
||||
@@ -1669,6 +1716,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
}
|
||||
}
|
||||
vmcase(OP_RETURN) {
|
||||
StkId ra = RA(i);
|
||||
int n = GETARG_B(i) - 1; /* number of results */
|
||||
int nparams1 = GETARG_C(i);
|
||||
if (n < 0) /* not fixed? */
|
||||
@@ -1691,6 +1739,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
}
|
||||
vmcase(OP_RETURN0) {
|
||||
if (l_unlikely(L->hookmask)) {
|
||||
StkId ra = RA(i);
|
||||
L->top = ra;
|
||||
savepc(ci);
|
||||
luaD_poscall(L, ci, 0); /* no hurry... */
|
||||
@@ -1707,6 +1756,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
}
|
||||
vmcase(OP_RETURN1) {
|
||||
if (l_unlikely(L->hookmask)) {
|
||||
StkId ra = RA(i);
|
||||
L->top = ra + 1;
|
||||
savepc(ci);
|
||||
luaD_poscall(L, ci, 1); /* no hurry... */
|
||||
@@ -1718,6 +1768,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
if (nres == 0)
|
||||
L->top = base - 1; /* asked for no results */
|
||||
else {
|
||||
StkId ra = RA(i);
|
||||
setobjs2s(L, base - 1, ra); /* at least this result */
|
||||
L->top = base;
|
||||
for (; l_unlikely(nres > 1); nres--)
|
||||
@@ -1733,6 +1784,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
}
|
||||
}
|
||||
vmcase(OP_FORLOOP) {
|
||||
StkId ra = RA(i);
|
||||
if (ttisinteger(s2v(ra + 2))) { /* integer loop? */
|
||||
lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1)));
|
||||
if (count > 0) { /* still more iterations? */
|
||||
@@ -1751,12 +1803,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_FORPREP) {
|
||||
StkId ra = RA(i);
|
||||
savestate(L, ci); /* in case of errors */
|
||||
if (forprep(L, ra))
|
||||
pc += GETARG_Bx(i) + 1; /* skip the loop */
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_TFORPREP) {
|
||||
StkId ra = RA(i);
|
||||
/* create to-be-closed upvalue (if needed) */
|
||||
halfProtect(luaF_newtbcupval(L, ra + 3));
|
||||
pc += GETARG_Bx(i);
|
||||
@@ -1765,7 +1819,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
goto l_tforcall;
|
||||
}
|
||||
vmcase(OP_TFORCALL) {
|
||||
l_tforcall:
|
||||
l_tforcall: {
|
||||
StkId ra = RA(i);
|
||||
/* 'ra' has the iterator function, 'ra + 1' has the state,
|
||||
'ra + 2' has the control variable, and 'ra + 3' has the
|
||||
to-be-closed variable. The call will use the stack after
|
||||
@@ -1779,16 +1834,18 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
i = *(pc++); /* go to next instruction */
|
||||
lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
|
||||
goto l_tforloop;
|
||||
}
|
||||
}}
|
||||
vmcase(OP_TFORLOOP) {
|
||||
l_tforloop:
|
||||
l_tforloop: {
|
||||
StkId ra = RA(i);
|
||||
if (!ttisnil(s2v(ra + 4))) { /* continue loop? */
|
||||
setobjs2s(L, ra + 2, ra + 4); /* save control variable */
|
||||
pc -= GETARG_Bx(i); /* jump back */
|
||||
}
|
||||
vmbreak;
|
||||
}
|
||||
}}
|
||||
vmcase(OP_SETLIST) {
|
||||
StkId ra = RA(i);
|
||||
int n = GETARG_B(i);
|
||||
unsigned int last = GETARG_C(i);
|
||||
Table *h = hvalue(s2v(ra));
|
||||
@@ -1812,12 +1869,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_CLOSURE) {
|
||||
StkId ra = RA(i);
|
||||
Proto *p = cl->p->p[GETARG_Bx(i)];
|
||||
halfProtect(pushclosure(L, p, cl->upvals, base, ra));
|
||||
checkGC(L, ra + 1);
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_VARARG) {
|
||||
StkId ra = RA(i);
|
||||
int n = GETARG_C(i) - 1; /* required results */
|
||||
Protect(luaT_getvarargs(L, ci, ra, n));
|
||||
vmbreak;
|
||||
|
||||
@@ -1,159 +1,140 @@
|
||||
# Makefile for building Lua
|
||||
# See ../doc/readme.html for installation and customization instructions.
|
||||
# Developer's makefile for building Lua
|
||||
# see luaconf.h for further customization
|
||||
|
||||
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
|
||||
|
||||
# Your platform. See PLATS for possible values.
|
||||
PLAT= guess
|
||||
# Warnings valid for both C and C++
|
||||
CWARNSCPP= \
|
||||
-Wfatal-errors \
|
||||
-Wextra \
|
||||
-Wshadow \
|
||||
-Wsign-compare \
|
||||
-Wundef \
|
||||
-Wwrite-strings \
|
||||
-Wredundant-decls \
|
||||
-Wdisabled-optimization \
|
||||
-Wdouble-promotion \
|
||||
-Wmissing-declarations \
|
||||
# the next warnings might be useful sometimes,
|
||||
# but usually they generate too much noise
|
||||
# -Werror \
|
||||
# -pedantic # warns if we use jump tables \
|
||||
# -Wconversion \
|
||||
# -Wsign-conversion \
|
||||
# -Wstrict-overflow=2 \
|
||||
# -Wformat=2 \
|
||||
# -Wcast-qual \
|
||||
|
||||
CC= gcc -std=gnu99
|
||||
CFLAGS= -O2 -Wall -Wextra $(SYSCFLAGS) $(MYCFLAGS)
|
||||
LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS)
|
||||
LIBS= -lm $(SYSLIBS) $(MYLIBS)
|
||||
|
||||
AR= ar rcu
|
||||
# Warnings for gcc, not valid for clang
|
||||
CWARNGCC= \
|
||||
-Wlogical-op \
|
||||
-Wno-aggressive-loop-optimizations \
|
||||
|
||||
|
||||
# The next warnings are neither valid nor needed for C++
|
||||
CWARNSC= -Wdeclaration-after-statement \
|
||||
-Wmissing-prototypes \
|
||||
-Wnested-externs \
|
||||
-Wstrict-prototypes \
|
||||
-Wc++-compat \
|
||||
-Wold-style-definition \
|
||||
|
||||
|
||||
CWARNS= $(CWARNSCPP) $(CWARNSC) $(CWARNGCC)
|
||||
|
||||
# Some useful compiler options for internal tests:
|
||||
# -DLUAI_ASSERT turns on all assertions inside Lua.
|
||||
# -DHARDSTACKTESTS forces a reallocation of the stack at every point where
|
||||
# the stack can be reallocated.
|
||||
# -DHARDMEMTESTS forces a full collection at all points where the collector
|
||||
# can run.
|
||||
# -DEMERGENCYGCTESTS forces an emergency collection at every single allocation.
|
||||
# -DEXTERNMEMCHECK removes internal consistency checking of blocks being
|
||||
# deallocated (useful when an external tool like valgrind does the check).
|
||||
# -DMAXINDEXRK=k limits range of constants in RK instruction operands.
|
||||
# -DLUA_COMPAT_5_3
|
||||
|
||||
# -pg -malign-double
|
||||
# -DLUA_USE_CTYPE -DLUA_USE_APICHECK
|
||||
# ('-ftrapv' for runtime checks of integer overflows)
|
||||
# -fsanitize=undefined -ftrapv -fno-inline
|
||||
# TESTS= -DLUA_USER_H='"ltests.h"' -O0 -g
|
||||
|
||||
|
||||
LOCAL = $(TESTS) $(CWARNS)
|
||||
|
||||
|
||||
# enable Linux goodies
|
||||
MYCFLAGS= $(LOCAL) -std=c99 -DLUA_USE_LINUX -I../../skynet-src
|
||||
MYLDFLAGS= $(LOCAL) -Wl,-E
|
||||
MYLIBS= -ldl
|
||||
|
||||
|
||||
CC= gcc
|
||||
CFLAGS= -Wall -O2 $(MYCFLAGS) -fno-stack-protector -fno-common -march=native
|
||||
AR= ar rc
|
||||
RANLIB= ranlib
|
||||
RM= rm -f
|
||||
UNAME= uname
|
||||
|
||||
SYSCFLAGS=
|
||||
SYSLDFLAGS=
|
||||
SYSLIBS=
|
||||
|
||||
MYCFLAGS=-I../../skynet-src -g
|
||||
MYLDFLAGS=
|
||||
MYLIBS=
|
||||
MYOBJS=
|
||||
# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
|
||||
|
||||
# Special flags for compiler modules; -Os reduces code size.
|
||||
CMCFLAGS=
|
||||
|
||||
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
|
||||
LIBS = -lm
|
||||
|
||||
PLATS= guess aix bsd c89 freebsd generic linux linux-readline macosx mingw posix solaris
|
||||
|
||||
LUA_A= liblua.a
|
||||
CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o
|
||||
LIB_O= lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o linit.o
|
||||
BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS)
|
||||
CORE_T= liblua.a
|
||||
CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \
|
||||
lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \
|
||||
ltm.o lundump.o lvm.o lzio.o ltests.o
|
||||
AUX_O= lauxlib.o
|
||||
LIB_O= lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o lstrlib.o \
|
||||
lutf8lib.o loadlib.o lcorolib.o linit.o
|
||||
|
||||
LUA_T= lua
|
||||
LUA_O= lua.o
|
||||
|
||||
LUAC_T= luac
|
||||
LUAC_O= luac.o
|
||||
|
||||
ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O)
|
||||
ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
|
||||
ALL_A= $(LUA_A)
|
||||
|
||||
# Targets start here.
|
||||
default: $(PLAT)
|
||||
ALL_T= $(CORE_T) $(LUA_T)
|
||||
ALL_O= $(CORE_O) $(LUA_O) $(AUX_O) $(LIB_O)
|
||||
ALL_A= $(CORE_T)
|
||||
|
||||
all: $(ALL_T)
|
||||
touch all
|
||||
|
||||
o: $(ALL_O)
|
||||
|
||||
a: $(ALL_A)
|
||||
|
||||
$(LUA_A): $(BASE_O)
|
||||
$(AR) $@ $(BASE_O)
|
||||
$(CORE_T): $(CORE_O) $(AUX_O) $(LIB_O)
|
||||
$(AR) $@ $?
|
||||
$(RANLIB) $@
|
||||
|
||||
$(LUA_T): $(LUA_O) $(LUA_A)
|
||||
$(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
|
||||
$(LUA_T): $(LUA_O) $(CORE_T)
|
||||
$(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(CORE_T) $(LIBS) $(MYLIBS) $(DL)
|
||||
|
||||
$(LUAC_T): $(LUAC_O) $(LUA_A)
|
||||
$(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
|
||||
|
||||
test:
|
||||
./$(LUA_T) -v
|
||||
|
||||
clean:
|
||||
$(RM) $(ALL_T) $(ALL_O)
|
||||
|
||||
depend:
|
||||
@$(CC) $(CFLAGS) -MM l*.c
|
||||
@$(CC) $(CFLAGS) -MM *.c
|
||||
|
||||
echo:
|
||||
@echo "PLAT= $(PLAT)"
|
||||
@echo "CC= $(CC)"
|
||||
@echo "CFLAGS= $(CFLAGS)"
|
||||
@echo "LDFLAGS= $(LDFLAGS)"
|
||||
@echo "LIBS= $(LIBS)"
|
||||
@echo "AR= $(AR)"
|
||||
@echo "RANLIB= $(RANLIB)"
|
||||
@echo "RM= $(RM)"
|
||||
@echo "UNAME= $(UNAME)"
|
||||
@echo "CC = $(CC)"
|
||||
@echo "CFLAGS = $(CFLAGS)"
|
||||
@echo "AR = $(AR)"
|
||||
@echo "RANLIB = $(RANLIB)"
|
||||
@echo "RM = $(RM)"
|
||||
@echo "MYCFLAGS = $(MYCFLAGS)"
|
||||
@echo "MYLDFLAGS = $(MYLDFLAGS)"
|
||||
@echo "MYLIBS = $(MYLIBS)"
|
||||
@echo "DL = $(DL)"
|
||||
|
||||
# Convenience targets for popular platforms.
|
||||
ALL= all
|
||||
$(ALL_O): makefile ltests.h
|
||||
|
||||
help:
|
||||
@echo "Do 'make PLATFORM' where PLATFORM is one of these:"
|
||||
@echo " $(PLATS)"
|
||||
@echo "See doc/readme.html for complete instructions."
|
||||
|
||||
guess:
|
||||
@echo Guessing `$(UNAME)`
|
||||
@$(MAKE) `$(UNAME)`
|
||||
|
||||
AIX aix:
|
||||
$(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall"
|
||||
|
||||
bsd:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E"
|
||||
|
||||
c89:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_C89" CC="gcc -std=c89"
|
||||
@echo ''
|
||||
@echo '*** C89 does not guarantee 64-bit integers for Lua.'
|
||||
@echo '*** Make sure to compile all external Lua libraries'
|
||||
@echo '*** with LUA_USE_C89 to ensure consistency'
|
||||
@echo ''
|
||||
|
||||
FreeBSD NetBSD OpenBSD freebsd:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE -I/usr/include/edit" SYSLIBS="-Wl,-E -ledit" CC="cc"
|
||||
|
||||
generic: $(ALL)
|
||||
|
||||
Linux linux: linux-noreadline
|
||||
|
||||
linux-noreadline:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl"
|
||||
|
||||
linux-readline:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE" SYSLIBS="-Wl,-E -ldl -lreadline"
|
||||
|
||||
Darwin macos macosx:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX -DLUA_USE_READLINE" SYSLIBS="-lreadline"
|
||||
|
||||
mingw:
|
||||
$(MAKE) "LUA_A=lua54.dll" "LUA_T=lua.exe" \
|
||||
"AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
|
||||
"SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe
|
||||
$(MAKE) "LUAC_T=luac.exe" luac.exe
|
||||
|
||||
posix:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX"
|
||||
|
||||
SunOS solaris:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-ldl"
|
||||
|
||||
# Targets that do not create files (not all makes understand .PHONY).
|
||||
.PHONY: all $(PLATS) help test clean default o a depend echo
|
||||
|
||||
# Compiler modules may use special flags.
|
||||
llex.o:
|
||||
$(CC) $(CFLAGS) $(CMCFLAGS) -c llex.c
|
||||
|
||||
lparser.o:
|
||||
$(CC) $(CFLAGS) $(CMCFLAGS) -c lparser.c
|
||||
|
||||
lcode.o:
|
||||
$(CC) $(CFLAGS) $(CMCFLAGS) -c lcode.c
|
||||
|
||||
# DO NOT DELETE
|
||||
# DO NOT EDIT
|
||||
# automatically made with 'gcc -MM l*.c'
|
||||
|
||||
lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
|
||||
@@ -204,11 +185,13 @@ lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
|
||||
ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
ltests.o: ltests.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||
lobject.h ltm.h lzio.h lmem.h lauxlib.h lcode.h llex.h lopcodes.h \
|
||||
lparser.h lctype.h ldebug.h ldo.h lfunc.h lopnames.h lstring.h lgc.h \
|
||||
ltable.h lualib.h
|
||||
ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
|
||||
lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h ldebug.h lstate.h \
|
||||
lobject.h llimits.h ltm.h lzio.h lmem.h lopcodes.h lopnames.h lundump.h
|
||||
lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
|
||||
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
|
||||
lundump.h
|
||||
Reference in New Issue
Block a user