From b3c87776e08f546a9994527f7c2c7fc4ec07d9a1 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 17:09:03 +1000 Subject: Introduce setobjs2s --- src/lapi.js | 5 +++-- src/ldebug.js | 9 +++++---- src/ldo.js | 18 +++++++++--------- src/lobject.js | 6 ++++++ src/ltm.js | 6 ++---- src/lvm.js | 34 +++++++++++++++++----------------- 6 files changed, 42 insertions(+), 36 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index 92e1612..00e608f 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -163,7 +163,7 @@ 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]; + lobject.setobjs2s(L, from, to); L.stack[to] = temp; } }; @@ -892,7 +892,8 @@ 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.setobjs2s(L, L.top, L.top - 1); + L.top++; } /* 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]); diff --git a/src/ldebug.js b/src/ldebug.js index 0f387af..0231e67 100644 --- a/src/ldebug.js +++ b/src/ldebug.js @@ -155,7 +155,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); @@ -280,7 +280,8 @@ const lua_getinfo = function(L, what, ar) { 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.setobjs2s(L, L.top, funcOff); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); } @@ -590,8 +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]; + lobject.setobjs2s(L, L.top, L.top - 1); /* move argument */ + lobject.setobjs2s(L, L.top - 1, errfunc); /* push function */ L.top++; ldo.luaD_callnoyield(L, L.top - 2, 1); } diff --git a/src/ldo.js b/src/ldo.js index 4c198ee..d236968 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -32,7 +32,7 @@ const seterrorobj = function(L, errcode, oldtop) { break; } default: { - L.stack[oldtop] = L.stack[L.top - 1]; + lobject.setobjs2s(L, oldtop, L.top - 1); } } @@ -186,12 +186,12 @@ const moveresults = function(L, firstResult, res, nres, wanted) { case 1: { if (nres === 0) L.stack[firstResult] = lobject.luaO_nilobject; - L.stack[res] = L.stack[firstResult]; + 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); L.top = res + nres; return false; } @@ -199,11 +199,11 @@ const moveresults = function(L, firstResult, res, nres, wanted) { let i; if (wanted <= nres) { for (i = 0; i < wanted; i++) { - L.stack[res + i] = L.stack[firstResult + i]; + lobject.setobjs2s(L, res + i, firstResult + i); } } else { for (i = 0; i < nres; i++) - L.stack[res + i] = L.stack[firstResult + i]; + lobject.setobjs2s(L, res + i, firstResult + i); for (; i < wanted; i++) L.stack[res + i] = new lobject.TValue(CT.LUA_TNIL, null); } @@ -252,7 +252,7 @@ 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]; + lobject.setobjs2s(L, L.top++, fixed + i); L.stack[fixed + i] = new lobject.TValue(CT.LUA_TNIL, null); } @@ -268,7 +268,7 @@ const tryfuncTM = function(L, off, func) { 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]; + lobject.setobjs2s(L, p, 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 */ }; @@ -351,8 +351,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); } diff --git a/src/lobject.js b/src/lobject.js index b6fd581..7b8a332 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -185,6 +185,11 @@ class TValue { } +/* from stack to (same) stack */ +const setobjs2s = function(L, newidx, oldidx) { + L.stack[newidx] = L.stack[oldidx]; +}; + const luaO_nilobject = new TValue(CT.LUA_TNIL, null); Object.freeze(luaO_nilobject); module.exports.luaO_nilobject = luaO_nilobject; @@ -667,3 +672,4 @@ module.exports.luaO_tostring = luaO_tostring; module.exports.luaO_utf8desc = luaO_utf8desc; module.exports.luaO_utf8esc = luaO_utf8esc; module.exports.numarith = numarith; +module.exports.setobjs2s = setobjs2s; diff --git a/src/ltm.js b/src/ltm.js index ad09c26..041dd19 100644 --- a/src/ltm.js +++ b/src/ltm.js @@ -108,7 +108,6 @@ 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) */ @@ -124,9 +123,8 @@ const luaT_callTM = function(L, f, p1, p2, p3, 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 */ + lobject.setobjs2s(L, p3, --L.top); } }; diff --git a/src/lvm.js b/src/lvm.js index 07acb42..602fe5c 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -34,7 +34,7 @@ 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); break; } case OCi.OP_LE: case OCi.OP_LT: case OCi.OP_EQ: { @@ -121,7 +121,7 @@ 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: { @@ -197,12 +197,11 @@ const luaV_execute = function(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: { @@ -409,7 +408,7 @@ 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]; + lobject.setobjs2s(L, ra, rb); L.top = ci.top; /* restore top */ break; } @@ -446,11 +445,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; @@ -485,7 +485,7 @@ 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]; + 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); @@ -565,9 +565,9 @@ 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]; + 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) */ ldo.luaD_call(L, cb, i.C); /* go straight to OP_TFORLOOP */ @@ -579,7 +579,7 @@ const luaV_execute = function(L) { } 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; @@ -625,7 +625,7 @@ const luaV_execute = function(L) { } 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); @@ -996,7 +996,7 @@ const luaV_concat = function(L, total) { tostring(L, top - 2); delete L.stack[top - 1]; } else if (isemptystr(L.stack[top-2])) { - L.stack[top - 2] = L.stack[top - 1]; + 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 */ -- cgit v1.2.3-70-g09d2 From 888c1286cfe25c1b21605c3443cc0a20b522972b Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 17:37:20 +1000 Subject: Introduce setobj2s --- src/lapi.js | 27 +++++++++++---------------- src/ldebug.js | 4 +++- src/ldo.js | 2 +- src/lobject.js | 5 +++++ src/ltable.js | 4 ++-- src/ltm.js | 8 ++++---- src/lvm.js | 8 ++++---- 7 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index 00e608f..2cf3a1c 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -112,7 +112,7 @@ 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]; + lobject.setobj2s(to, to.top, from.stack[from.top + i]); to.top++; } }; @@ -135,8 +135,7 @@ const lua_gettop = function(L) { }; const lua_pushvalue = function(L, idx) { - L.stack[L.top] = index2addr(L, idx); - + lobject.setobj2s(L, L.top, index2addr(L, idx)); L.top++; assert(L.top <= L.ci.top, "stack overflow"); }; @@ -164,7 +163,7 @@ const reverse = function(L, from, to) { for (; from < to; from++, to--) { let temp = L.stack[from]; lobject.setobjs2s(L, from, to); - L.stack[to] = temp; + lobject.setobj2s(L, to, temp); } }; @@ -474,12 +473,10 @@ const auxgetstr = function(L, t, k) { 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.setobj2s(L, L.top, ltable.luaH_getint(t.value, n)); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); - return L.stack[L.top - 1].ttnov(); }; @@ -487,18 +484,16 @@ 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.setobj2s(L, L.top, ltable.luaH_get(L, t.value, k)); + L.top++; 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(); }; @@ -552,9 +547,9 @@ 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.setobj2s(L, L.top, val); + L.top++; + assert(L.top <= L.ci.top, "stack overflow"); return name; } return null; diff --git a/src/ldebug.js b/src/ldebug.js index 0231e67..e78d3e7 100644 --- a/src/ldebug.js +++ b/src/ldebug.js @@ -140,7 +140,9 @@ 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.setobj2s(L, L.top, L.stack[local.pos]); + L.top++; + assert(L.top <= L.ci.top, "stack overflow"); } else { name = null; } diff --git a/src/ldo.js b/src/ldo.js index d236968..5fa51db 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -270,7 +270,7 @@ const tryfuncTM = function(L, off, func) { for (let p = L.top; p > off; p--) lobject.setobjs2s(L, p, 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.setobj2s(L, off, tm); /* tag method is the new function to be called */ }; /* diff --git a/src/lobject.js b/src/lobject.js index 7b8a332..3a442ee 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -189,6 +189,10 @@ class TValue { const setobjs2s = function(L, newidx, oldidx) { L.stack[newidx] = L.stack[oldidx]; }; +/* to stack (not from same stack) */ +const setobj2s = function(L, newidx, oldtv) { + L.stack[newidx] = new TValue(oldtv.type, oldtv.value); +}; const luaO_nilobject = new TValue(CT.LUA_TNIL, null); Object.freeze(luaO_nilobject); @@ -673,3 +677,4 @@ module.exports.luaO_utf8desc = luaO_utf8desc; module.exports.luaO_utf8esc = luaO_utf8esc; module.exports.numarith = numarith; module.exports.setobjs2s = setobjs2s; +module.exports.setobj2s = setobj2s; 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 041dd19..c3efc1e 100644 --- a/src/ltm.js +++ b/src/ltm.js @@ -110,13 +110,13 @@ const luaT_objtypename = function(L, o) { const luaT_callTM = function(L, f, p1, p2, p3, hasres) { 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 */ + 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; if (!hasres) /* no result? 'p3' is third argument */ - L.stack[L.top++] = new lobject.TValue(p3.type, p3.value); /* 3rd argument */ + lobject.setobj2s(L, L.top++, p3); /* 3rd argument */ if (L.ci.callstatus & lstate.CIST_LUA) ldo.luaD_call(L, func, hasres); diff --git a/src/lvm.js b/src/lvm.js index 602fe5c..c7bb7ad 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -126,13 +126,13 @@ const luaV_execute = function(L) { } 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: { @@ -150,7 +150,7 @@ const luaV_execute = function(L) { } 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: { @@ -1033,7 +1033,7 @@ 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 */ -- cgit v1.2.3-70-g09d2 From 941e38fe2360fc0b4fa6f4ef5c9a9a43c172d528 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 17:38:15 +1000 Subject: src/lvm.js: Use setobjs2s in luaV_finishOp's OP_CONCAT case --- src/lvm.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lvm.js b/src/lvm.js index c7bb7ad..ecacd92 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -54,14 +54,13 @@ 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]; + lobject.setobjs2s(L, ci.l_base + inst.A, L.top - 1); L.top = ci.top; /* restore top */ break; } -- cgit v1.2.3-70-g09d2 From 78f764030414e5c45ea059a5f582885da0282e39 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 18:02:28 +1000 Subject: Introduce setsvalue2s --- src/lapi.js | 35 ++++++++++++++++++----------------- src/ldo.js | 7 ++++--- src/lobject.js | 12 ++++++++---- src/lvm.js | 4 ++-- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index 2cf3a1c..8b2e164 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -235,9 +235,9 @@ 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 = lstring.luaS_bless(L, s.slice(0, len)); + lobject.setsvalue2s(L, L.top, ts); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); return ts.value; @@ -249,9 +249,9 @@ const lua_pushstring = function (L, s) { 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)); + let ts = lstring.luaS_new(L, s); + lobject.setsvalue2s(L, L.top, ts); } - L.top++; assert(L.top <= L.ci.top, "stack overflow"); @@ -350,11 +350,11 @@ 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.setsvalue2s(L, L.top, str); /* push 'str' (to make it a TValue) */ + 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 */ delete L.stack[--L.top]; @@ -461,13 +461,11 @@ 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.setsvalue2s(L, L.top, str); + 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(); }; @@ -649,7 +647,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(); }; @@ -663,7 +662,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(); }; @@ -1041,7 +1041,8 @@ 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.setsvalue2s(L, L.top, lstring.luaS_newliteral(L, [])); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); } }; diff --git a/src/ldo.js b/src/ldo.js index 5fa51db..b32e404 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -24,11 +24,11 @@ const TS = defs.thread_status; const seterrorobj = function(L, errcode, oldtop) { 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: { @@ -465,7 +465,8 @@ const recover = function(L, status) { */ 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 */ + lobject.setsvalue2s(L, L.top, lstring.luaS_newliteral(L, msg)); /* push error message */ + L.top++; assert(L.top <= L.ci.top, "stack overflow"); return TS.LUA_ERRRUN; }; diff --git a/src/lobject.js b/src/lobject.js index 3a442ee..ee7a51d 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -193,6 +193,9 @@ const setobjs2s = function(L, newidx, oldidx) { const setobj2s = function(L, newidx, oldtv) { L.stack[newidx] = new TValue(oldtv.type, oldtv.value); }; +const setsvalue2s = function(L, newidx, ts) { + L.stack[newidx] = new TValue(CT.LUA_TLNGSTR, ts); +}; const luaO_nilobject = new TValue(CT.LUA_TNIL, null); Object.freeze(luaO_nilobject); @@ -486,12 +489,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) { + setsvalue2s(L, L.top, lstring.luaS_new(L, str)); ldo.luaD_inctop(L); - L.stack[L.top-1] = new TValue(CT.LUA_TLNGSTR, lstring.luaS_new(L, str)); }; const luaO_pushvfstring = function(L, fmt, argp) { @@ -519,11 +522,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++]; @@ -678,3 +681,4 @@ module.exports.luaO_utf8esc = luaO_utf8esc; module.exports.numarith = numarith; module.exports.setobjs2s = setobjs2s; module.exports.setobj2s = setobj2s; +module.exports.setsvalue2s = setsvalue2s; diff --git a/src/lvm.js b/src/lvm.js index ecacd92..b9c2972 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -967,7 +967,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; } @@ -1011,7 +1011,7 @@ const luaV_concat = function(L, total) { 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 */ -- cgit v1.2.3-70-g09d2 From cc371ddf515fc40d7fbbb8a4e4040673de127c50 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 18:02:56 +1000 Subject: src/lapi.js: Ignore 's' when lua_pushlstring is passed 0 --- src/lapi.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index 8b2e164..2341722 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -232,10 +232,14 @@ const lua_pushinteger = function(L, n) { }; const lua_pushlstring = function(L, s, len) { - assert(Array.isArray(s), "lua_pushlstring expects array of byte"); assert(typeof len === "number"); - - let ts = lstring.luaS_bless(L, s.slice(0, len)); + 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.setsvalue2s(L, L.top, ts); L.top++; assert(L.top <= L.ci.top, "stack overflow"); -- cgit v1.2.3-70-g09d2 From a8972da5384812ab71157ced89c6b5df6da14132 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 18:03:14 +1000 Subject: src/lapi.js: lua_pushstring should return internal copy --- src/lapi.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lapi.js b/src/lapi.js index 2341722..e9994f5 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -255,6 +255,7 @@ const lua_pushstring = function (L, s) { else { let ts = lstring.luaS_new(L, s); lobject.setsvalue2s(L, L.top, ts); + s = ts.getstr(); /* internal copy */ } L.top++; assert(L.top <= L.ci.top, "stack overflow"); -- cgit v1.2.3-70-g09d2 From 4034ef458697729d1a8a25058b43272ae5882ce2 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 18:03:35 +1000 Subject: src/lapi.js: Fix incorrect argument to luaS_newliteral in lua_concat --- src/lapi.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lapi.js b/src/lapi.js index e9994f5..a1dc542 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -1046,7 +1046,7 @@ 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_newliteral(L, [])); + lobject.setsvalue2s(L, L.top, lstring.luaS_bless(L, [])); L.top++; assert(L.top <= L.ci.top, "stack overflow"); } -- cgit v1.2.3-70-g09d2 From 018f9cd8bbff126b7381bafa135e8127033c2faa Mon Sep 17 00:00:00 2001 From: daurnimator Date: Wed, 24 May 2017 14:14:58 +1000 Subject: Keep api_incr_top macro contents distinct - Don't have postincrement in a previous expression - Fix a couple of places the assert was missing --- src/lapi.js | 57 ++++++++++++++++++++++++++++++++------------------------- src/ldebug.js | 6 ++++-- src/lstate.js | 3 ++- 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index a1dc542..0cad44a 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -210,24 +210,23 @@ 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"); }; @@ -323,21 +322,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; }; @@ -413,7 +412,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 */ @@ -503,8 +503,8 @@ const lua_rawget = function(L, idx) { // 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"); }; @@ -514,10 +514,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; }; @@ -596,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; } @@ -608,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(); }; @@ -626,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(); @@ -767,7 +769,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; @@ -801,7 +805,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; } @@ -894,6 +899,7 @@ const lua_arith = function(L, op) { assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); lobject.setobjs2s(L, L.top, L.top - 1); L.top++; + 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]); @@ -1054,7 +1060,8 @@ const lua_concat = function(L, n) { const lua_len = function(L, idx) { let t = index2addr(L, idx); - lvm.luaV_objlen(L, L.top++, t); + lvm.luaV_objlen(L, L.top, t); + L.top++; assert(L.top <= L.ci.top, "stack overflow"); }; diff --git a/src/ldebug.js b/src/ldebug.js index e78d3e7..2a9ada6 100644 --- a/src/ldebug.js +++ b/src/ldebug.js @@ -183,12 +183,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++) diff --git a/src/lstate.js b/src/lstate.js index 2413574..b7a11bc 100644 --- a/src/lstate.js +++ b/src/lstate.js @@ -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; -- cgit v1.2.3-70-g09d2 From ebbfaf9602a624e1c8eb39e88661fadc56996c4b Mon Sep 17 00:00:00 2001 From: daurnimator Date: Wed, 24 May 2017 14:18:59 +1000 Subject: src/lapi.js: Sync lua_pushliteral implementation with lua_pushstring --- src/lapi.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index 0cad44a..9b10d94 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -272,16 +272,17 @@ 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) 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; + let ts = lstring.luaS_newliteral(L, s); + lobject.setsvalue2s(L, L.top, ts); + s = ts.getstr(); /* internal copy */ } - L.top++; assert(L.top <= L.ci.top, "stack overflow"); -- cgit v1.2.3-70-g09d2 From bb6dc6106cd1d9aedc0e9554928da6d232309a1a Mon Sep 17 00:00:00 2001 From: daurnimator Date: Wed, 24 May 2017 16:38:03 +1000 Subject: Introduce chgfltvalue and chgivalue --- src/lobject.js | 10 ++++++++++ src/lvm.js | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/lobject.js b/src/lobject.js index ee7a51d..54d4de9 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; diff --git a/src/lvm.js b/src/lvm.js index b9c2972..2786306 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -520,7 +520,7 @@ 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].chgivalue(idx); /* update internal index... */ L.stack[ra + 3] = new lobject.TValue(CT.LUA_TNUMINT, idx); } } else { /* floating loop */ @@ -530,7 +530,7 @@ 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].chgfltvalue(idx); /* update internal index... */ L.stack[ra + 3] = new lobject.TValue(CT.LUA_TNUMFLT, idx); } } -- cgit v1.2.3-70-g09d2 From 35754b22d6130971a9d0b51177bfcb7c401bb196 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Wed, 24 May 2017 16:43:47 +1000 Subject: src/lobject.js: Introduce TValue.set*value for missing types --- src/lobject.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/lobject.js b/src/lobject.js index 54d4de9..aec7109 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -161,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; -- cgit v1.2.3-70-g09d2 From 1428582c2d88b23f12c87921381796d03b388d9f Mon Sep 17 00:00:00 2001 From: daurnimator Date: Wed, 24 May 2017 16:44:48 +1000 Subject: Use .setclLvalue --- src/lparser.js | 2 +- src/lundump.js | 2 +- src/lvm.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lparser.js b/src/lparser.js index 13f75c9..96bad67 100644 --- a/src/lparser.js +++ b/src/lparser.js @@ -1565,7 +1565,7 @@ 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); diff --git a/src/lundump.js b/src/lundump.js index 4931fe8..5686430 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] = new lobject.TValue(defs.CT.LUA_TLCL, 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 2786306..e308807 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -943,7 +943,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); -- cgit v1.2.3-70-g09d2 From ed0518f417a61b32e531f85c434b8024859202cd Mon Sep 17 00:00:00 2001 From: daurnimator Date: Wed, 24 May 2017 20:44:34 +1000 Subject: Modify stack values up to L.top instead of replacing --- src/lapi.js | 98 +++++++++++----------- src/ldebug.js | 21 ++--- src/ldo.js | 79 +++++++++++++----- src/lobject.js | 28 ++++--- src/lparser.js | 4 +- src/lstate.js | 2 +- src/ltm.js | 18 ++-- src/lundump.js | 2 +- src/lvm.js | 257 +++++++++++++++++++++++++++++++++++++++------------------ 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; i0) + --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 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]' */ -- cgit v1.2.3-70-g09d2 From 63446e402d2aa70bb53cbc40563edafb6383cf5d Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 26 May 2017 15:54:47 +1000 Subject: Have ltm.luaT_callorderTM return a boolean --- src/ltm.js | 6 +++--- src/lvm.js | 14 ++++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/ltm.js b/src/ltm.js index 8f4908c..88f25fb 100644 --- a/src/ltm.js +++ b/src/ltm.js @@ -159,11 +159,11 @@ const luaT_trybinTM = function(L, p1, p2, res, event) { }; const luaT_callorderTM = function(L, p1, p2, event) { - let res = new lobject.TValue(CT.LUA_TNIL, null); + let res = new lobject.TValue(); if (!luaT_callbinTM(L, p1, p2, res, event)) - return -1; + return null; else - return res.l_isfalse() ? 0 : 1; + return !res.l_isfalse(); }; const fasttm = function(l, et, e) { diff --git a/src/lvm.js b/src/lvm.js index 724f689..9bbe768 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -752,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) { -- cgit v1.2.3-70-g09d2 From d19e7de4602f180e700f237f64b5669605d232b4 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 26 May 2017 15:55:45 +1000 Subject: src/lauxlib.js: In luaL_loadfilex only wrap the fs library calls in try/catch --- src/lauxlib.js | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) 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) { -- cgit v1.2.3-70-g09d2 From 7807868d67aa6f24a22eff2a62964a1bafb05ac7 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 26 May 2017 16:32:03 +1000 Subject: src/ldo.js: Don't export functions we don't need elsewhere --- src/ldo.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ldo.js b/src/ldo.js index 464d373..84bf2b6 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -693,8 +693,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; @@ -712,6 +710,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; -- cgit v1.2.3-70-g09d2 From 290704d7bd80907d7442f50b0bd56fdd2794107e Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 26 May 2017 16:55:37 +1000 Subject: src/ldo.js: Make sure to extend stack before assigning in seterrorobj --- src/ldo.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/ldo.js b/src/ldo.js index 84bf2b6..4c53f11 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -22,6 +22,12 @@ 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: { lobject.setsvalue2s(L, oldtop, lstring.luaS_newliteral(L, "not enough memory")); @@ -32,17 +38,12 @@ const seterrorobj = function(L, errcode, oldtop) { break; } default: { - lobject.setobjs2s(L, oldtop, L.top - 1); + lobject.setobjs2s(L, oldtop, current_top - 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]; - } + while (L.top > oldtop + 1) + delete L.stack[--L.top]; }; const ERRORSTACKSIZE = luaconf.LUAI_MAXSTACK + 200; -- cgit v1.2.3-70-g09d2 From 183768f08070003691f206ac16cb2310a7b4fa90 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 26 May 2017 17:06:55 +1000 Subject: src/lapi.js: Use a temporary variable in lua_len --- src/lapi.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index a8e0c82..e323e4f 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -1060,8 +1060,9 @@ const lua_concat = function(L, n) { const lua_len = function(L, idx) { let t = index2addr(L, idx); - L.stack[L.top] = new TValue(); - lvm.luaV_objlen(L, L.stack[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"); }; -- cgit v1.2.3-70-g09d2