From b3f5b92b221c0ad8a94b8cb95081bb85d235c39f Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 29 May 2017 13:28:24 +1000 Subject: Have lua closures point to directly to their upvalues on stack --- src/lapi.js | 4 ++-- src/ldebug.js | 2 +- src/lfunc.js | 39 ++++++++++++++++++--------------------- src/lvm.js | 26 ++++++++++---------------- 4 files changed, 31 insertions(+), 40 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index f24c4af..529a009 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -538,7 +538,7 @@ const aux_upvalue = function(L, fi, n) { let name = p.upvalues[n-1].name; return { name: name ? name.getstr() : defs.to_luastring("(*no name)", true), - val: f.upvals[n-1].val() + val: f.upvals[n-1].v }; } default: return null; /* not a closure */ @@ -926,7 +926,7 @@ const lua_load = function(L, reader, data, chunkname, mode) { /* get global table from registry */ let gt = ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS); /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ - f.upvals[0].value.setfrom(gt); + f.upvals[0].v.setfrom(gt); } } return status; diff --git a/src/ldebug.js b/src/ldebug.js index 45d126f..510221f 100644 --- a/src/ldebug.js +++ b/src/ldebug.js @@ -518,7 +518,7 @@ const isinstack = function(L, ci, o) { const getupvalname = function(L, ci, o) { let c = ci.func.value; for (let i = 0; i < c.nupvalues; i++) { - if (c.upvals[i].val() === o) { + if (c.upvals[i].v === o) { return { name: upvalname(c.p, i), funcname: defs.to_luastring('upvalue', true) diff --git a/src/lfunc.js b/src/lfunc.js index 663f614..97e5f02 100644 --- a/src/lfunc.js +++ b/src/lfunc.js @@ -30,19 +30,14 @@ class Proto { class UpVal { constructor() { - this.L = null; /* Keep track of the thread it comes from */ - this.v = null; /* if open: stack index. if closed: null (find it in this.value) */ - this.open_next = null; /* linked list (when open) */ + this.v = void 0; /* if open: reference to TValue on stack. if closed: TValue */ + this.vOff = void 0; /* if open: index on stack. if closed: undefined */ this.refcount = 0; - this.value = null; /* the TValue (when closed) */ - } - - val() { - return this.v !== null ? this.L.stack[this.v] : this.value; + this.open_next = null; /* linked list (when open) */ } isopen() { - return this.v !== null; + return this.vOff !== void 0; } } @@ -56,9 +51,9 @@ const luaF_newLclosure = function(L, n) { const luaF_findupval = function(L, level) { let prevp; let p = L.openupval; - while (p !== null && p.v >= level) { + while (p !== null && p.vOff >= level) { assert(p.isopen()); - if (p.v === level) /* found a corresponding upvalue? */ + if (p.vOff === level) /* found a corresponding upvalue? */ return p; /* return it */ prevp = p; p = p.open_next; @@ -71,23 +66,25 @@ const luaF_findupval = function(L, level) { prevp.open_next = uv; else L.openupval = uv; - /* current value lives in the stack */ - uv.L = L; - uv.v = level; + uv.v = L.stack[level]; /* current value lives in the stack */ + uv.vOff = level; return uv; }; const luaF_close = function(L, level) { - while (L.openupval !== null && L.openupval.v >= level) { + while (L.openupval !== null && L.openupval.vOff >= level) { let uv = L.openupval; assert(uv.isopen()); L.openupval = uv.open_next; /* remove from 'open' list */ - if (uv.refcount > 0) { - let from = uv.L.stack[uv.v]; - uv.L = null; - uv.v = null; - uv.value = new lobject.TValue(from.type, from.value); + if (uv.refcount === 0) { /* no references? */ + /* free upvalue */ + uv.v = void 0; + uv.open_next = null; + } else { + let from = uv.v; + uv.v = new lobject.TValue(from.type, from.value); } + uv.vOff = void 0; } }; @@ -98,7 +95,7 @@ const luaF_initupvals = function(L, cl) { for (let i = 0; i < cl.nupvalues; i++) { let uv = new UpVal(L); uv.refcount = 1; - uv.value = new lobject.TValue(CT.LUA_TNIL, null); + uv.v = new lobject.TValue(CT.LUA_TNIL, null); cl.upvals[i] = uv; } }; diff --git a/src/lvm.js b/src/lvm.js index af8984f..b7b1358 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -171,32 +171,26 @@ const luaV_execute = function(L) { break; } case OCi.OP_GETUPVAL: { - let o = cl.upvals[i.B].val(); - lobject.setobj2s(L, ra, o); + let b = i.B; + lobject.setobj2s(L, ra, cl.upvals[b].v); break; } case OCi.OP_SETUPVAL: { let uv = cl.upvals[i.B]; - if (uv.isopen()) { - uv.L.stack[uv.v].setfrom(L.stack[ra]); - } else { - uv.value.setfrom(L.stack[ra]); - } + uv.v.setfrom(L.stack[ra]); break; } case OCi.OP_GETTABUP: { - let table = cl.upvals[i.B].val(); - let key = RKC(L, base, k, i); - - gettable(L, table, key, ra); + let upval = cl.upvals[i.B].v; + let rc = RKC(L, base, k, i); + gettable(L, upval, rc, ra); break; } case OCi.OP_SETTABUP: { - let table = cl.upvals[i.A].val(); - let key = RKB(L, base, k, i); - let v = RKC(L, base, k, i); - - settable(L, table, key, v); + let upval = cl.upvals[i.A].v; + let rb = RKB(L, base, k, i); + let rc = RKC(L, base, k, i); + settable(L, upval, rb, rc); break; } case OCi.OP_GETTABLE: { -- cgit v1.2.3-70-g09d2