aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Giannangeli <giann008@gmail.com>2017-05-28 11:36:00 +0200
committerBenoit Giannangeli <giann008@gmail.com>2017-05-28 11:40:31 +0200
commit8173e639527cffc583c9c6ad6e7fc0d43429ab50 (patch)
tree0fc1cb51dbeb813f48fca03716088e0ecf61a989
parentbaa9730a961ab2d1810a3093f63e2c66241a6b72 (diff)
parent183768f08070003691f206ac16cb2310a7b4fa90 (diff)
downloadfengari-8173e639527cffc583c9c6ad6e7fc0d43429ab50.tar.gz
fengari-8173e639527cffc583c9c6ad6e7fc0d43429ab50.tar.bz2
fengari-8173e639527cffc583c9c6ad6e7fc0d43429ab50.zip
Merge remote-tracking branch 'daurnimator/stack-modification-work' into test-suite
-rw-r--r--src/lapi.js201
-rw-r--r--src/lauxlib.js41
-rw-r--r--src/ldebug.js28
-rw-r--r--src/ldo.js102
-rw-r--r--src/lobject.js78
-rw-r--r--src/lparser.js6
-rw-r--r--src/lstate.js5
-rw-r--r--src/ltable.js4
-rw-r--r--src/ltm.js24
-rw-r--r--src/lundump.js2
-rw-r--r--src/lvm.js326
11 files changed, 506 insertions, 311 deletions
diff --git a/src/lapi.js b/src/lapi.js
index 9b40b36..1dfd112 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] = from.stack[from.top + 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,22 +137,24 @@ const lua_gettop = function(L) {
};
const lua_pushvalue = function(L, idx) {
- L.stack[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];
}
@@ -162,9 +166,10 @@ const lua_pop = function(L, n) {
const reverse = function(L, from, to) {
for (; from < to; from++, to--) {
- let temp = L.stack[from];
- L.stack[from] = L.stack[to];
- L.stack[to] = temp;
+ let fromtv = L.stack[from];
+ let temp = new TValue(fromtv.type, fromtv.value);
+ lobject.setobjs2s(L, from, to);
+ lobject.setobj2s(L, to, temp);
}
};
@@ -189,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) {
@@ -211,34 +216,36 @@ const lua_replace = function(L, idx) {
*/
const lua_pushnil = function(L) {
- L.stack[L.top++] = new TValue(CT.LUA_TNIL, null);
-
+ L.stack[L.top] = new TValue(CT.LUA_TNIL, null);
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
};
const lua_pushnumber = function(L, n) {
assert(typeof n === "number");
- L.stack[L.top++] = new TValue(CT.LUA_TNUMFLT, n);
-
+ L.stack[L.top] = new TValue(CT.LUA_TNUMFLT, n);
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
};
const lua_pushinteger = function(L, n) {
assert(typeof n === "number" && (n|0) === n);
-
- L.stack[L.top++] = new TValue(CT.LUA_TNUMINT, n);
-
+ L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n);
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
};
const lua_pushlstring = function(L, s, len) {
- assert(Array.isArray(s), "lua_pushlstring expects array of byte");
assert(typeof len === "number");
-
- let ts = new TValue(CT.LUA_TLNGSTR, lstring.luaS_bless(L, s.slice(0, len)));
- L.stack[L.top++] = ts;
-
+ let ts;
+ if (len === 0) {
+ ts = lstring.luaS_bless(L, []);
+ } else {
+ assert(Array.isArray(s), "lua_pushlstring expects array of byte");
+ ts = lstring.luaS_bless(L, s.slice(0, len));
+ }
+ lobject.pushsvalue2s(L, ts);
assert(L.top <= L.ci.top, "stack overflow");
return ts.value;
@@ -247,13 +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 {
- L.stack[L.top] = new TValue(CT.LUA_TLNGSTR, lstring.luaS_new(L, s));
+ 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.pushsvalue2s(L, ts);
+ s = ts.getstr(); /* internal copy */
}
-
- L.top++;
assert(L.top <= L.ci.top, "stack overflow");
return s;
@@ -269,17 +277,18 @@ const lua_pushfstring = function (L, fmt, ...argp) {
return lobject.luaO_pushvfstring(L, fmt, argp);
};
+/* Similar to lua_pushstring, but takes a JS string */
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 {
- let ts = new TValue(CT.LUA_TLNGSTR, lstring.luaS_newliteral(L, s));
- L.stack[L.top] = ts;
+ L.top++;
+ } else {
+ let ts = lstring.luaS_newliteral(L, s);
+ lobject.pushsvalue2s(L, ts);
+ s = ts.getstr(); /* internal copy */
}
-
- L.top++;
assert(L.top <= L.ci.top, "stack overflow");
return s;
@@ -296,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");
};
@@ -319,21 +326,21 @@ const lua_pushcfunction = function(L, fn) {
const lua_pushjsfunction = lua_pushcfunction;
const lua_pushboolean = function(L, b) {
- L.stack[L.top++] = new TValue(CT.LUA_TBOOLEAN, b ? true : false);
-
+ L.stack[L.top] = new TValue(CT.LUA_TBOOLEAN, b ? true : false);
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
};
const lua_pushlightuserdata = function(L, p) {
- L.stack[L.top++] = new TValue(CT.LUA_TLIGHTUSERDATA, p);
-
+ L.stack[L.top] = new TValue(CT.LUA_TLIGHTUSERDATA, p);
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
};
const lua_pushthread = function(L) {
- L.stack[L.top++] = new TValue(CT.LUA_TTHREAD, L);
+ L.stack[L.top] = new TValue(CT.LUA_TTHREAD, L);
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
-
return L.l_G.mainthread === L;
};
@@ -351,11 +358,10 @@ const lua_pushglobaltable = function(L) {
const auxsetstr = function(L, t, k) {
assert(Array.isArray(k), "key must be an array of bytes");
- let str = new TValue(CT.LUA_TLNGSTR, lstring.luaS_new(L, k));
-
+ let str = lstring.luaS_new(L, k);
assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
-
- L.stack[L.top++] = str;
+ 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 */
delete L.stack[--L.top];
@@ -409,7 +415,8 @@ const lua_seti = function(L, idx, n) {
assert(typeof n === "number" && (n|0) === n);
assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
let t = index2addr(L, idx);
- L.stack[L.top++] = new TValue(CT.LUA_TNUMINT, n);
+ L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n);
+ L.top++;
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 */
@@ -430,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) {
@@ -453,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];
};
/*
@@ -462,24 +470,18 @@ 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 = new TValue(CT.LUA_TLNGSTR, lstring.luaS_new(L, k));
-
- L.stack[L.top++] = str;
+ let str = lstring.luaS_new(L, k);
+ 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();
};
const lua_rawgeti = function(L, idx, n) {
let t = index2addr(L, idx);
-
assert(t.ttistable(), "table expected");
-
- L.stack[L.top++] = ltable.luaH_getint(t.value, n);
+ lobject.pushobj2s(L, ltable.luaH_getint(t.value, n));
assert(L.top <= L.ci.top, "stack overflow");
-
return L.stack[L.top - 1].ttnov();
};
@@ -487,26 +489,23 @@ 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);
- L.stack[L.top++] = ltable.luaH_get(L, t.value, k);
+ 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();
};
const lua_rawget = function(L, idx) {
let t = index2addr(L, idx);
-
assert(t.ttistable(t), "table expected");
-
- L.stack[L.top - 1] = ltable.luaH_get(L, t.value, L.stack[L.top - 1]);
-
+ lobject.setobj2s(L, L.top - 1, ltable.luaH_get(L, t.value, L.stack[L.top - 1]));
return L.stack[L.top - 1].ttnov();
};
// narray and nrec are mostly useless for this implementation
const lua_createtable = function(L, narray, nrec) {
let t = new lobject.TValue(CT.LUA_TTABLE, ltable.luaH_new(L));
- L.stack[L.top++] = t;
-
+ L.stack[L.top] = t;
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
};
@@ -516,10 +515,9 @@ const luaS_newudata = function(L, size) {
const lua_newuserdata = function(L, size) {
let u = luaS_newudata(L, size);
- L.stack[L.top++] = new lobject.TValue(CT.LUA_TUSERDATA, u);
-
+ L.stack[L.top] = new lobject.TValue(CT.LUA_TUSERDATA, u);
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
-
return u.data;
};
@@ -552,9 +550,8 @@ const lua_getupvalue = function(L, funcindex, n) {
if (up) {
let name = up.name;
let val = up.val;
-
- L.stack[L.top++] = new TValue(val.type, val.value);
-
+ lobject.pushobj2s(L, val);
+ assert(L.top <= L.ci.top, "stack overflow");
return name;
}
return null;
@@ -567,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;
@@ -598,7 +595,8 @@ const lua_getmetatable = function(L, objindex) {
}
if (mt !== null && mt !== undefined) {
- L.stack[L.top++] = new TValue(CT.LUA_TTABLE, mt);
+ L.stack[L.top] = new TValue(CT.LUA_TTABLE, mt);
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
res = true;
}
@@ -610,7 +608,8 @@ const lua_getuservalue = function(L, idx) {
let o = index2addr(L, idx);
assert(L, o.ttisfulluserdata(), "full userdata expected");
let uv = o.value.uservalue;
- L.stack[L.top++] = new TValue(uv.type, uv.value);
+ L.stack[L.top] = new TValue(uv.type, uv.value);
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
return L.stack[L.top - 1].ttnov();
};
@@ -628,7 +627,8 @@ const lua_getfield = function(L, idx, k) {
const lua_geti = function(L, idx, n) {
assert(typeof n === "number" && (n|0) === n);
let t = index2addr(L, idx);
- L.stack[L.top++] = new TValue(CT.LUA_TNUMINT, n);
+ L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n);
+ L.top++;
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();
@@ -654,7 +654,8 @@ const lua_tolstring = function(L, idx) {
if (!lvm.cvt2str(o)) { /* not convertible? */
return null;
}
- o = lobject.luaO_tostring(L, o);
+ /* TODO: this should modify number on the stack */
+ return lobject.luaO_tostring(L, o).getstr();
}
return o.svalue();
};
@@ -668,7 +669,8 @@ const lua_toljsstring = function(L, idx) {
if (!lvm.cvt2str(o)) { /* not convertible? */
return null;
}
- o = lobject.luaO_tostring(L, o);
+ /* TODO: this should modify number on the stack */
+ return defs.to_jsstring(lobject.luaO_tostring(L, o).getstr());
}
return o.jsstring();
};
@@ -768,7 +770,9 @@ const lua_isproxy = function(p, L) {
const create_proxy = function(G, type, value) {
let proxy = function(L) {
assert(L instanceof lstate.lua_State && G === L.l_G, "must be from same global state");
- L.stack[L.top++] = new TValue(type, value);
+ L.stack[L.top] = new TValue(type, value);
+ L.top++;
+ assert(L.top <= L.ci.top, "stack overflow");
};
seen.set(proxy, G);
return proxy;
@@ -802,7 +806,8 @@ const lua_compare = function(L, index1, index2, op) {
const lua_stringtonumber = function(L, s) {
let tv = lobject.luaO_str2num(s);
if (tv) {
- L.stack[L.top++] = tv;
+ L.stack[L.top] = tv;
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
return s.length+1;
}
@@ -893,11 +898,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");
- L.stack[L.top++] = L.stack[L.top - 1];
+ 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.top - 2);
- L.top--; /* remove second operand */
+ lobject.luaO_arith(L, op, L.stack[L.top - 2], L.stack[L.top - 1], L.stack[L.top - 2]);
+ delete L.stack[--L.top]; /* remove second operand */
};
/*
@@ -1030,13 +1036,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;
}
};
@@ -1046,14 +1054,17 @@ const lua_concat = function(L, n) {
if (n >= 2)
lvm.luaV_concat(L, n);
else if (n === 0) {
- L.stack[L.top++] = new TValue(CT.LUA_TLNGSTR, lstring.luaS_newliteral(L, ""));
+ 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);
+ let tv = new TValue();
+ lvm.luaV_objlen(L, tv, t);
+ L.stack[L.top] = tv;
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
};
diff --git a/src/lauxlib.js b/src/lauxlib.js
index b14379c..0672c14 100644
--- a/src/lauxlib.js
+++ b/src/lauxlib.js
@@ -654,6 +654,7 @@ if (!WEB) {
this.f = null; /* file being read */
this.buff = new Buffer(1024); /* area for reading file */
this.pos = 0; /* current position in file */
+ this.err = void 0;
}
}
@@ -665,7 +666,12 @@ if (!WEB) {
lf.n = 0; /* no more pre-read characters */
} else { /* read a block from file */
lf.buff.fill(0);
- bytes = fs.readSync(lf.f, lf.buff, 0, lf.buff.length, lf.pos); /* read block */
+ try {
+ bytes = fs.readSync(lf.f, lf.buff, 0, lf.buff.length, lf.pos); /* read block */
+ } catch(e) {
+ lf.err = e;
+ bytes = 0;
+ }
lf.pos += bytes;
}
if (bytes > 0)
@@ -743,25 +749,24 @@ if (!WEB) {
return errfile(L, "open", fnameindex, e);
}
}
-
- try {
- let com = skipcomment(lf);
- /* check for signature first, as we don't want to add line number corrections in binary case */
- if (com.c === lua.LUA_SIGNATURE.charCodeAt(0) && filename) { /* binary file? */
- /* no need to re-open in node.js */
- } else if (com.skipped) { /* read initial portion */
- lf.buff[lf.n++] = '\n'.charCodeAt(0); /* add line to correct line numbers */
- }
- if (com.c !== null)
- lf.buff[lf.n++] = com.c; /* 'c' is the first character of the stream */
- let status = lua.lua_load(L, getF, lf, lua.lua_tostring(L, -1), mode);
- if (filename) fs.closeSync(lf.f); /* close file (even in case of errors) */
- lua.lua_remove(L, fnameindex);
- return status;
- } catch (err) {
+ let com = skipcomment(lf);
+ /* check for signature first, as we don't want to add line number corrections in binary case */
+ if (com.c === lua.LUA_SIGNATURE.charCodeAt(0) && filename) { /* binary file? */
+ /* no need to re-open in node.js */
+ } else if (com.skipped) { /* read initial portion */
+ lf.buff[lf.n++] = '\n'.charCodeAt(0); /* add line to correct line numbers */
+ }
+ if (com.c !== null)
+ lf.buff[lf.n++] = com.c; /* 'c' is the first character of the stream */
+ let status = lua.lua_load(L, getF, lf, lua.lua_tostring(L, -1), mode);
+ let readstatus = lf.err;
+ if (filename) try { fs.closeSync(lf.f); } catch(e) {} /* close file (even in case of errors) */
+ if (readstatus) {
lua.lua_settop(L, fnameindex); /* ignore results from 'lua_load' */
- return errfile(L, "read", fnameindex, err);
+ return errfile(L, "read", fnameindex, readstatus);
}
+ lua.lua_remove(L, fnameindex);
+ return status;
};
const luaL_loadfile = function(L, filename) {
diff --git a/src/ldebug.js b/src/ldebug.js
index 0f387af..3636a06 100644
--- a/src/ldebug.js
+++ b/src/ldebug.js
@@ -140,7 +140,8 @@ const lua_getlocal = function(L, ar, n) {
let local = findlocal(L, ar.i_ci, n);
if (local) {
name = local.name;
- L.stack[L.top++] = L.stack[local.pos];
+ lobject.pushobj2s(L, L.stack[local.pos]);
+ assert(L.top <= L.ci.top, "stack overflow");
} else {
name = null;
}
@@ -155,7 +156,7 @@ const lua_setlocal = function(L, ar, n) {
let name = local.name;
let pos = local.pos;
if (name) {
- L.stack[pos] = L.stack[L.top - 1];
+ lobject.setobjs2s(L, pos, L.top - 1);
delete L.stack[--L.top]; /* pop value */
}
swapextra(L);
@@ -181,12 +182,14 @@ const funcinfo = function(ar, cl) {
const collectvalidlines = function(L, f) {
if (f === null || f instanceof lobject.CClosure) {
- L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ L.stack[L.top] = new lobject.TValue(CT.LUA_TNIL, null);
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
} else {
let lineinfo = f.l.p.lineinfo;
let t = ltable.luaH_new(L);
- L.stack[L.top++] = new lobject.TValue(CT.LUA_TTABLE, t);
+ L.stack[L.top] = new lobject.TValue(CT.LUA_TTABLE, t);
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
let v = new lobject.TValue(CT.LUA_TBOOLEAN, true);
for (let i = 0; i < f.l.p.length; i++)
@@ -261,26 +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) {
- L.stack[L.top++] = func;
+ lobject.pushobj2s(L, func);
assert(L.top <= L.ci.top, "stack overflow");
}
@@ -590,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;
- L.stack[L.top] = L.stack[L.top - 1];
- L.stack[L.top - 1] = L.stack[errfunc];
- 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);
}
@@ -638,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 4c198ee..4c53f11 100644
--- a/src/ldo.js
+++ b/src/ldo.js
@@ -22,21 +22,28 @@ const CT = defs.constant_types;
const TS = defs.thread_status;
const seterrorobj = function(L, errcode, oldtop) {
+ let current_top = L.top;
+
+ /* extend stack so that L.stack[oldtop] is sure to exist */
+ while (L.top < oldtop + 1)
+ L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+
switch (errcode) {
case TS.LUA_ERRMEM: {
- L.stack[oldtop] = new lobject.TValue(CT.LUA_TLNGSTR, lstring.luaS_newliteral(L, "not enough memory"));
+ lobject.setsvalue2s(L, oldtop, lstring.luaS_newliteral(L, "not enough memory"));
break;
}
case TS.LUA_ERRERR: {
- L.stack[oldtop] = new lobject.TValue(CT.LUA_TLNGSTR, lstring.luaS_newliteral(L, "error in error handling"));
+ lobject.setsvalue2s(L, oldtop, lstring.luaS_newliteral(L, "error in error handling"));
break;
}
default: {
- L.stack[oldtop] = L.stack[L.top - 1];
+ lobject.setobjs2s(L, oldtop, current_top - 1);
}
}
- L.top = oldtop + 1;
+ while (L.top > oldtop + 1)
+ delete L.stack[--L.top];
};
const ERRORSTACKSIZE = luaconf.LUAI_MAXSTACK + 200;
@@ -94,8 +101,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 +158,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 +173,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 +200,42 @@ const moveresults = function(L, firstResult, res, nres, wanted) {
break;
case 1: {
if (nres === 0)
- L.stack[firstResult] = lobject.luaO_nilobject;
- L.stack[res] = L.stack[firstResult];
+ 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++)
- L.stack[res + i] = L.stack[firstResult + 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++) {
- L.stack[res + i] = L.stack[firstResult + i];
- }
+ for (i = 0; i < wanted; i++)
+ lobject.setobjs2s(L, res + i, firstResult + i);
} else {
for (i = 0; i < nres; i++)
- L.stack[res + i] = L.stack[firstResult + i];
- for (; i < wanted; i++)
- L.stack[res + i] = new lobject.TValue(CT.LUA_TNIL, null);
+ lobject.setobjs2s(L, res + i, firstResult + i);
+ 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 +263,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 +282,8 @@ const adjust_varargs = function(L, p, actual) {
let i;
for (i = 0; i < nfixargs && i < actual; i++) {
- L.stack[L.top++] = L.stack[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,10 +297,10 @@ 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--)
- L.stack[p] = L.stack[p-1];
- L.top++; /* slot ensured by caller */
- L.stack[off] = new lobject.TValue(tm.type, tm.value); /* tag method is the new function to be called */
+ 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 */
};
/*
@@ -351,8 +381,8 @@ const luaD_rawrunprotected = function(L, f, ud) {
/* copy of luaG_errormsg without the throw */
if (L.errfunc !== 0) { /* is there an error handling function? */
let errfunc = L.errfunc;
- L.stack[L.top] = L.stack[L.top - 1];
- L.stack[L.top - 1] = L.stack[errfunc];
+ lobject.setobjs2s(L, L.top, L.top - 1); /* move argument */
+ lobject.setobjs2s(L, L.top - 1, errfunc); /* push function */
L.top++;
luaD_callnoyield(L, L.top - 2, 1);
}
@@ -464,9 +494,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 */
- L.stack[L.top++] = new lobject.TValue(CT.LUA_TLNGSTR, lstring.luaS_newliteral(L, msg)); /* push error message */
- 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;
};
@@ -657,8 +694,6 @@ const luaD_protectedparser = function(L, z, name, mode) {
return status;
};
-module.exports.SParser = SParser;
-module.exports.adjust_varargs = adjust_varargs;
module.exports.luaD_call = luaD_call;
module.exports.luaD_callnoyield = luaD_callnoyield;
module.exports.luaD_checkstack = luaD_checkstack;
@@ -676,6 +711,3 @@ module.exports.lua_isyieldable = lua_isyieldable;
module.exports.lua_resume = lua_resume;
module.exports.lua_yield = lua_yield;
module.exports.lua_yieldk = lua_yieldk;
-module.exports.moveresults = moveresults;
-module.exports.stackerror = stackerror;
-module.exports.tryfuncTM = tryfuncTM;
diff --git a/src/lobject.js b/src/lobject.js
index d08849c..7f81438 100644
--- a/src/lobject.js
+++ b/src/lobject.js
@@ -126,11 +126,21 @@ class TValue {
this.value = x;
}
+ chgfltvalue(x) {
+ assert(this.type == CT.LUA_TNUMFLT);
+ this.value = x;
+ }
+
setivalue(x) {
this.type = CT.LUA_TNUMINT;
this.value = x;
}
+ chgivalue(x) {
+ assert(this.type == CT.LUA_TNUMINT);
+ this.value = x;
+ }
+
setnilvalue() {
this.type = CT.LUA_TNIL;
this.value = void 0;
@@ -151,6 +161,31 @@ class TValue {
this.value = x;
}
+ setsvalue(x) {
+ this.type = CT.LUA_TLNGSTR; /* LUA_TSHRSTR? */
+ this.value = x;
+ }
+
+ setuvalue(x) {
+ this.type = CT.LUA_TUSERDATA;
+ this.value = x;
+ }
+
+ setthvalue(x) {
+ this.type = CT.LUA_TTHREAD;
+ this.value = x;
+ }
+
+ setclLvalue(x) {
+ this.type = CT.LUA_TLCL;
+ this.value = x;
+ }
+
+ setclCvalue(x) {
+ this.type = CT.LUA_TCCL;
+ this.value = x;
+ }
+
sethvalue(x) {
this.type = CT.LUA_TTABLE;
this.value = x;
@@ -185,6 +220,24 @@ 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].setfrom(L.stack[oldidx]);
+};
+/* to stack (not from same stack) */
+const setobj2s = function(L, newidx, oldtv) {
+ L.stack[newidx].setfrom(oldtv);
+};
+const setsvalue2s = function(L, newidx, ts) {
+ L.stack[newidx].setsvalue(ts);
+};
+
const luaO_nilobject = new TValue(CT.LUA_TNIL, null);
Object.freeze(luaO_nilobject);
module.exports.luaO_nilobject = luaO_nilobject;
@@ -477,12 +530,12 @@ const luaO_tostring = function(L, obj) {
buff.push(char['0']); /* adds '.0' to result */
}
}
- return new TValue(CT.LUA_TLNGSTR, lstring.luaS_bless(L, buff));
+ return lstring.luaS_bless(L, buff);
};
const pushstr = function(L, str) {
ldo.luaD_inctop(L);
- L.stack[L.top-1] = new TValue(CT.LUA_TLNGSTR, lstring.luaS_new(L, str));
+ setsvalue2s(L, L.top-1, lstring.luaS_new(L, str));
};
const luaO_pushvfstring = function(L, fmt, argp) {
@@ -510,11 +563,11 @@ const luaO_pushvfstring = function(L, fmt, argp) {
case char['d']:
case char['I']:
ldo.luaD_inctop(L);
- L.stack[L.top-1] = luaO_tostring(L, new TValue(CT.LUA_TNUMINT, argp[a++]));
+ setsvalue2s(L, L.top-1, luaO_tostring(L, new TValue(CT.LUA_TNUMINT, argp[a++])));
break;
case char['f']:
ldo.luaD_inctop(L);
- L.stack[L.top-1] = luaO_tostring(L, new TValue(CT.LUA_TNUMFLT, argp[a++]));
+ setsvalue2s(L, L.top-1, luaO_tostring(L, new TValue(CT.LUA_TNUMFLT, argp[a++])));
break;
case char['p']:
let v = argp[a++];
@@ -614,8 +667,7 @@ const luaO_arith = function(L, op, p1, p2, p3) {
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 */
@@ -623,8 +675,7 @@ const luaO_arith = function(L, op, p1, p2, p3) {
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 */
@@ -632,13 +683,11 @@ const luaO_arith = function(L, op, p1, p2, p3) {
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 */
@@ -669,3 +718,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 13f75c9..0079141 100644
--- a/src/lparser.js
+++ b/src/lparser.js
@@ -1565,10 +1565,10 @@ const luaY_parser = function(L, z, buff, dyd, name, firstchar) {
let funcstate = new FuncState();
let cl = lfunc.luaF_newLclosure(L, 1); /* create main closure */
ldo.luaD_inctop(L);
- L.stack[L.top-1] = new TValue(defs.CT.LUA_TLCL, cl);
+ 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 2413574..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;
@@ -147,7 +147,8 @@ const f_luaopen = function(L) {
const lua_newthread = function(L) {
let g = L.l_G;
let L1 = new lua_State(g);
- L.stack[L.top++] = new lobject.TValue(CT.LUA_TTHREAD, L1);
+ L.stack[L.top] = new lobject.TValue(CT.LUA_TTHREAD, L1);
+ L.top++;
assert(L.top <= L.ci.top, "stack overflow");
L1.hookmask = L.hookmask;
L1.basehookcount = L.basehookcount;
diff --git a/src/ltable.js b/src/ltable.js
index 5a31b48..53a5d79 100644
--- a/src/ltable.js
+++ b/src/ltable.js
@@ -261,8 +261,8 @@ const luaH_next = function(L, table, keyI) {
} while (entry.key.ttisdeadkey());
}
}
- L.stack[keyI] = new lobject.TValue(entry.key.type, entry.key.value);
- L.stack[keyI+1] = new lobject.TValue(entry.value.type, entry.value.value);
+ lobject.setobj2s(L, keyI, entry.key);
+ lobject.setobj2s(L, keyI+1, entry.value);
return true;
};
diff --git a/src/ltm.js b/src/ltm.js
index ad09c26..88f25fb 100644
--- a/src/ltm.js
+++ b/src/ltm.js
@@ -108,25 +108,24 @@ const luaT_objtypename = function(L, o) {
};
const luaT_callTM = function(L, f, p1, p2, p3, hasres) {
- let result = p3;
let func = L.top;
- L.stack[L.top] = new lobject.TValue(f.type, f.value); /* push function (assume EXTRA_STACK) */
- L.stack[L.top + 1] = new lobject.TValue(p1.type, p1.value); /* 1st argument */
- L.stack[L.top + 2] = new lobject.TValue(p2.type, p2.value); /* 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 */
- L.stack[L.top++] = new lobject.TValue(p3.type, p3.value); /* 3rd argument */
+ lobject.pushobj2s(L, p3); /* 3rd argument */
if (L.ci.callstatus & lstate.CIST_LUA)
ldo.luaD_call(L, func, hasres);
else
ldo.luaD_callnoyield(L, func, hasres);
- if (hasres) {
- assert(typeof result === "number");
- L.stack[result] = L.stack[--L.top];
+ if (hasres) { /* if has result, move it to its place */
+ let tv = L.stack[L.top-1];
+ delete L.stack[--L.top];
+ p3.setfrom(tv);
}
};
@@ -160,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))
- return -1;
+ let res = new lobject.TValue();
+ if (!luaT_callbinTM(L, p1, p2, res, event))
+ return null;
else
- return !L.stack[L.top].l_isfalse() ? 1 : 0;
+ return !res.l_isfalse();
};
const fasttm = function(l, et, e) {
diff --git a/src/lundump.js b/src/lundump.js
index 4931fe8..3f61cb6 100644
--- a/src/lundump.js
+++ b/src/lundump.js
@@ -266,7 +266,7 @@ const luaU_undump = function(L, Z, name) {
S.checkHeader();
let cl = lfunc.luaF_newLclosure(L, S.readByte());
ldo.luaD_inctop(L);
- L.stack[L.top-1] = new lobject.TValue(defs.CT.LUA_TLCL, cl);
+ 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 07acb42..9bbe768 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: {
- L.stack[base + inst.A] = L.stack[--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 */
@@ -54,25 +55,46 @@ const luaV_finishOp = function(L) {
let top = L.top - 1; /* top when 'luaT_trybinTM' was called */
let b = inst.B; /* first element to concatenate */
let total = top - 1 - (base + b); /* yet to concatenate */
- L.stack[top - 2] = L.stack[top]; /* put TM result in proper position */
+ lobject.setobjs2s(L, top - 2, top); /* put TM result in proper position */
if (total > 1) { /* are there elements to concat? */
L.top = top - 1; /* top is one after last element (at top-2) */
luaV_concat(L, total); /* concat them (may yield again) */
}
-
/* move final result to final position */
- L.stack[ci.l_base + inst.A] = L.stack[L.top - 1];
- L.top = ci.top; /* restore top */
+ lobject.setobjs2s(L, ci.l_base + inst.A, L.top - 1);
+ /* 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;
}
}
@@ -121,22 +143,22 @@ const luaV_execute = function(L) {
switch (opcode) {
case OCi.OP_MOVE: {
- L.stack[ra] = L.stack[RB(L, base, i)];
+ lobject.setobjs2s(L, ra, RB(L, base, i));
break;
}
case OCi.OP_LOADK: {
let konst = k[i.Bx];
- L.stack[ra] = new lobject.TValue(konst.type, konst.value);
+ lobject.setobj2s(L, ra, konst);
break;
}
case OCi.OP_LOADKX: {
assert(ci.l_code[ci.l_savedpc].opcode === OCi.OP_EXTRAARG);
let konst = k[ci.l_code[ci.l_savedpc++].Ax];
- L.stack[ra] = new lobject.TValue(konst.type, konst.value);
+ lobject.setobj2s(L, ra, konst);
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) */
@@ -145,18 +167,18 @@ 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: {
let o = cl.upvals[i.B].val();
- L.stack[ra] = new lobject.TValue(o.type, o.value);
+ lobject.setobj2s(L, ra, o);
break;
}
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]);
}
@@ -193,16 +215,15 @@ 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: {
- let table = L.stack[RB(L, base, i)];
- let key = RKC(L, base, k, i);
-
- L.stack[ra + 1] = table;
+ let rb = RB(L, base, i);
+ let rc = RKC(L, base, k, i);
+ lobject.setobjs2s(L, ra + 1, rb);
- gettable(L, table, key, ra);
+ gettable(L, L.stack[rb], rc, ra);
break;
}
case OCi.OP_ADD: {
@@ -212,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;
}
@@ -227,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;
}
@@ -242,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;
}
@@ -257,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;
}
@@ -272,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;
}
@@ -285,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;
}
@@ -298,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;
}
@@ -313,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;
}
@@ -326,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;
}
@@ -339,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;
}
@@ -352,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;
}
@@ -365,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;
}
@@ -376,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;
}
@@ -388,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: {
@@ -409,8 +430,15 @@ const luaV_execute = function(L) {
L.top = base + c + 1; /* mark the end of concat operands */
luaV_concat(L, c - b + 1);
let rb = base + b;
- L.stack[ra] = L.stack[rb];
- L.top = ci.top; /* restore top */
+ lobject.setobjs2s(L, ra, rb);
+ /* 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: {
@@ -446,11 +474,12 @@ const luaV_execute = function(L) {
break;
}
case OCi.OP_TESTSET: {
- let rb = L.stack[RB(L, base, i)];
+ let rbIdx = RB(L, base, i);
+ let rb = L.stack[rbIdx];
if (i.C ? rb.l_isfalse() : !rb.l_isfalse())
ci.l_savedpc++;
else {
- L.stack[ra] = rb;
+ lobject.setobjs2s(L, ra, rbIdx);
donextjump(L, ci);
}
break;
@@ -459,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;
@@ -473,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,10 +537,16 @@ const luaV_execute = function(L) {
let lim = nci.l_base + nfunc.value.p.numparams;
if (cl.p.p.length > 0) lfunc.luaF_close(L, oci.l_base);
for (let aux = 0; nfuncOff + aux < lim; aux++)
- L.stack[ofuncOff + aux] = L.stack[nfuncOff + aux];
- oci.func = nci.func;
+ lobject.setobjs2s(L, ofuncOff + aux, nfuncOff + aux);
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;
@@ -507,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,8 +588,8 @@ const luaV_execute = function(L) {
if (0 < step ? idx <= limit : limit <= idx) {
ci.l_savedpc += i.sBx;
- L.stack[ra].value = idx;
- L.stack[ra + 3] = new lobject.TValue(CT.LUA_TNUMINT, idx);
+ L.stack[ra].chgivalue(idx); /* update internal index... */
+ L.stack[ra + 3].setivalue(idx);
}
} else { /* floating loop */
let step = L.stack[ra + 2].value;
@@ -531,8 +598,8 @@ const luaV_execute = function(L) {
if (0 < step ? idx <= limit : limit <= idx) {
ci.l_savedpc += i.sBx;
- L.stack[ra].value = idx;
- L.stack[ra + 3] = new lobject.TValue(CT.LUA_TNUMFLT, idx);
+ L.stack[ra].chgfltvalue(idx); /* update internal index... */
+ L.stack[ra + 3].setfltvalue(idx);
}
}
break;
@@ -551,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;
@@ -565,21 +632,34 @@ const luaV_execute = function(L) {
}
case OCi.OP_TFORCALL: {
let cb = ra + 3; /* call base */
- L.stack[cb + 2] = L.stack[ra + 2];
- L.stack[cb + 1] = L.stack[ra + 1];
- L.stack[cb] = L.stack[ra];
- L.top = cb + 3; /* func. + 2 args (state and index) */
+ lobject.setobjs2s(L, cb+2, ra+2);
+ lobject.setobjs2s(L, cb+1, ra+1);
+ lobject.setobjs2s(L, cb, ra);
+ /* 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? */
- L.stack[ra] = L.stack[ra + 1]; /* save control variable */
+ lobject.setobjs2s(L, ra, ra + 1); /* save control variable */
ci.l_savedpc += i.sBx; /* jump back */
}
break;
@@ -602,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: {
@@ -621,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++)
- L.stack[ra + j] = L.stack[base - 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: {
@@ -656,31 +752,29 @@ const luaV_lessthan = function(L, l, r) {
return l_strcmp(l.tsvalue(), r.tsvalue()) < 0 ? 1 : 0;
else {
let res = ltm.luaT_callorderTM(L, l, r, ltm.TMS.TM_LT);
- if (res < 0)
+ if (res === null)
ldebug.luaG_ordererror(L, l, r);
return res ? 1 : 0;
}
};
const luaV_lessequal = function(L, l, r) {
- let res;
-
if (l.ttisnumber() && r.ttisnumber())
return LEnum(l, r) ? 1 : 0;
else if (l.ttisstring() && r.ttisstring())
return l_strcmp(l.tsvalue(), r.tsvalue()) <= 0 ? 1 : 0;
else {
- res = ltm.luaT_callorderTM(L, l, r, ltm.TMS.TM_LE);
- if (res >= 0)
+ let res = ltm.luaT_callorderTM(L, l, r, ltm.TMS.TM_LE);
+ if (res !== null)
return res ? 1 : 0;
}
/* try 'lt': */
L.ci.callstatus |= lstate.CIST_LEQ; /* mark it is doing 'lt' for 'le' */
- res = ltm.luaT_callorderTM(L, r, l, ltm.TMS.TM_LT);
+ let res = ltm.luaT_callorderTM(L, r, l, ltm.TMS.TM_LT);
L.ci.callstatus ^= lstate.CIST_LEQ; /* clear mark */
- if (res < 0)
+ if (res === null)
ldebug.luaG_ordererror(L, l, r);
- return res !== 1 ? 1 : 0; /* result is negated */
+ return res ? 0 : 1; /* result is negated */
};
const luaV_equalobj = function(L, t1, t2) {
@@ -726,8 +820,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) {
@@ -891,12 +986,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);
@@ -944,7 +1039,7 @@ const pushclosure = function(L, p, encup, base, ra) {
let uv = p.upvalues;
let ncl = new lobject.LClosure(L, nup);
ncl.p = p;
- L.stack[ra] = new lobject.TValue(CT.LUA_TLCL, ncl);
+ L.stack[ra].setclLvalue(ncl);
for (let i = 0; i < nup; i++) {
if (uv[i].instack)
ncl.upvals[i] = lfunc.luaF_findupval(L, base + uv[i].idx);
@@ -968,7 +1063,7 @@ const tostring = function(L, i) {
if (o.ttisstring()) return true;
if (cvt2str(o)) {
- L.stack[i] = lobject.luaO_tostring(L, o);
+ lobject.setsvalue2s(L, i, lobject.luaO_tostring(L, o));
return true;
}
@@ -990,32 +1085,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])) {
- L.stack[top - 2] = L.stack[top - 1];
- delete L.stack[top - 1];
+ lobject.setobjs2s(L, top - 2, 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));
- L.stack[top - n] = new lobject.TValue(CT.LUA_TLNGSTR, ts);
+ 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 */
};
@@ -1033,19 +1125,19 @@ const gettable = function(L, t, key, ra) {
} else {
let slot = ltable.luaH_get(L, t.value, key);
if (!slot.ttisnil()) {
- L.stack[ra] = new lobject.TValue(slot.type, slot.value);
+ lobject.setobj2s(L, ra, slot);
return;
} 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]' */