summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaurnimator <quae@daurnimator.com>2017-05-24 20:44:34 +1000
committerdaurnimator <quae@daurnimator.com>2017-05-27 22:43:18 +1000
commited0518f417a61b32e531f85c434b8024859202cd (patch)
tree39df7684f14774877a6c454d125e23b28cb5dd18
parent1428582c2d88b23f12c87921381796d03b388d9f (diff)
downloadfengari-ed0518f417a61b32e531f85c434b8024859202cd.tar.gz
fengari-ed0518f417a61b32e531f85c434b8024859202cd.tar.bz2
fengari-ed0518f417a61b32e531f85c434b8024859202cd.zip
Modify stack values up to L.top instead of replacing
-rw-r--r--src/lapi.js98
-rw-r--r--src/ldebug.js21
-rw-r--r--src/ldo.js79
-rw-r--r--src/lobject.js28
-rw-r--r--src/lparser.js4
-rw-r--r--src/lstate.js2
-rw-r--r--src/ltm.js18
-rw-r--r--src/lundump.js2
-rw-r--r--src/lvm.js257
9 files changed, 320 insertions, 189 deletions
diff --git a/src/lapi.js b/src/lapi.js
index 9b10d94..a8e0c82 100644
--- a/src/lapi.js
+++ b/src/lapi.js
@@ -112,7 +112,9 @@ const lua_xmove = function(from, to, n) {
from.top -= n;
for (let i = 0; i < n; i++) {
+ to.stack[to.top] = new lobject.TValue();
lobject.setobj2s(to, to.top, from.stack[from.top + i]);
+ delete from.stack[from.top + i];
to.top++;
}
};
@@ -135,21 +137,24 @@ const lua_gettop = function(L) {
};
const lua_pushvalue = function(L, idx) {
- lobject.setobj2s(L, L.top, index2addr(L, idx));
- L.top++;
+ lobject.pushobj2s(L, index2addr(L, idx));
assert(L.top <= L.ci.top, "stack overflow");
};
const lua_settop = function(L, idx) {
let func = L.ci.funcOff;
+ let newtop;
if (idx >= 0) {
assert(idx <= L.stack_last - (func + 1), "new top too large");
- while (L.top < func + 1 + idx)
- L.stack[L.top++] = new TValue(CT.LUA_TNIL, null);
- L.top = func + 1 + idx;
+ newtop = func + 1 + idx;
} else {
assert(-(idx + 1) <= L.top - (func + 1), "invalid new top");
- let newtop = L.top + idx + 1; /* 'subtract' index (index is negative) */
+ newtop = L.top + idx + 1; /* 'subtract' index (index is negative) */
+ }
+ if (L.top < newtop) {
+ while (L.top < newtop)
+ L.stack[L.top++] = new TValue(CT.LUA_TNIL, null);
+ } else {
while (L.top > newtop)
delete L.stack[--L.top];
}
@@ -161,7 +166,8 @@ const lua_pop = function(L, n) {
const reverse = function(L, from, to) {
for (; from < to; from++, to--) {
- let temp = L.stack[from];
+ let fromtv = L.stack[from];
+ let temp = new TValue(fromtv.type, fromtv.value);
lobject.setobjs2s(L, from, to);
lobject.setobj2s(L, to, temp);
}
@@ -188,7 +194,7 @@ const lua_rotate = function(L, idx, n) {
const lua_copy = function(L, fromidx, toidx) {
let from = index2addr(L, fromidx);
- L.stack[index2addr_(L, toidx)] = new TValue(from.type, from.value);
+ L.stack[index2addr_(L, toidx)].setfrom(from);
};
const lua_remove = function(L, idx) {
@@ -239,8 +245,7 @@ const lua_pushlstring = function(L, s, len) {
assert(Array.isArray(s), "lua_pushlstring expects array of byte");
ts = lstring.luaS_bless(L, s.slice(0, len));
}
- lobject.setsvalue2s(L, L.top, ts);
- L.top++;
+ lobject.pushsvalue2s(L, ts);
assert(L.top <= L.ci.top, "stack overflow");
return ts.value;
@@ -249,14 +254,14 @@ const lua_pushlstring = function(L, s, len) {
const lua_pushstring = function (L, s) {
assert(Array.isArray(s) || s === undefined || s === null, "lua_pushstring expects array of byte");
- if (s === undefined || s === null)
- L.stack[L.top] = new TValue(CT.LUA_TNIL, null);
- else {
+ if (s === undefined || s === null) {
+ L.stack[L.top] = new TValue(CT.LUA_TNIL, null)
+ L.top++;
+ } else {
let ts = lstring.luaS_new(L, s);
- lobject.setsvalue2s(L, L.top, ts);
+ lobject.pushsvalue2s(L, ts);
s = ts.getstr(); /* internal copy */
}
- L.top++;
assert(L.top <= L.ci.top, "stack overflow");
return s;
@@ -276,14 +281,14 @@ const lua_pushfstring = function (L, fmt, ...argp) {
const lua_pushliteral = function (L, s) {
assert(typeof s === "string" || s === undefined || s === null, "lua_pushliteral expects a JS string");
- if (s === undefined || s === null)
+ if (s === undefined || s === null) {
L.stack[L.top] = new TValue(CT.LUA_TNIL, null);
- else {
+ L.top++;
+ } else {
let ts = lstring.luaS_newliteral(L, s);
- lobject.setsvalue2s(L, L.top, ts);
+ lobject.pushsvalue2s(L, ts);
s = ts.getstr(); /* internal copy */
}
- L.top++;
assert(L.top <= L.ci.top, "stack overflow");
return s;
@@ -300,16 +305,14 @@ const lua_pushcclosure = function(L, fn, n) {
assert(n <= MAXUPVAL, "upvalue index too large");
let cl = new CClosure(L, fn, n);
-
- L.top -= n;
- while (n--) {
- cl.upvalue[n].setfrom(L.stack[L.top + n])
- delete L.stack[L.top + n];
- }
-
- L.stack[L.top] = new TValue(CT.LUA_TCCL, cl);
+ for (let i=0; i<n; i++)
+ cl.upvalue[i].setfrom(L.stack[L.top - n + i]);
+ for (let i=1; i<n; i++)
+ delete L.stack[--L.top];
+ if (n>0)
+ --L.top;
+ L.stack[L.top].setclCvalue(cl);
}
-
L.top++;
assert(L.top <= L.ci.top, "stack overflow");
};
@@ -357,8 +360,7 @@ const auxsetstr = function(L, t, k) {
let str = lstring.luaS_new(L, k);
assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
- lobject.setsvalue2s(L, L.top, str); /* push 'str' (to make it a TValue) */
- L.top++;
+ lobject.pushsvalue2s(L, str); /* push 'str' (to make it a TValue) */
assert(L.top <= L.ci.top, "stack overflow");
lvm.settable(L, t, L.stack[L.top - 1], L.stack[L.top - 2]);
/* pop value and key */
@@ -435,7 +437,8 @@ const lua_rawset = function(L, idx) {
slot.setfrom(v);
}
ltable.invalidateTMcache(o.value);
- L.top -= 2;
+ delete L.stack[--L.top];
+ delete L.stack[--L.top];
};
const lua_rawseti = function(L, idx, n) {
@@ -458,7 +461,7 @@ const lua_rawsetp = function(L, idx, p) {
let slot = ltable.luaH_set(L, o.value, k);
slot.setfrom(v);
}
- L.top--;
+ delete L.stack[--L.top];
};
/*
@@ -468,8 +471,7 @@ const lua_rawsetp = function(L, idx, p) {
const auxgetstr = function(L, t, k) {
assert(Array.isArray(k), "key must be an array of bytes");
let str = lstring.luaS_new(L, k);
- lobject.setsvalue2s(L, L.top, str);
- L.top++;
+ lobject.pushsvalue2s(L, str);
assert(L.top <= L.ci.top, "stack overflow");
lvm.gettable(L, t, L.stack[L.top - 1], L.top - 1);
return L.stack[L.top - 1].ttnov();
@@ -478,8 +480,7 @@ const auxgetstr = function(L, t, k) {
const lua_rawgeti = function(L, idx, n) {
let t = index2addr(L, idx);
assert(t.ttistable(), "table expected");
- lobject.setobj2s(L, L.top, ltable.luaH_getint(t.value, n));
- L.top++;
+ lobject.pushobj2s(L, ltable.luaH_getint(t.value, n));
assert(L.top <= L.ci.top, "stack overflow");
return L.stack[L.top - 1].ttnov();
};
@@ -488,8 +489,7 @@ const lua_rawgetp = function(L, idx, p) {
let t = index2addr(L, idx);
assert(t.ttistable(), "table expected");
let k = new TValue(CT.LUA_TLIGHTUSERDATA, p);
- lobject.setobj2s(L, L.top, ltable.luaH_get(L, t.value, k));
- L.top++;
+ lobject.pushobj2s(L, ltable.luaH_get(L, t.value, k));
assert(L.top <= L.ci.top, "stack overflow");
return L.stack[L.top - 1].ttnov();
};
@@ -550,8 +550,7 @@ const lua_getupvalue = function(L, funcindex, n) {
if (up) {
let name = up.name;
let val = up.val;
- lobject.setobj2s(L, L.top, val);
- L.top++;
+ lobject.pushobj2s(L, val);
assert(L.top <= L.ci.top, "stack overflow");
return name;
}
@@ -565,8 +564,8 @@ const lua_setupvalue = function(L, funcindex, n) {
if (aux) {
let name = aux.name;
let val = aux.val;
- L.top--;
- val.setfrom(L.stack[L.top]);
+ val.setfrom(L.stack[L.top-1]);
+ delete L.stack[--L.top];
return name;
}
return null;
@@ -898,13 +897,12 @@ const lua_arith = function(L, op) {
assert(2 < L.top - L.ci.funcOff, "not enough elements in the stack"); /* all other operations expect two operands */
else { /* for unary operations, add fake 2nd operand */
assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
- lobject.setobjs2s(L, L.top, L.top - 1);
- L.top++;
+ lobject.pushobj2s(L, L.stack[L.top-1]);
assert(L.top <= L.ci.top, "stack overflow");
}
/* first operand at top - 2, second at top - 1; result go to top - 2 */
lobject.luaO_arith(L, op, L.stack[L.top - 2], L.stack[L.top - 1], L.stack[L.top - 2]);
- L.top--; /* remove second operand */
+ delete L.stack[--L.top]; /* remove second operand */
};
/*
@@ -1037,13 +1035,15 @@ const lua_error = function(L) {
const lua_next = function(L, idx) {
let t = index2addr(L, idx);
assert(t.ttistable(), "table expected");
+ L.stack[L.top] = new TValue();
let more = ltable.luaH_next(L, t.value, L.top - 1);
if (more) {
L.top++;
assert(L.top <= L.ci.top, "stack overflow");
return 1;
} else {
- L.top--;
+ delete L.stack[L.top];
+ delete L.stack[--L.top];
return 0;
}
};
@@ -1053,15 +1053,15 @@ const lua_concat = function(L, n) {
if (n >= 2)
lvm.luaV_concat(L, n);
else if (n === 0) {
- lobject.setsvalue2s(L, L.top, lstring.luaS_bless(L, []));
- L.top++;
+ lobject.pushsvalue2s(L, lstring.luaS_bless(L, []));
assert(L.top <= L.ci.top, "stack overflow");
}
};
const lua_len = function(L, idx) {
let t = index2addr(L, idx);
- lvm.luaV_objlen(L, L.top, t);
+ L.stack[L.top] = new TValue();
+ lvm.luaV_objlen(L, L.stack[L.top], t);
L.top++;
assert(L.top <= L.ci.top, "stack overflow");
};
diff --git a/src/ldebug.js b/src/ldebug.js
index 2a9ada6..3636a06 100644
--- a/src/ldebug.js
+++ b/src/ldebug.js
@@ -140,8 +140,7 @@ const lua_getlocal = function(L, ar, n) {
let local = findlocal(L, ar.i_ci, n);
if (local) {
name = local.name;
- lobject.setobj2s(L, L.top, L.stack[local.pos]);
- L.top++;
+ lobject.pushobj2s(L, L.stack[local.pos]);
assert(L.top <= L.ci.top, "stack overflow");
} else {
name = null;
@@ -265,27 +264,24 @@ const auxgetinfo = function(L, what, ar, f, ci) {
};
const lua_getinfo = function(L, what, ar) {
- let status, cl, ci, func, funcOff;
+ let status, cl, ci, func;
swapextra(L);
if (what[0] === '>'.charCodeAt(0)) {
ci = null;
- funcOff = L.top - 1;
- func = L.stack[funcOff];
+ func = L.stack[L.top - 1];
assert(L, func.ttisfunction(), "function expected");
what = what.slice(1); /* skip the '>' */
L.top--; /* pop function */
} else {
ci = ar.i_ci;
func = ci.func;
- funcOff = ci.funcOff;
assert(ci.func.ttisfunction());
}
cl = func.ttisclosure() ? func.value : null;
status = auxgetinfo(L, what, ar, cl, ci);
if (what.indexOf('f'.charCodeAt(0)) >= 0) {
- lobject.setobjs2s(L, L.top, funcOff);
- L.top++;
+ lobject.pushobj2s(L, func);
assert(L.top <= L.ci.top, "stack overflow");
}
@@ -595,9 +591,8 @@ const luaG_runerror = function(L, fmt, ...argp) {
const luaG_errormsg = function(L) {
if (L.errfunc !== 0) { /* is there an error handling function? */
let errfunc = L.errfunc;
- lobject.setobjs2s(L, L.top, L.top - 1); /* move argument */
- lobject.setobjs2s(L, L.top - 1, errfunc); /* push function */
- L.top++;
+ lobject.pushobj2s(L, L.stack[L.top - 1]); /* move argument */
+ lobject.setobjs2s(L, L.top - 2, errfunc); /* push function */
ldo.luaD_callnoyield(L, L.top - 2, 1);
}
@@ -643,8 +638,8 @@ const luaG_traceexec = function(L) {
L.hookcount = 1; /* undo decrement to zero */
ci.l_savedpc--; /* undo increment (resume will increment it again) */
ci.callstatus |= lstate.CIST_HOOKYIELD; /* mark that it yielded */
- ci.func = L.stack[L.top - 1]; /* protect stack below results */
- ci.funcOff = L.top - 1;
+ ci.funcOff = L.top - 1; /* protect stack below results */
+ ci.func = L.stack[ci.funcOff];
ldo.luaD_throw(L, TS.LUA_YIELD);
}
};
diff --git a/src/ldo.js b/src/ldo.js
index b32e404..464d373 100644
--- a/src/ldo.js
+++ b/src/ldo.js
@@ -36,7 +36,13 @@ const seterrorobj = function(L, errcode, oldtop) {
}
}
- L.top = oldtop + 1;
+ if (L.top < oldtop + 1) {
+ while (L.top < oldtop + 1)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > oldtop + 1)
+ delete L.stack[--L.top];
+ }
};
const ERRORSTACKSIZE = luaconf.LUAI_MAXSTACK + 200;
@@ -94,8 +100,8 @@ const luaD_shrinkstack = function(L) {
};
const luaD_inctop = function(L) {
- luaD_checkstack(L, 1);
- L.top++;
+ luaD_checkstack(L, 1);
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
};
/*
@@ -151,7 +157,14 @@ const luaD_precall = function(L, off, nresults) {
ci.nresults = nresults;
ci.func = func;
ci.l_base = base;
- L.top = ci.top = base + fsize;
+ ci.top = base + fsize;
+ if (L.top < ci.top) {
+ while (L.top < ci.top)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > ci.top)
+ delete L.stack[--L.top];
+ }
ci.l_code = p.code;
ci.l_savedpc = 0;
ci.callstatus = lstate.CIST_LUA;
@@ -159,6 +172,7 @@ const luaD_precall = function(L, off, nresults) {
return false;
}
default:
+ luaD_checkstack(L, 1);
tryfuncTM(L, off, func);
return luaD_precall(L, off, nresults);
}
@@ -185,33 +199,42 @@ const moveresults = function(L, firstResult, res, nres, wanted) {
break;
case 1: {
if (nres === 0)
- L.stack[firstResult] = lobject.luaO_nilobject;
- lobject.setobjs2s(L, res, firstResult); /* move it to proper place */
+ L.stack[res].setnilvalue();
+ else {
+ lobject.setobjs2s(L, res, firstResult); /* move it to proper place */
+ }
break;
}
case defs.LUA_MULTRET: {
for (let i = 0; i < nres; i++)
lobject.setobjs2s(L, res + i, firstResult + i);
+ for (let i=L.top; i>=(res + nres); i--)
+ delete L.stack[i];
L.top = res + nres;
return false;
}
default: {
let i;
if (wanted <= nres) {
- for (i = 0; i < wanted; i++) {
+ for (i = 0; i < wanted; i++)
lobject.setobjs2s(L, res + i, firstResult + i);
- }
} else {
for (i = 0; i < nres; i++)
lobject.setobjs2s(L, res + i, firstResult + i);
- for (; i < wanted; i++)
- L.stack[res + i] = new lobject.TValue(CT.LUA_TNIL, null);
+ for (; i < wanted; i++) {
+ if (res+i >= L.top)
+ L.stack[res + i] = new lobject.TValue(CT.LUAT_NIL, null);
+ else
+ L.stack[res + i].setnilvalue();
+ }
}
break;
}
}
-
- L.top = res + wanted; /* top points after the last result */
+ let newtop = res + wanted; /* top points after the last result */
+ for (let i=L.top; i>=newtop; i--)
+ delete L.stack[i];
+ L.top = newtop;
return true;
};
@@ -239,7 +262,13 @@ const luaD_hook = function(L, event, line) {
assert(!L.allowhook);
L.allowhook = 1;
ci.top = ci_top;
- L.top = top;
+ if (L.top < top) {
+ while (L.top < top)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > top)
+ delete L.stack[--L.top];
+ }
ci.callstatus &= ~lstate.CIST_HOOKED;
}
};
@@ -252,8 +281,8 @@ const adjust_varargs = function(L, p, actual) {
let i;
for (i = 0; i < nfixargs && i < actual; i++) {
- lobject.setobjs2s(L, L.top++, fixed + i);
- L.stack[fixed + i] = new lobject.TValue(CT.LUA_TNIL, null);
+ lobject.pushobj2s(L, L.stack[fixed + i]);
+ L.stack[fixed + i].setnilvalue();
}
for (; i < nfixargs; i++)
@@ -267,9 +296,9 @@ const tryfuncTM = function(L, off, func) {
if (!tm.ttisfunction(tm))
ldebug.luaG_typeerror(L, func, defs.to_luastring("call", true));
/* Open a hole inside the stack at 'func' */
- for (let p = L.top; p > off; p--)
- lobject.setobjs2s(L, p, p-1);
- L.top++; /* slot ensured by caller */
+ lobject.pushobj2s(L, L.stack[L.top-1]); /* push top of stack again */
+ for (let p = L.top-2; p > off; p--)
+ lobject.setobjs2s(L, p, p-1); /* move other items up one */
lobject.setobj2s(L, off, tm); /* tag method is the new function to be called */
};
@@ -464,10 +493,16 @@ const recover = function(L, status) {
** coroutine error handler and should not kill the coroutine.)
*/
const resume_error = function(L, msg, narg) {
- L.top -= narg; /* remove args from the stack */
- lobject.setsvalue2s(L, L.top, lstring.luaS_newliteral(L, msg)); /* push error message */
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ let ts = lstring.luaS_newliteral(L, msg);
+ if (narg === 0) {
+ lobject.pushsvalue2s(L, ts);
+ assert(L.top <= L.ci.top, "stack overflow");
+ } else {
+ /* remove args from the stack */
+ for (let i=1; i<narg; i++)
+ delete L.stack[--L.top];
+ lobject.setsvalue2s(L, L.top-1, ts); /* push error message */
+ }
return TS.LUA_ERRRUN;
};
diff --git a/src/lobject.js b/src/lobject.js
index aec7109..f395036 100644
--- a/src/lobject.js
+++ b/src/lobject.js
@@ -220,16 +220,22 @@ class TValue {
}
+const pushobj2s = function(L, tv) {
+ L.stack[L.top++] = new TValue(tv.type, tv.value);
+};
+const pushsvalue2s = function(L, ts) {
+ L.stack[L.top++] = new TValue(CT.LUA_TLNGSTR, ts);
+};
/* from stack to (same) stack */
const setobjs2s = function(L, newidx, oldidx) {
- L.stack[newidx] = L.stack[oldidx];
+ L.stack[newidx].setfrom(L.stack[oldidx]);
};
/* to stack (not from same stack) */
const setobj2s = function(L, newidx, oldtv) {
- L.stack[newidx] = new TValue(oldtv.type, oldtv.value);
+ L.stack[newidx].setfrom(oldtv);
};
const setsvalue2s = function(L, newidx, ts) {
- L.stack[newidx] = new TValue(CT.LUA_TLNGSTR, ts);
+ L.stack[newidx].setsvalue(ts);
};
const luaO_nilobject = new TValue(CT.LUA_TNIL, null);
@@ -528,8 +534,8 @@ const luaO_tostring = function(L, obj) {
};
const pushstr = function(L, str) {
- setsvalue2s(L, L.top, lstring.luaS_new(L, str));
ldo.luaD_inctop(L);
+ setsvalue2s(L, L.top-1, lstring.luaS_new(L, str));
};
const luaO_pushvfstring = function(L, fmt, argp) {
@@ -659,8 +665,7 @@ const luaO_arith = function(L, op, p1, p2, res) {
case defs.LUA_OPBNOT: { /* operate only on integers */
let i1, i2;
if ((i1 = lvm.tointeger(p1)) !== false && (i2 = lvm.tointeger(p2)) !== false) {
- res.type = CT.LUA_TNUMINT;
- res.value = intarith(L, op, i1, i2);
+ res.setivalue(intarith(L, op, i1, i2));
return;
}
else break; /* go to the end */
@@ -668,8 +673,7 @@ const luaO_arith = function(L, op, p1, p2, res) {
case defs.LUA_OPDIV: case defs.LUA_OPPOW: { /* operate only on floats */
let n1, n2;
if ((n1 = lvm.tonumber(p1)) !== false && (n2 = lvm.tonumber(p2)) !== false) {
- res.type = CT.LUA_TNUMFLT;
- res.value = numarith(L, op, n1, n2);
+ res.setfltvalue(numarith(L, op, n1, n2));
return;
}
else break; /* go to the end */
@@ -677,13 +681,11 @@ const luaO_arith = function(L, op, p1, p2, res) {
default: { /* other operations */
let n1, n2;
if (p1.ttisinteger() && p2.ttisinteger()) {
- res.type = CT.LUA_TNUMINT;
- res.value = intarith(L, op, p1.value, p2.value);
+ res.setivalue(intarith(L, op, p1.value, p2.value));
return;
}
else if ((n1 = lvm.tonumber(p1)) !== false && (n2 = lvm.tonumber(p2)) !== false) {
- res.type = CT.LUA_TNUMFLT;
- res.value = numarith(L, op, n1, n2);
+ res.setfltvalue(numarith(L, op, n1, n2));
return;
}
else break; /* go to the end */
@@ -714,6 +716,8 @@ module.exports.luaO_tostring = luaO_tostring;
module.exports.luaO_utf8desc = luaO_utf8desc;
module.exports.luaO_utf8esc = luaO_utf8esc;
module.exports.numarith = numarith;
+module.exports.pushobj2s = pushobj2s;
+module.exports.pushsvalue2s = pushsvalue2s;
module.exports.setobjs2s = setobjs2s;
module.exports.setobj2s = setobj2s;
module.exports.setsvalue2s = setsvalue2s;
diff --git a/src/lparser.js b/src/lparser.js
index 96bad67..0079141 100644
--- a/src/lparser.js
+++ b/src/lparser.js
@@ -1568,7 +1568,7 @@ const luaY_parser = function(L, z, buff, dyd, name, firstchar) {
L.stack[L.top-1].setclLvalue(cl);
lexstate.h = ltable.luaH_new(L); /* create table for scanner */
ldo.luaD_inctop(L);
- L.stack[L.top-1] = new TValue(defs.CT.LUA_TTABLE, lexstate.h);
+ L.stack[L.top-1].sethvalue(lexstate.h);
funcstate.f = cl.p = new Proto(L);
funcstate.f.source = lstring.luaS_new(L, name);
lexstate.buff = buff;
@@ -1579,7 +1579,7 @@ const luaY_parser = function(L, z, buff, dyd, name, firstchar) {
assert(!funcstate.prev && funcstate.nups === 1 && !lexstate.fs);
/* all scopes should be correctly finished */
assert(dyd.actvar.n === 0 && dyd.gt.n === 0 && dyd.label.n === 0);
- L.top--; /* remove scanner's table */
+ delete L.stack[--L.top]; /* remove scanner's table */
return cl; /* closure is on the stack, too */
};
diff --git a/src/lstate.js b/src/lstate.js
index b7a11bc..9046adf 100644
--- a/src/lstate.js
+++ b/src/lstate.js
@@ -109,8 +109,8 @@ const stack_init = function(L1, L) {
let ci = L1.base_ci;
ci.next = ci.previous = null;
ci.callstatus = 0;
- ci.func = L1.stack[L1.top];
ci.funcOff = L1.top;
+ ci.func = L1.stack[L1.top];
L1.stack[L1.top++] = new lobject.TValue(CT.LUA_TNIL, null);
ci.top = L1.top + defs.LUA_MINSTACK;
L1.ci = ci;
diff --git a/src/ltm.js b/src/ltm.js
index c3efc1e..8f4908c 100644
--- a/src/ltm.js
+++ b/src/ltm.js
@@ -110,13 +110,12 @@ const luaT_objtypename = function(L, o) {
const luaT_callTM = function(L, f, p1, p2, p3, hasres) {
let func = L.top;
- lobject.setobj2s(L, L.top, f); /* push function (assume EXTRA_STACK) */
- lobject.setobj2s(L, L.top + 1, p1); /* 1st argument */
- lobject.setobj2s(L, L.top + 2, p2); /* 2nd argument */
- L.top += 3;
+ lobject.pushobj2s(L, f); /* push function (assume EXTRA_STACK) */
+ lobject.pushobj2s(L, p1); /* 1st argument */
+ lobject.pushobj2s(L, p2); /* 2nd argument */
if (!hasres) /* no result? 'p3' is third argument */
- lobject.setobj2s(L, L.top++, p3); /* 3rd argument */
+ lobject.pushobj2s(L, p3); /* 3rd argument */
if (L.ci.callstatus & lstate.CIST_LUA)
ldo.luaD_call(L, func, hasres);
@@ -124,7 +123,9 @@ const luaT_callTM = function(L, f, p1, p2, p3, hasres) {
ldo.luaD_callnoyield(L, func, hasres);
if (hasres) { /* if has result, move it to its place */
- lobject.setobjs2s(L, p3, --L.top);
+ let tv = L.stack[L.top-1];
+ delete L.stack[--L.top];
+ p3.setfrom(tv);
}
};
@@ -158,10 +159,11 @@ const luaT_trybinTM = function(L, p1, p2, res, event) {
};
const luaT_callorderTM = function(L, p1, p2, event) {
- if (!luaT_callbinTM(L, p1, p2, L.top, event))
+ let res = new lobject.TValue(CT.LUA_TNIL, null);
+ if (!luaT_callbinTM(L, p1, p2, res, event))
return -1;
else
- return !L.stack[L.top].l_isfalse() ? 1 : 0;
+ return res.l_isfalse() ? 0 : 1;
};
const fasttm = function(l, et, e) {
diff --git a/src/lundump.js b/src/lundump.js
index 5686430..3f61cb6 100644
--- a/src/lundump.js
+++ b/src/lundump.js
@@ -265,8 +265,8 @@ const luaU_undump = function(L, Z, name) {
let S = new BytecodeParser(L, Z, name);
S.checkHeader();
let cl = lfunc.luaF_newLclosure(L, S.readByte());
- L.stack[L.top].setclLvalue(cl);
ldo.luaD_inctop(L);
+ L.stack[L.top-1].setclLvalue(cl);
cl.p = new lfunc.Proto(L);
S.readFunction(cl.p, null);
assert(cl.nupvalues === cl.p.upvalues.length);
diff --git a/src/lvm.js b/src/lvm.js
index e308807..724f689 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -34,12 +34,13 @@ const luaV_finishOp = function(L) {
case OCi.OP_MOD: case OCi.OP_POW:
case OCi.OP_UNM: case OCi.OP_BNOT: case OCi.OP_LEN:
case OCi.OP_GETTABUP: case OCi.OP_GETTABLE: case OCi.OP_SELF: {
- lobject.setobjs2s(L, base + inst.A, --L.top);
+ lobject.setobjs2s(L, base + inst.A, L.top-1);
+ delete L.stack[--L.top];
break;
}
case OCi.OP_LE: case OCi.OP_LT: case OCi.OP_EQ: {
let res = !L.stack[L.top - 1].l_isfalse();
- L.top--;
+ delete L.stack[--L.top];
if (ci.callstatus & lstate.CIST_LEQ) { /* "<=" using "<" instead? */
assert(op === OCi.OP_LE);
ci.callstatus ^= lstate.CIST_LEQ; /* clear mark */
@@ -61,17 +62,39 @@ const luaV_finishOp = function(L) {
}
/* move final result to final position */
lobject.setobjs2s(L, ci.l_base + inst.A, L.top - 1);
- L.top = ci.top; /* restore top */
+ /* restore top */
+ if (L.top < ci.top) {
+ while (L.top < ci.top)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > ci.top)
+ delete L.stack[--L.top];
+ }
break;
}
case OCi.OP_TFORCALL: {
assert(ci.l_code[ci.l_savedpc].opcode === OCi.OP_TFORLOOP);
- L.top = ci.top; /* correct top */
+ /* correct top */
+ if (L.top < ci.top) {
+ while (L.top < ci.top)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > ci.top)
+ delete L.stack[--L.top];
+ }
break;
}
case OCi.OP_CALL: {
- if (inst.C - 1 >= 0) /* nresults >= 0? */
- L.top = ci.top; /* adjust results */
+ if (inst.C - 1 >= 0) { /* nresults >= 0? */
+ /* adjust results */
+ if (L.top < ci.top) {
+ while (L.top < ci.top)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > ci.top)
+ delete L.stack[--L.top];
+ }
+ }
break;
}
}
@@ -135,7 +158,7 @@ const luaV_execute = function(L) {
break;
}
case OCi.OP_LOADBOOL: {
- L.stack[ra] = new lobject.TValue(CT.LUA_TBOOLEAN, i.B !== 0);
+ L.stack[ra].setbvalue(i.B !== 0);
if (i.C !== 0)
ci.l_savedpc++; /* skip next instruction (if C) */
@@ -144,7 +167,7 @@ const luaV_execute = function(L) {
}
case OCi.OP_LOADNIL: {
for (let j = 0; j <= i.B; j++)
- L.stack[ra + j] = new lobject.TValue(CT.LUA_TNIL, null);
+ L.stack[ra + j].setnilvalue();
break;
}
case OCi.OP_GETUPVAL: {
@@ -155,7 +178,7 @@ const luaV_execute = function(L) {
case OCi.OP_SETUPVAL: {
let uv = cl.upvals[i.B];
if (uv.isopen()) {
- uv.L.stack[uv.v] = L.stack[ra];
+ uv.L.stack[uv.v].setfrom(L.stack[ra]);
} else {
uv.value.setfrom(L.stack[ra]);
}
@@ -192,7 +215,7 @@ const luaV_execute = function(L) {
break;
}
case OCi.OP_NEWTABLE: {
- L.stack[ra] = new lobject.TValue(CT.LUA_TTABLE, ltable.luaH_new(L));
+ L.stack[ra].sethvalue(ltable.luaH_new(L));
break;
}
case OCi.OP_SELF: {
@@ -210,11 +233,11 @@ const luaV_execute = function(L) {
let numberop2 = tonumber(op2);
if (op1.ttisinteger() && op2.ttisinteger()) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, (op1.value + op2.value)|0);
+ L.stack[ra].setivalue((op1.value + op2.value)|0);
} else if (numberop1 !== false && numberop2 !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMFLT, numberop1 + numberop2);
+ L.stack[ra].setfltvalue(numberop1 + numberop2);
} else {
- ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_ADD);
+ ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_ADD);
}
break;
}
@@ -225,11 +248,11 @@ const luaV_execute = function(L) {
let numberop2 = tonumber(op2);
if (op1.ttisinteger() && op2.ttisinteger()) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, (op1.value - op2.value)|0);
+ L.stack[ra].setivalue((op1.value - op2.value)|0);
} else if (numberop1 !== false && numberop2 !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMFLT, numberop1 - numberop2);
+ L.stack[ra].setfltvalue(numberop1 - numberop2);
} else {
- ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_SUB);
+ ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_SUB);
}
break;
}
@@ -240,11 +263,11 @@ const luaV_execute = function(L) {
let numberop2 = tonumber(op2);
if (op1.ttisinteger() && op2.ttisinteger()) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, Math.imul(op1.value, op2.value));
+ L.stack[ra].setivalue(Math.imul(op1.value, op2.value));
} else if (numberop1 !== false && numberop2 !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMFLT, numberop1 * numberop2);
+ L.stack[ra].setfltvalue(numberop1 * numberop2);
} else {
- ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_MUL);
+ ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_MUL);
}
break;
}
@@ -255,11 +278,11 @@ const luaV_execute = function(L) {
let numberop2 = tonumber(op2);
if (op1.ttisinteger() && op2.ttisinteger()) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, luaV_mod(L, op1.value, op2.value));
+ L.stack[ra].setivalue(luaV_mod(L, op1.value, op2.value));
} else if (numberop1 !== false && numberop2 !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMFLT, llimit.luai_nummod(L, numberop1, numberop2));
+ L.stack[ra].setfltvalue(llimit.luai_nummod(L, numberop1, numberop2));
} else {
- ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_MOD);
+ ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_MOD);
}
break;
}
@@ -270,9 +293,9 @@ const luaV_execute = function(L) {
let numberop2 = tonumber(op2);
if (numberop1 !== false && numberop2 !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMFLT, Math.pow(numberop1, numberop2));
+ L.stack[ra].setfltvalue(Math.pow(numberop1, numberop2));
} else {
- ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_POW);
+ ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_POW);
}
break;
}
@@ -283,9 +306,9 @@ const luaV_execute = function(L) {
let numberop2 = tonumber(op2);
if (numberop1 !== false && numberop2 !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMFLT, numberop1 / numberop2);
+ L.stack[ra].setfltvalue(numberop1 / numberop2);
} else {
- ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_DIV);
+ ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_DIV);
}
break;
}
@@ -296,11 +319,11 @@ const luaV_execute = function(L) {
let numberop2 = tonumber(op2);
if (op1.ttisinteger() && op2.ttisinteger()) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, luaV_div(L, op1.value, op2.value));
+ L.stack[ra].setivalue(luaV_div(L, op1.value, op2.value));
} else if (numberop1 !== false && numberop2 !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMFLT, Math.floor(numberop1 / numberop2));
+ L.stack[ra].setfltvalue(Math.floor(numberop1 / numberop2));
} else {
- ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_IDIV);
+ ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_IDIV);
}
break;
}
@@ -311,9 +334,9 @@ const luaV_execute = function(L) {
let numberop2 = tointeger(op2);
if (numberop1 !== false && numberop2 !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, (numberop1 & numberop2));
+ L.stack[ra].setivalue(numberop1 & numberop2);
} else {
- ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_BAND);
+ ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_BAND);
}
break;
}
@@ -324,9 +347,9 @@ const luaV_execute = function(L) {
let numberop2 = tointeger(op2);
if (numberop1 !== false && numberop2 !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, (numberop1 | numberop2));
+ L.stack[ra].setivalue(numberop1 | numberop2);
} else {
- ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_BOR);
+ ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_BOR);
}
break;
}
@@ -337,9 +360,9 @@ const luaV_execute = function(L) {
let numberop2 = tointeger(op2);
if (numberop1 !== false && numberop2 !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, (numberop1 ^ numberop2));
+ L.stack[ra].setivalue(numberop1 ^ numberop2);
} else {
- ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_BXOR);
+ ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_BXOR);
}
break;
}
@@ -350,9 +373,9 @@ const luaV_execute = function(L) {
let numberop2 = tointeger(op2);
if (numberop1 !== false && numberop2 !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, luaV_shiftl(numberop1, numberop2));
+ L.stack[ra].setivalue(luaV_shiftl(numberop1, numberop2));
} else {
- ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_SHL);
+ ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_SHL);
}
break;
}
@@ -363,9 +386,9 @@ const luaV_execute = function(L) {
let numberop2 = tointeger(op2);
if (numberop1 !== false && numberop2 !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, luaV_shiftl(numberop1, -numberop2));
+ L.stack[ra].setivalue(luaV_shiftl(numberop1, -numberop2));
} else {
- ltm.luaT_trybinTM(L, op1, op2, ra, ltm.TMS.TM_SHR);
+ ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_SHR);
}
break;
}
@@ -374,11 +397,11 @@ const luaV_execute = function(L) {
let numberop = tonumber(op);
if (op.ttisinteger()) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, (-op.value)|0);
+ L.stack[ra].setivalue((-op.value)|0);
} else if (numberop !== false) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMFLT, -numberop);
+ L.stack[ra].setfltvalue(-numberop);
} else {
- ltm.luaT_trybinTM(L, op, op, ra, ltm.TMS.TM_UNM);
+ ltm.luaT_trybinTM(L, op, op, L.stack[ra], ltm.TMS.TM_UNM);
}
break;
}
@@ -386,19 +409,19 @@ const luaV_execute = function(L) {
let op = L.stack[RB(L, base, i)];
if (op.ttisinteger()) {
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, ~op.value);
+ L.stack[ra].setivalue(~op.value);
} else {
- ltm.luaT_trybinTM(L, op, op, ra, ltm.TMS.TM_BNOT);
+ ltm.luaT_trybinTM(L, op, op, L.stack[ra], ltm.TMS.TM_BNOT);
}
break;
}
case OCi.OP_NOT: {
let op = L.stack[RB(L, base, i)];
- L.stack[ra] = new lobject.TValue(CT.LUA_TBOOLEAN, op.l_isfalse());
+ L.stack[ra].setbvalue(op.l_isfalse());
break;
}
case OCi.OP_LEN: {
- luaV_objlen(L, ra, L.stack[RB(L, base, i)]);
+ luaV_objlen(L, L.stack[ra], L.stack[RB(L, base, i)]);
break;
}
case OCi.OP_CONCAT: {
@@ -408,7 +431,14 @@ const luaV_execute = function(L) {
luaV_concat(L, c - b + 1);
let rb = base + b;
lobject.setobjs2s(L, ra, rb);
- L.top = ci.top; /* restore top */
+ /* restore top */
+ if (L.top < ci.top) {
+ while (L.top < ci.top)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > ci.top)
+ delete L.stack[--L.top];
+ }
break;
}
case OCi.OP_JMP: {
@@ -458,12 +488,26 @@ const luaV_execute = function(L) {
let b = i.B;
let nresults = i.C - 1;
- if (b !== 0)
- L.top = ra+b;
+ if (b !== 0) {
+ if (L.top < ra+b) {
+ while (L.top < ra+b)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > ra+b)
+ delete L.stack[--L.top];
+ }
+ }
if (ldo.luaD_precall(L, ra, nresults)) {
- if (nresults >= 0)
- L.top = ci.top;
+ if (nresults >= 0) {
+ if (L.top < ci.top) {
+ while (L.top < ci.top)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > ci.top)
+ delete L.stack[--L.top];
+ }
+ }
} else {
ci = L.ci;
continue newframe;
@@ -472,7 +516,16 @@ const luaV_execute = function(L) {
break;
}
case OCi.OP_TAILCALL: {
- if (i.B !== 0) L.top = ra + i.B;
+ let b = i.B;
+ if (b !== 0) {
+ if (L.top < ra+b) {
+ while (L.top < ra+b)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > ra+b)
+ delete L.stack[--L.top];
+ }
+ } /* else previous instruction set top */
if (ldo.luaD_precall(L, ra, LUA_MULTRET)) { // JS function
} else {
/* tail call: put called frame (n) in place of caller one (o) */
@@ -485,9 +538,15 @@ const luaV_execute = function(L) {
if (cl.p.p.length > 0) lfunc.luaF_close(L, oci.l_base);
for (let aux = 0; nfuncOff + aux < lim; aux++)
lobject.setobjs2s(L, ofuncOff + aux, nfuncOff + aux);
- oci.func = nci.func;
oci.l_base = ofuncOff + (nci.l_base - nfuncOff);
- oci.top = L.top = ofuncOff + (L.top - nfuncOff);
+ oci.top = ofuncOff + (L.top - nfuncOff);
+ if (L.top < nci.top) {
+ while (L.top < oci.top)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > oci.top)
+ delete L.stack[--L.top];
+ }
oci.l_code = nci.l_code;
oci.l_savedpc = nci.l_savedpc;
oci.callstatus |= lstate.CIST_TAIL;
@@ -506,10 +565,19 @@ const luaV_execute = function(L) {
if (ci.callstatus & lstate.CIST_FRESH)
return; /* external invocation: return */
-
+ /* invocation via reentry: continue execution */
ci = L.ci;
- if (b) L.top = ci.top;
-
+ if (b) {
+ if (L.top < ci.top) {
+ while (L.top < ci.top)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > ci.top)
+ delete L.stack[--L.top];
+ }
+ }
+ assert(ci.callstatus & lstate.CIST_LUA);
+ assert(ci.l_code[ci.l_savedpc - 1].opcode === OCi.OP_CALL);
continue newframe;
}
case OCi.OP_FORLOOP: {
@@ -521,7 +589,7 @@ const luaV_execute = function(L) {
if (0 < step ? idx <= limit : limit <= idx) {
ci.l_savedpc += i.sBx;
L.stack[ra].chgivalue(idx); /* update internal index... */
- L.stack[ra + 3] = new lobject.TValue(CT.LUA_TNUMINT, idx);
+ L.stack[ra + 3].setivalue(idx);
}
} else { /* floating loop */
let step = L.stack[ra + 2].value;
@@ -531,7 +599,7 @@ const luaV_execute = function(L) {
if (0 < step ? idx <= limit : limit <= idx) {
ci.l_savedpc += i.sBx;
L.stack[ra].chgfltvalue(idx); /* update internal index... */
- L.stack[ra + 3] = new lobject.TValue(CT.LUA_TNUMFLT, idx);
+ L.stack[ra + 3].setfltvalue(idx);
}
}
break;
@@ -550,13 +618,13 @@ const luaV_execute = function(L) {
let nlimit, nstep, ninit;
if ((nlimit = tonumber(plimit)) === false)
ldebug.luaG_runerror(L, defs.to_luastring("'for' limit must be a number", true));
- L.stack[ra + 1] = new lobject.TValue(CT.LUA_TNUMFLT, nlimit);
+ L.stack[ra + 1].setfltvalue(nlimit);
if ((nstep = tonumber(pstep)) === false)
ldebug.luaG_runerror(L, defs.to_luastring("'for' step must be a number", true));
- L.stack[ra + 2] = new lobject.TValue(CT.LUA_TNUMFLT, nstep);
+ L.stack[ra + 2].setfltvalue(nstep);
if ((ninit = tonumber(init)) === false)
ldebug.luaG_runerror(L, defs.to_luastring("'for' initial value must be a number", true));
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMFLT, ninit - nstep);
+ L.stack[ra].setfltvalue(ninit - nstep);
}
ci.l_savedpc += i.sBx;
@@ -567,15 +635,28 @@ const luaV_execute = function(L) {
lobject.setobjs2s(L, cb+2, ra+2);
lobject.setobjs2s(L, cb+1, ra+1);
lobject.setobjs2s(L, cb, ra);
- L.top = cb + 3; /* func. + 2 args (state and index) */
+ /* func. + 2 args (state and index) */
+ if (L.top < cb + 3) {
+ while (L.top < cb + 3)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > cb + 3)
+ delete L.stack[--L.top];
+ }
ldo.luaD_call(L, cb, i.C);
+ if (L.top < ci.top) {
+ while (L.top < ci.top)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > ci.top)
+ delete L.stack[--L.top];
+ }
/* go straight to OP_TFORLOOP */
- L.top = ci.top;
i = ci.l_code[ci.l_savedpc++];
ra = RA(L, base, i);
assert(i.opcode === OCi.OP_TFORLOOP);
- /* fall through */
}
+ /* fall through */
case OCi.OP_TFORLOOP: {
if (!L.stack[ra + 1].ttisnil()) { /* continue loop? */
lobject.setobjs2s(L, ra, ra + 1); /* save control variable */
@@ -601,7 +682,14 @@ const luaV_execute = function(L) {
ltable.luaH_setint(h, last--, L.stack[ra + n]);
}
- L.top = ci.top; /* correct top (in case of previous open call) */
+ /* correct top (in case of previous open call) */
+ if (L.top < ci.top) {
+ while (L.top < ci.top)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ } else {
+ while (L.top > ci.top)
+ delete L.stack[--L.top];
+ }
break;
}
case OCi.OP_CLOSURE: {
@@ -620,14 +708,23 @@ const luaV_execute = function(L) {
if (b < 0) {
b = n; /* get all var. arguments */
ldo.luaD_checkstack(L, n);
- L.top = ra + n;
+ if (L.top >= ra+n) {
+ while (L.top > ra+n)
+ delete L.stack[--L.top];
+ } else {
+ while (L.top < ra+n) {
+ L.stack[L.top] = new lobject.TValue();
+ L.top++;
+ }
+ }
+ assert(L.top == ra + n);
}
for (j = 0; j < b && j < n; j++)
lobject.setobjs2s(L, ra + j, base - n + j);
for (; j < b; j++) /* complete required results with nil */
- L.stack[ra + j] = new lobject.TValue(CT.LUA_TNIL, null);
+ L.stack[ra + j].setnilvalue();
break;
}
case OCi.OP_EXTRAARG: {
@@ -725,8 +822,9 @@ const luaV_equalobj = function(L, t1, t2) {
if (tm === null) /* no TM? */
return 0;
- ltm.luaT_callTM(L, tm, t1, t2, L.top, 1);
- return L.stack[L.top].l_isfalse() ? 0 : 1;
+ let tv = new lobject.TValue(); /* doesn't use the stack */
+ ltm.luaT_callTM(L, tm, t1, t2, tv, 1);
+ return tv.l_isfalse() ? 0 : 1;
};
const luaV_rawequalobj = function(t1, t2) {
@@ -890,12 +988,12 @@ const luaV_objlen = function(L, ra, rb) {
let h = rb.value;
tm = ltm.fasttm(L, h.metatable, ltm.TMS.TM_LEN);
if (tm !== null) break; /* metamethod? break switch to call it */
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, ltable.luaH_getn(h)); /* else primitive len */
+ ra.setivalue(ltable.luaH_getn(h)); /* else primitive len */
return;
}
case CT.LUA_TSHRSTR:
case CT.LUA_TLNGSTR:
- L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, rb.vslen());
+ ra.setivalue(rb.vslen());
return;
default: {
tm = ltm.luaT_gettmbyobj(L, rb, ltm.TMS.TM_LEN);
@@ -989,32 +1087,29 @@ const luaV_concat = function(L, total) {
let n = 2; /* number of elements handled in this pass (at least 2) */
if (!(L.stack[top-2].ttisstring() || cvt2str(L.stack[top-2])) || !tostring(L, top - 1)) {
- ltm.luaT_trybinTM(L, L.stack[top-2], L.stack[top-1], top-2, ltm.TMS.TM_CONCAT);
- delete L.stack[top - 1];
+ ltm.luaT_trybinTM(L, L.stack[top-2], L.stack[top-1], L.stack[top-2], ltm.TMS.TM_CONCAT);
} else if (isemptystr(L.stack[top-1])) {
tostring(L, top - 2);
- delete L.stack[top - 1];
} else if (isemptystr(L.stack[top-2])) {
lobject.setobjs2s(L, top - 2, top - 1);
- delete L.stack[top - 1];
} else {
/* at least two non-empty string values; get as many as possible */
let toconcat = new Array(total);
toconcat[total-1] = L.stack[top-1].svalue();
- delete L.stack[top - 1];
for (n = 1; n < total; n++) {
if (!tostring(L, top - n - 1)) {
toconcat = toconcat.slice(total-n);
break;
}
toconcat[total-n-1] = L.stack[top - n - 1].svalue();
- delete L.stack[top - n - 1];
}
let ts = lstring.luaS_bless(L, Array.prototype.concat.apply([], toconcat));
lobject.setsvalue2s(L, top - n, ts);
}
total -= n - 1; /* got 'n' strings to create 1 new */
- L.top -= n - 1; /* popped 'n' strings and pushed one */
+ /* popped 'n' strings and pushed one */
+ for (; L.top > top-(n-1);)
+ delete L.stack[--L.top];
} while (total > 1); /* repeat until only 1 result left */
};
@@ -1037,14 +1132,14 @@ const gettable = function(L, t, key, ra) {
} else { /* 't' is a table */
tm = ltm.fasttm(L, t.value.metatable, ltm.TMS.TM_INDEX); /* table's metamethod */
if (tm === null) { /* no metamethod? */
- L.stack[ra] = new lobject.TValue(CT.LUA_TNIL, null); /* result is nil */
+ L.stack[ra].setnilvalue(); /* result is nil */
return;
}
}
/* else will try the metamethod */
}
if (tm.ttisfunction()) { /* is metamethod a function? */
- ltm.luaT_callTM(L, tm, t, key, ra, 1); /* call it */
+ ltm.luaT_callTM(L, tm, t, key, L.stack[ra], 1); /* call it */
return;
}
t = tm; /* else try to access 'tm[key]' */