summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaurnimator <quae@daurnimator.com>2018-01-29 19:01:22 +1100
committerdaurnimator <quae@daurnimator.com>2018-01-29 22:07:00 +1100
commit313f55905253697fe4966f979865296aeaa7a801 (patch)
treea8f060a377d45943952ade62507951cd4555a21b
parent62b07567d9f39fa746ea35d9c08cd1dcf37dc67a (diff)
downloadfengari-313f55905253697fe4966f979865296aeaa7a801.tar.gz
fengari-313f55905253697fe4966f979865296aeaa7a801.tar.bz2
fengari-313f55905253697fe4966f979865296aeaa7a801.zip
src/: Upvalues are now just TValues (possibly referencing on-stack)
- Removes `Upval` class - closing over upvalues is now done by creating new on-stack TValue objects - No more `openupval` linked list With this fix, upvalues from collected coroutines will no longer keep other values alive Closes #44
-rw-r--r--src/lapi.js13
-rw-r--r--src/ldebug.js2
-rw-r--r--src/lfunc.js64
-rw-r--r--src/lobject.js6
-rw-r--r--src/lstate.js4
-rw-r--r--src/lvm.js13
6 files changed, 20 insertions, 82 deletions
diff --git a/src/lapi.js b/src/lapi.js
index ec643b3..8ed67f5 100644
--- a/src/lapi.js
+++ b/src/lapi.js
@@ -32,10 +32,7 @@ const {
from_userstring,
to_luastring,
} = require('./defs.js');
-const {
- api_check,
- lua_assert
-} = require('./llimits.js');
+const { api_check } = require('./llimits.js');
const ldebug = require('./ldebug.js');
const ldo = require('./ldo.js');
const { luaU_dump } = require('./ldump.js');
@@ -555,7 +552,7 @@ const aux_upvalue = function(L, fi, n) {
let name = p.upvalues[n-1].name;
return {
name: name ? name.getstr() : to_luastring("(*no name)", true),
- val: f.upvals[n-1].v
+ val: f.upvals[n-1]
};
}
default: return null; /* not a closure */
@@ -930,7 +927,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, LUA_RIDX_GLOBALS);
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
- f.upvals[0].v.setfrom(gt);
+ f.upvals[0].setfrom(gt);
}
}
return status;
@@ -1111,13 +1108,9 @@ const lua_upvalueid = function(L, fidx, n) {
const lua_upvaluejoin = function(L, fidx1, n1, fidx2, n2) {
let ref1 = getupvalref(L, fidx1, n1);
let ref2 = getupvalref(L, fidx2, n2);
- let up1 = ref1.upval;
let up2 = ref2.upval;
let f1 = ref1.closure;
- lua_assert(up1.refcount > 0);
- up1.refcount--;
f1.upvals[ref1.upvalOff] = up2;
- up2.refcount++;
};
// This functions are only there for compatibility purposes
diff --git a/src/ldebug.js b/src/ldebug.js
index e403ba6..a471c75 100644
--- a/src/ldebug.js
+++ b/src/ldebug.js
@@ -537,7 +537,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].v === o) {
+ if (c.upvals[i] === o) {
return {
name: upvalname(c.p, i),
funcname: to_luastring('upvalue', true)
diff --git a/src/lfunc.js b/src/lfunc.js
index 2f28d0e..198c4b9 100644
--- a/src/lfunc.js
+++ b/src/lfunc.js
@@ -1,7 +1,6 @@
"use strict";
const { constant_types: { LUA_TNIL } } = require('./defs.js');
-const { lua_assert } = require('./llimits.js');
const lobject = require('./lobject.js');
class Proto {
@@ -25,22 +24,6 @@ class Proto {
}
-class UpVal {
-
- constructor(L) {
- this.id = L.l_G.id_counter++;
- 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.open_next = null; /* linked list (when open) */
- }
-
- isopen() {
- return this.vOff !== void 0;
- }
-
-}
-
const luaF_newLclosure = function(L, n) {
let c = new lobject.LClosure(L, n);
return c;
@@ -48,54 +31,24 @@ const luaF_newLclosure = function(L, n) {
const luaF_findupval = function(L, level) {
- let prevp;
- let p = L.openupval;
- while (p !== null && p.vOff >= level) {
- lua_assert(p.isopen());
- if (p.vOff === level) /* found a corresponding upvalue? */
- return p; /* return it */
- prevp = p;
- p = p.open_next;
- }
- /* not found: create a new upvalue */
- let uv = new UpVal(L);
- /* link it to list of open upvalues */
- uv.open_next = p;
- if (prevp)
- prevp.open_next = uv;
- else
- L.openupval = uv;
- uv.v = L.stack[level]; /* current value lives in the stack */
- uv.vOff = level;
- return uv;
+ return L.stack[level];
};
const luaF_close = function(L, level) {
- while (L.openupval !== null && L.openupval.vOff >= level) {
- let uv = L.openupval;
- lua_assert(uv.isopen());
- L.openupval = uv.open_next; /* remove from 'open' list */
- 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;
+ /* Create new TValues on stack;
+ * any closures will keep referencing old TValues */
+ for (let i=level; i<L.top; i++) {
+ let old = L.stack[i];
+ L.stack[i] = new lobject.TValue(old.type, old.value);
}
};
/*
-** fill a closure with new closed upvalues
+** fill a closure with new upvalues
*/
const luaF_initupvals = function(L, cl) {
for (let i = 0; i < cl.nupvalues; i++) {
- let uv = new UpVal(L);
- uv.refcount = 1;
- uv.v = new lobject.TValue(LUA_TNIL, null);
- cl.upvals[i] = uv;
+ cl.upvals[i] = new lobject.TValue(LUA_TNIL, null);
}
};
@@ -117,7 +70,6 @@ const luaF_getlocalname = function(f, local_number, pc) {
module.exports.MAXUPVAL = 255;
module.exports.Proto = Proto;
-module.exports.UpVal = UpVal;
module.exports.luaF_findupval = luaF_findupval;
module.exports.luaF_close = luaF_close;
module.exports.luaF_getlocalname = luaF_getlocalname;
diff --git a/src/lobject.js b/src/lobject.js
index 34d8550..055ccb2 100644
--- a/src/lobject.js
+++ b/src/lobject.js
@@ -48,7 +48,6 @@ const {
} = require('./ljstype.js');
const ldebug = require('./ldebug.js');
const ldo = require('./ldo.js');
-const lfunc = require('./lfunc.js');
const lstate = require('./lstate.js');
const {
luaS_bless,
@@ -301,7 +300,7 @@ class LClosure {
this.p = null;
this.nupvalues = n;
- this.upvals = new Array(n); /* list of upvalues as UpVals. initialised in luaF_initupvals */
+ this.upvals = new Array(n); /* list of upvalues. initialised in luaF_initupvals */
}
}
@@ -656,8 +655,7 @@ const luaO_pushvfstring = function(L, fmt, argp) {
v instanceof ltable.Table ||
v instanceof Udata ||
v instanceof LClosure ||
- v instanceof CClosure ||
- v instanceof lfunc.UpVal) {
+ v instanceof CClosure) {
pushstr(L, to_luastring("0x"+v.id.toString(16)));
} else if (v === null) { /* handle null before checking for typeof == object */
pushstr(L, to_luastring("null"));
diff --git a/src/lstate.js b/src/lstate.js
index 461ad83..0c44f3c 100644
--- a/src/lstate.js
+++ b/src/lstate.js
@@ -18,7 +18,6 @@ const lobject = require('./lobject.js');
const ldo = require('./ldo.js');
const lapi = require('./lapi.js');
const ltable = require('./ltable.js');
-const lfunc = require('./lfunc.js');
const ltm = require('./ltm.js');
const EXTRA_STACK = 5;
@@ -70,7 +69,6 @@ class lua_State {
this.basehookcount = 0;
this.allowhook = 1;
this.hookcount = this.basehookcount;
- this.openupval = null;
this.nny = 1;
this.status = LUA_OK;
this.errfunc = 0;
@@ -166,7 +164,6 @@ const lua_newthread = function(L) {
};
const luaE_freethread = function(L, L1) {
- lfunc.luaF_close(L1, L1.stack);
freestack(L1);
};
@@ -183,7 +180,6 @@ const lua_newstate = function() {
};
const close_state = function(L) {
- lfunc.luaF_close(L, L.stack); /* close all upvalues for this thread */
freestack(L);
};
diff --git a/src/lvm.js b/src/lvm.js
index 0f184a1..908125f 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -225,11 +225,11 @@ const luaV_execute = function(L) {
}
case OP_GETUPVAL: {
let b = i.B;
- lobject.setobj2s(L, ra, cl.upvals[b].v);
+ lobject.setobj2s(L, ra, cl.upvals[b]);
break;
}
case OP_GETTABUP: {
- let upval = cl.upvals[i.B].v;
+ let upval = cl.upvals[i.B];
let rc = RKC(L, base, k, i);
luaV_gettable(L, upval, rc, ra);
break;
@@ -241,7 +241,7 @@ const luaV_execute = function(L) {
break;
}
case OP_SETTABUP: {
- let upval = cl.upvals[i.A].v;
+ let upval = cl.upvals[i.A];
let rb = RKB(L, base, k, i);
let rc = RKC(L, base, k, i);
settable(L, upval, rb, rc);
@@ -249,7 +249,7 @@ const luaV_execute = function(L) {
}
case OP_SETUPVAL: {
let uv = cl.upvals[i.B];
- uv.v.setfrom(L.stack[ra]);
+ uv.setfrom(L.stack[ra]);
break;
}
case OP_SETTABLE: {
@@ -973,8 +973,8 @@ const getcached = function(p, encup, stack, base) {
let uv = p.upvalues;
let nup = uv.length;
for (let i = 0; i < nup; i++) { /* check whether it has right upvalues */
- let v = uv[i].instack ? stack[base + uv[i].idx] : encup[uv[i].idx].v;
- if (c.upvals[i].v !== v)
+ let v = uv[i].instack ? stack[base + uv[i].idx] : encup[uv[i].idx];
+ if (c.upvals[i] !== v)
return null; /* wrong upvalue; cannot reuse closure */
}
}
@@ -996,7 +996,6 @@ const pushclosure = function(L, p, encup, base, ra) {
ncl.upvals[i] = lfunc.luaF_findupval(L, base + uv[i].idx);
else
ncl.upvals[i] = encup[uv[i].idx];
- ncl.upvals[i].refcount++;
}
p.cache = ncl; /* save it on cache for reuse */
};