diff options
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | src/ldebug.js | 21 | ||||
-rw-r--r-- | src/ldo.js | 45 | ||||
-rw-r--r-- | src/loadlib.js | 3 | ||||
-rw-r--r-- | src/lstate.js | 82 | ||||
-rw-r--r-- | src/lstrlib.js | 2 | ||||
-rw-r--r-- | src/lvm.js | 54 |
7 files changed, 104 insertions, 104 deletions
@@ -44,7 +44,6 @@ - [ ] `file:flush()` - [ ] `file:lines()` - [ ] `file:read()` - - [ ] `file:read()` - [ ] `file:setvbuf()` - [ ] `file:__gc()` - [ ] C API diff --git a/src/ldebug.js b/src/ldebug.js index 5b537c2..13b9da7 100644 --- a/src/ldebug.js +++ b/src/ldebug.js @@ -17,8 +17,13 @@ const lvm = require('./lvm.js'); const CT = defs.constant_types; const TS = defs.thread_status; +const currentpc = function(ci) { + assert(ci.callstatus & lstate.CIST_LUA); + return ci.l_savedpc - 1; +}; + const currentline = function(ci) { - return ci.func.value.p.lineinfo ? ci.func.value.p.lineinfo[ci.pcOff-1] : -1; + return ci.func.value.p.lineinfo ? ci.func.value.p.lineinfo[currentpc(ci)] : -1; }; /* @@ -43,7 +48,7 @@ const lua_sethook = function(L, func, mask, count) { func = null; } if (L.ci.callstatus & lstate.CIST_LUA) - L.oldpc = L.ci.pcOff; + L.oldpc = L.ci.l_savedpc; L.hook = func; L.basehookcount = count; L.hookcount = L.basehookcount; @@ -105,7 +110,7 @@ const findlocal = function(L, ci, n) { return findvararg(ci, -n); else { base = ci.l_base; - name = lfunc.luaF_getlocalname(ci.func.value.p, n, ci.pcOff); + name = lfunc.luaF_getlocalname(ci.func.value.p, n, currentpc(ci)); } } else base = ci.funcOff + 1; @@ -439,7 +444,7 @@ const funcnamefromcode = function(L, ci) { let tm = 0; /* (initial value avoids warnings) */ let p = ci.func.value.p; /* calling function */ - let pc = ci.pcOff - 1; /* calling instruction index */ + let pc = currentpc(ci); /* calling instruction index */ let i = p.code[pc]; /* calling instruction */ if (ci.callstatus & lstate.CIST_HOOKED) { @@ -529,7 +534,7 @@ const varinfo = function(L, o) { kind = getupvalname(L, ci, o); /* check whether 'o' is an upvalue */ let stkid = isinstack(L, ci, o); if (!kind && stkid) /* no? try a register */ - kind = getobjname(ci.func.value.p, ci.pcOff - 1, stkid - ci.l_base); + kind = getobjname(ci.func.value.p, currentpc(ci), stkid - ci.l_base); } return kind ? lobject.luaO_pushfstring(L, defs.to_luastring(" (%s '%s')", true), kind.funcname, kind.name) : defs.to_luastring("", true); @@ -620,14 +625,14 @@ const luaG_traceexec = function(L) { ldo.luaD_hook(L, defs.LUA_HOOKCOUNT, -1); /* call count hook */ if (mask & defs.LUA_MASKLINE) { let p = ci.func.value.p; - let npc = ci.pcOff; // pcRel(ci.u.l.savedpc, p); + let npc = ci.l_savedpc; // pcRel(ci.u.l.savedpc, p); let newline = p.lineinfo ? p.lineinfo[npc] : -1; if (npc === 0 || /* call linehook when enter a new function, */ - ci.pcOff <= L.oldpc || /* when jump back (loop), or when */ + ci.l_savedpc <= L.oldpc || /* when jump back (loop), or when */ newline !== p.lineinfo ? p.lineinfo[L.oldpc] : -1) /* enter a new line */ ldo.luaD_hook(L, defs.LUA_HOOKLINE, newline); /* call line hook */ } - L.oldpc = ci.pcOff; + L.oldpc = ci.l_savedpc; if (L.status === TS.LUA_YIELD) { /* did hook yield? */ if (counthook) L.hookcount = 1; /* undo decrement to zero */ @@ -47,30 +47,16 @@ const seterrorobj = function(L, errcode, oldtop) { */ const luaD_precall = function(L, off, nresults) { let func = L.stack[off]; - let ci; switch(func.type) { case CT.LUA_TCCL: case CT.LUA_TLCF: { let f = func.type === CT.LUA_TCCL ? func.value.f : func.value; - // next_ci - if (L.ci.next) { - L.ci = L.ci.next; - ci = L.ci; - } else { - ci = new lstate.CallInfo(off); - L.ci.next = ci; - ci.previous = L.ci; - ci.next = null; - - L.ci = ci; - L.ciOff++; - } - + let ci = lstate.luaE_extendCI(L); + ci.funcOff = off; ci.nresults = nresults; ci.func = func; - ci.funcOff = off; ci.top = L.top + defs.LUA_MINSTACK; ci.callstatus = 0; if (L.hookmask & defs.LUA_MASKCALL) @@ -98,27 +84,14 @@ const luaD_precall = function(L, off, nresults) { base = off + 1; } - // next_ci - if (L.ci.next) { - L.ci = L.ci.next; - ci = L.ci; - } else { - ci = new lstate.CallInfo(off); - L.ci.next = ci; - ci.previous = L.ci; - ci.next = null; - - L.ci = ci; - L.ciOff++; - } + let ci = lstate.luaE_extendCI(L); + ci.funcOff = off; ci.nresults = nresults; ci.func = func; - ci.funcOff = off; ci.l_base = base; - ci.top = base + fsize; - L.top = ci.top; - ci.l_savedpc = p.code; - ci.pcOff = 0; + L.top = ci.top = base + fsize; + ci.l_code = p.code; + ci.l_savedpc = 0; ci.callstatus = lstate.CIST_LUA; return false; @@ -135,12 +108,12 @@ const luaD_poscall = function(L, ci, firstResult, nres) { if (L.hookmask & (defs.LUA_MASKRET | defs.LUA_MASKLINE)) { if (L.hookmask & defs.LUA_MASKRET) luaD_hook(L, defs.LUA_HOOKRET, -1); - L.oldpc = ci.previous.pcOff; /* 'oldpc' for caller function */ + L.oldpc = ci.previous.l_savedpc; /* 'oldpc' for caller function */ } let res = ci.funcOff; L.ci = ci.previous; - L.ciOff--; + L.ci.next = null; return moveresults(L, firstResult, res, nres, wanted); }; diff --git a/src/loadlib.js b/src/loadlib.js index c70e7f9..c43f498 100644 --- a/src/loadlib.js +++ b/src/loadlib.js @@ -88,12 +88,11 @@ if (!WEB) { try { fd = fs.openSync(lua.to_jsstring(filename), 'r'); + fs.closeSync(fd); } catch (e) { return false; } - fs.closeSync(fd); - return true; }; } diff --git a/src/lstate.js b/src/lstate.js index 664ef27..7d7ff80 100644 --- a/src/lstate.js +++ b/src/lstate.js @@ -18,24 +18,24 @@ const BASIC_STACK_SIZE = 2 * defs.LUA_MINSTACK; class CallInfo { - constructor(funcOff, func, top, base, previous, next) { - this.func = func; - this.funcOff = funcOff; - this.top = top; - this.previous = previous; - this.next = next; - this.pcOff = 0; + constructor() { + this.func = null; + this.funcOff = NaN; + this.top = NaN; + this.previous = null; + this.next = null; /* only for Lua functions */ - this.l_base = base; /* base for this function */ - this.l_savedpc = []; + this.l_base = NaN; /* base for this function */ + this.l_code = null; /* reference to this.func.p.code */ + this.l_savedpc = NaN; /* offset into l_code */ /* only for JS functions */ this.c_k = null; /* continuation in case of yields */ this.c_old_errfunc = null; this.c_ctx = null; /* context info. in case of yields */ - this.nresults = 0; - this.callstatus = 0; + this.nresults = NaN; + this.callstatus = NaN; } } @@ -47,7 +47,6 @@ class lua_State { this.base_ci = new CallInfo(); // Will be populated later this.top = 0; this.ci = null; - this.ciOff = null; this.stack = []; this.openupval = null; this.status = TS.LUA_OK; @@ -74,6 +73,19 @@ class global_State { } +const luaE_extendCI = function(L) { + let ci = new CallInfo(); + L.ci.next = ci; + ci.previous = L.ci; + ci.next = null; + L.ci = ci; + return ci; +}; + +const luaE_freeCI = function(L) { + let ci = L.ci; + ci.next = null; +}; const stack_init = function(L1, L) { L1.stack = new Array(BASIC_STACK_SIZE); // TODO: for now we don't care about the stack size @@ -88,6 +100,12 @@ const stack_init = function(L1, L) { L1.ci = ci; }; +const freestack = function(L) { + L.ci = L.base_ci; + luaE_freeCI(L); + L.stack = null; +}; + /* ** Create registry table and its predefined values */ @@ -113,9 +131,8 @@ const f_luaopen = function(L) { const preinit_thread = function(L, g) { L.id = g.id_counter++; L.l_G = g; - L.stack = []; + L.stack = null; L.ci = null; - L.nci = 0; L.errorJmp = null; L.nCcalls = 0; L.hook = null; @@ -143,6 +160,11 @@ const lua_newthread = function(L) { return L1; }; +const luaE_freethread = function(L, L1) { + lfunc.luaF_close(L1, L1.stack); + freestack(L1); +}; + const lua_newstate = function() { let L = new lua_State(); let g = new global_State(L); @@ -158,6 +180,7 @@ const lua_newstate = function() { const close_state = function(L) { lfunc.luaF_close(L, L.stack); /* close all upvalues for this thread */ + freestack(L); }; const lua_close = function(L) { @@ -165,17 +188,20 @@ const lua_close = function(L) { close_state(L); }; -module.exports.lua_State = lua_State; -module.exports.CallInfo = CallInfo; -module.exports.CIST_OAH = (1<<0); /* original value of 'allowhook' */ -module.exports.CIST_LUA = (1<<1); /* call is running a Lua function */ -module.exports.CIST_HOOKED = (1<<2); /* call is running a debug hook */ -module.exports.CIST_FRESH = (1<<3); /* call is running on a fresh invocation of luaV_execute */ -module.exports.CIST_YPCALL = (1<<4); /* call is a yieldable protected call */ -module.exports.CIST_TAIL = (1<<5); /* call was tail called */ -module.exports.CIST_HOOKYIELD = (1<<6); /* last hook called yielded */ -module.exports.CIST_LEQ = (1<<7); /* using __lt for __le */ -module.exports.CIST_FIN = (1<<8); /* call is running a finalizer */ -module.exports.lua_close = lua_close; -module.exports.lua_newstate = lua_newstate; -module.exports.lua_newthread = lua_newthread; +module.exports.lua_State = lua_State; +module.exports.CallInfo = CallInfo; +module.exports.CIST_OAH = (1<<0); /* original value of 'allowhook' */ +module.exports.CIST_LUA = (1<<1); /* call is running a Lua function */ +module.exports.CIST_HOOKED = (1<<2); /* call is running a debug hook */ +module.exports.CIST_FRESH = (1<<3); /* call is running on a fresh invocation of luaV_execute */ +module.exports.CIST_YPCALL = (1<<4); /* call is a yieldable protected call */ +module.exports.CIST_TAIL = (1<<5); /* call was tail called */ +module.exports.CIST_HOOKYIELD = (1<<6); /* last hook called yielded */ +module.exports.CIST_LEQ = (1<<7); /* using __lt for __le */ +module.exports.CIST_FIN = (1<<8); /* call is running a finalizer */ +module.exports.lua_close = lua_close; +module.exports.lua_newstate = lua_newstate; +module.exports.lua_newthread = lua_newthread; +module.exports.luaE_extendCI = luaE_extendCI; +module.exports.luaE_freeCI = luaE_freeCI; +module.exports.luaE_freethread = luaE_freethread; diff --git a/src/lstrlib.js b/src/lstrlib.js index 2eb9ff5..9a75b78 100644 --- a/src/lstrlib.js +++ b/src/lstrlib.js @@ -449,7 +449,7 @@ const getoption = function(h, fmt) { case 'H'.charCodeAt(0): r.size = 2; r.opt = KOption.Kuint; return r; case 'l'.charCodeAt(0): r.size = 8; r.opt = KOption.Kint; return r; // sizeof(long): 8 case 'L'.charCodeAt(0): r.size = 8; r.opt = KOption.Kuint; return r; - case 'j'.charCodeAt(0): r.size = 4; r.opt = KOption.Kint; return r; // sizeof(lua_Integer): 8 + case 'j'.charCodeAt(0): r.size = 4; r.opt = KOption.Kint; return r; // sizeof(lua_Integer): 4 case 'J'.charCodeAt(0): r.size = 8; r.opt = KOption.Kuint; return r; case 'T'.charCodeAt(0): r.size = 8; r.opt = KOption.Kuint; return r; // sizeof(size_t): 8 case 'f'.charCodeAt(0): r.size = 4; r.opt = KOption.Kfloat; return r; // sizeof(float): 4 @@ -25,7 +25,7 @@ const luaV_finishOp = function(L) { let ci = L.ci; let OCi = lopcodes.OpCodesI; let base = ci.l_base; - let inst = ci.l_savedpc[ci.pcOff - 1]; /* interrupted instruction */ + let inst = ci.l_code[ci.l_savedpc - 1]; /* interrupted instruction */ let op = inst.opcode; switch (op) { /* finish its execution */ @@ -45,9 +45,9 @@ const luaV_finishOp = function(L) { ci.callstatus ^= lstate.CIST_LEQ; /* clear mark */ res = res !== 1 ? 1 : 0; /* negate result */ } - assert(ci.l_savedpc[ci.pcOff] === OCi.OP_JMP); + assert(ci.l_code[ci.l_savedpc] === OCi.OP_JMP); if (res !== inst.A) /* condition failed? */ - ci.pcOff++; /* skip jump instruction */ + ci.l_savedpc++; /* skip jump instruction */ break; } case OCi.OP_CONCAT: { @@ -66,7 +66,7 @@ const luaV_finishOp = function(L) { break; } case OCi.OP_TFORCALL: { - assert(ci.l_savedpc[ci.pcOff] === OCi.OP_TFORLOOP); + assert(ci.l_code[ci.l_savedpc] === OCi.OP_TFORLOOP); L.top = ci.top; /* correct top */ break; } @@ -110,7 +110,7 @@ const luaV_execute = function(L) { let k = cl.p.k; let base = ci.l_base; - let i = ci.l_savedpc[ci.pcOff++]; + let i = ci.l_code[ci.l_savedpc++]; if (L.hookmask & (defs.LUA_MASKLINE | defs.LUA_MASKCOUNT)) { ldebug.luaG_traceexec(L); @@ -130,8 +130,8 @@ const luaV_execute = function(L) { break; } case OCi.OP_LOADKX: { - assert(ci.l_savedpc[ci.pcOff].opcode === OCi.OP_EXTRAARG); - let konst = k[ci.l_savedpc[ci.pcOff++].Ax]; + 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); break; } @@ -139,7 +139,7 @@ const luaV_execute = function(L) { L.stack[ra] = new lobject.TValue(CT.LUA_TBOOLEAN, i.B !== 0); if (i.C !== 0) - ci.pcOff++; /* skip next instruction (if C) */ + ci.l_savedpc++; /* skip next instruction (if C) */ break; } @@ -420,28 +420,28 @@ const luaV_execute = function(L) { } case OCi.OP_EQ: { if (luaV_equalobj(L, RKB(L, base, k, i), RKC(L, base, k, i)) !== i.A) - ci.pcOff++; + ci.l_savedpc++; else donextjump(L, ci); break; } case OCi.OP_LT: { if (luaV_lessthan(L, RKB(L, base, k, i), RKC(L, base, k, i)) !== i.A) - ci.pcOff++; + ci.l_savedpc++; else donextjump(L, ci); break; } case OCi.OP_LE: { if (luaV_lessequal(L, RKB(L, base, k, i), RKC(L, base, k, i)) !== i.A) - ci.pcOff++; + ci.l_savedpc++; else donextjump(L, ci); break; } case OCi.OP_TEST: { if (i.C ? L.stack[ra].l_isfalse() : !L.stack[ra].l_isfalse()) - ci.pcOff++; + ci.l_savedpc++; else donextjump(L, ci); break; @@ -449,7 +449,7 @@ const luaV_execute = function(L) { case OCi.OP_TESTSET: { let rb = L.stack[RB(L, base, i)]; if (i.C ? rb.l_isfalse() : !rb.l_isfalse()) - ci.pcOff++; + ci.l_savedpc++; else { L.stack[ra] = rb; donextjump(L, ci); @@ -489,14 +489,12 @@ const luaV_execute = function(L) { L.stack[ofuncOff + aux] = L.stack[nfuncOff + aux]; oci.func = nci.func; oci.l_base = ofuncOff + (nci.l_base - nfuncOff); - L.top = ofuncOff + (L.top - nfuncOff); - oci.top = L.top; + oci.top = L.top = ofuncOff + (L.top - nfuncOff); + oci.l_code = nci.l_code; oci.l_savedpc = nci.l_savedpc; - oci.pcOff = nci.pcOff; oci.callstatus |= lstate.CIST_TAIL; - L.ci = oci; - ci = L.ci; - L.ciOff--; + oci.next = null; + ci = L.ci = oci; assert(L.top === oci.l_base + L.stack[ofuncOff].value.p.maxstacksize); @@ -523,7 +521,7 @@ const luaV_execute = function(L) { let limit = L.stack[ra + 1].value; if (0 < step ? idx <= limit : limit <= idx) { - ci.pcOff += i.sBx; + ci.l_savedpc += i.sBx; L.stack[ra].value = idx; L.stack[ra + 3] = new lobject.TValue(CT.LUA_TNUMINT, idx); // TODO: if tvalue already there, just update it } @@ -534,7 +532,7 @@ const luaV_execute = function(L) { // TODO: luai_numlt, luai_numle if (0 < step ? idx <= limit : limit <= idx) { - ci.pcOff += i.sBx; + ci.l_savedpc += i.sBx; L.stack[ra].value = idx; L.stack[ra + 3] = new lobject.TValue(CT.LUA_TNUMFLT, idx); // TODO: if tvalue already there, just update it } @@ -575,7 +573,7 @@ const luaV_execute = function(L) { init.value = ninit - nstep; } - ci.pcOff += i.sBx; + ci.l_savedpc += i.sBx; break; } case OCi.OP_TFORCALL: { @@ -587,7 +585,7 @@ const luaV_execute = function(L) { ldo.luaD_call(L, cb, i.C); /* go straight to OP_TFORLOOP */ L.top = ci.top; - i = ci.l_savedpc[ci.pcOff++]; + i = ci.l_code[ci.l_savedpc++]; ra = RA(L, base, i); assert(i.opcode === OCi.OP_TFORLOOP); /* fall through */ @@ -595,7 +593,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 */ - ci.pcOff += i.sBx; /* jump back */ + ci.l_savedpc += i.sBx; /* jump back */ } break; } @@ -606,8 +604,8 @@ const luaV_execute = function(L) { if (n === 0) n = L.top - ra - 1; if (c === 0) { - assert(ci.l_savedpc[ci.pcOff].opcode === OCi.OP_EXTRAARG); - c = ci.l_savedpc[ci.pcOff++].Ax; + assert(ci.l_code[ci.l_savedpc].opcode === OCi.OP_EXTRAARG); + c = ci.l_code[ci.l_savedpc++].Ax; } let h = L.stack[ra].value; @@ -668,11 +666,11 @@ const luaV_execute = function(L) { const dojump = function(L, ci, i, e) { let a = i.A; if (a !== 0) lfunc.luaF_close(L, ci.l_base + a - 1); - ci.pcOff += i.sBx + e; + ci.l_savedpc += i.sBx + e; }; const donextjump = function(L, ci) { - dojump(L, ci, ci.l_savedpc[ci.pcOff], 1); + dojump(L, ci, ci.l_code[ci.l_savedpc], 1); }; |