From d379aefe60b1c41618da2073dc0af2ccaa7f8045 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 12 May 2017 11:30:45 +1000 Subject: src/ltable.js: Use a weakmap to hold dead objects (where possible) --- src/ltable.js | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/ltable.js b/src/ltable.js index aa3473d..b609ad0 100644 --- a/src/ltable.js +++ b/src/ltable.js @@ -34,7 +34,8 @@ class Table { constructor(L) { this.id = L.l_G.id_counter++; this.strong = new Map(); - this.dead = new Map(); + this.dead_strong = new Map(); + this.dead_weak = void 0; /* initialised when needed */ this.f = void 0; /* first entry */ this.l = void 0; /* last entry */ this.metatable = null; @@ -42,7 +43,8 @@ class Table { } const add = function(t, hash, key, value) { - t.dead.clear(); + t.dead_strong.clear(); + t.dead_weak = void 0; let prev; let entry = { key: key, @@ -56,6 +58,9 @@ const add = function(t, hash, key, value) { t.l = entry; }; +const is_valid_weakmap_key = function(k) { + return typeof k === 'object' ? k !== null : typeof k === 'function'; +}; /* Move out of 'strong' part and into 'dead' part. */ const mark_dead = function(t, hash) { @@ -71,9 +76,15 @@ const mark_dead = function(t, hash) { if(t.f === e) t.f = next; if(t.l === e) t.l = prev; t.strong.delete(hash); - t.dead.set(hash, e); + if (is_valid_weakmap_key(hash)) { + if (!t.dead_weak) t.dead_weak = new WeakMap(); + t.dead_weak.set(hash, e); + } else { + /* can't be used as key in weakmap */ + t.dead_strong.set(hash, e); + } } -} +}; const luaH_new = function(L) { return new Table(L); @@ -174,18 +185,18 @@ const luaH_next = function(L, table, keyI) { entry = entry.n; if (!entry) return false; - } else if (!entry) { + } else { /* Try dead keys */ - entry = table.dead.get(hash); + entry = table.dead_weak.get(hash) || table.dead_strong.get(hash); if (!entry) /* item not in table */ - return ldebug.luaG_runerror(L, defs.to_luastring("invalid key to 'next'")) + return ldebug.luaG_runerror(L, defs.to_luastring("invalid key to 'next'")); /* Iterate until either out of keys, or until finding a non-dead key */ do { entry = entry.n; if (!entry) return false; - } while (entry.key.ttisdeadkey()) + } while (entry.key.ttisdeadkey()); } } L.stack[keyI] = new lobject.TValue(entry.key.type, entry.key.value); -- cgit v1.2.3-70-g09d2