diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lapi.js | 1 | ||||
-rw-r--r-- | src/ltable.js | 6 | ||||
-rw-r--r-- | src/ltm.js | 17 | ||||
-rw-r--r-- | src/lvm.js | 25 |
4 files changed, 37 insertions, 12 deletions
diff --git a/src/lapi.js b/src/lapi.js index d2f5c95..9aacb10 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -424,6 +424,7 @@ const lua_rawset = function(L, idx) { let slot = ltable.luaH_set(o.value, k); slot.setfrom(v); } + ltable.invalidateTMcache(o.value); L.top -= 2; }; diff --git a/src/ltable.js b/src/ltable.js index e4d21e2..0ed56ab 100644 --- a/src/ltable.js +++ b/src/ltable.js @@ -39,9 +39,14 @@ class Table { this.f = void 0; /* first entry */ this.l = void 0; /* last entry */ this.metatable = null; + this.flags = ~0; } } +const invalidateTMcache = function(t) { + t.flags = 0; +}; + const add = function(t, hash, key, value) { t.dead_strong.clear(); t.dead_weak = void 0; @@ -204,6 +209,7 @@ const luaH_next = function(L, table, keyI) { return true; }; +module.exports.invalidateTMcache = invalidateTMcache; module.exports.luaH_delete = luaH_delete; module.exports.luaH_get = luaH_get; module.exports.luaH_getint = luaH_getint; @@ -166,6 +166,21 @@ const luaT_callorderTM = function(L, p1, p2, event) { return !L.stack[L.top].l_isfalse() ? 1 : 0; }; +const fasttm = function(l, et, e) { + return et === null ? null : + (et.flags & (1 << e)) ? null : luaT_gettm(et, e, l.l_G.tmname[e]); +}; + +const luaT_gettm = function(events, event, ename) { + const tm = ltable.luaH_getstr(events, ename); + assert(event <= TMS.TM_EQ); + if (tm.ttisnil()) { /* no tag method? */ + events.flags |= 1<<event; /* cache this fact */ + return null; + } + else return tm; +}; + const luaT_gettmbyobj = function(L, o, event) { let mt; switch(o.ttnov()) { @@ -180,11 +195,13 @@ const luaT_gettmbyobj = function(L, o, event) { return mt ? ltable.luaH_getstr(mt, L.l_G.tmname[event]) : lobject.luaO_nilobject; }; +module.exports.fasttm = fasttm; module.exports.TMS = TMS; module.exports.luaT_callTM = luaT_callTM; module.exports.luaT_callbinTM = luaT_callbinTM; module.exports.luaT_trybinTM = luaT_trybinTM; module.exports.luaT_callorderTM = luaT_callorderTM; +module.exports.luaT_gettm = luaT_gettm; module.exports.luaT_gettmbyobj = luaT_gettmbyobj; module.exports.luaT_init = luaT_init; module.exports.luaT_objtypename = luaT_objtypename; @@ -725,6 +725,7 @@ const luaV_equalobj = function(L, t1, t2) { return 1; case CT.LUA_TBOOLEAN: return t1.value == t2.value ? 1 : 0; // Might be 1 or true + case CT.LUA_TLIGHTUSERDATA: case CT.LUA_TNUMINT: case CT.LUA_TNUMFLT: case CT.LUA_TLCF: @@ -733,22 +734,20 @@ const luaV_equalobj = function(L, t1, t2) { case CT.LUA_TLNGSTR: { return lstring.luaS_eqlngstr(t1.tsvalue(), t2.tsvalue()) ? 1 : 0; } - case CT.LUA_TLIGHTUSERDATA: case CT.LUA_TUSERDATA: case CT.LUA_TTABLE: if (t1.value === t2.value) return 1; else if (L === null) return 0; - // TODO: fasttm ? - tm = ltm.luaT_gettmbyobj(L, t1, ltm.TMS.TM_EQ); - if (tm.ttisnil()) - tm = ltm.luaT_gettmbyobj(L, t2, ltm.TMS.TM_EQ); + tm = ltm.fasttm(L, t1.value.metatable, ltm.TMS.TM_EQ); + if (tm === null) + tm = ltm.fasttm(L, t2.value.metatable, ltm.TMS.TM_EQ); break; default: return t1.value === t2.value ? 1 : 0; } - if (!tm || tm.ttisnil()) + if (tm === null) /* no TM? */ return 0; ltm.luaT_callTM(L, tm, t1, t2, L.top, 1); @@ -911,9 +910,10 @@ const luaV_objlen = function(L, ra, rb) { let tm; switch(rb.ttype()) { case CT.LUA_TTABLE: { - tm = ltm.luaT_gettmbyobj(L, rb, ltm.TMS.TM_LEN); - if (!tm.ttisnil()) break; - L.stack[ra] = new lobject.TValue(CT.LUA_TNUMINT, ltable.luaH_getn(rb.value)); + 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 */ return; } case CT.LUA_TSHRSTR: @@ -1031,8 +1031,8 @@ const gettable = function(L, t, key, ra) { L.stack[ra] = new lobject.TValue(slot.type, slot.value); return; } else { /* 't' is a table */ - tm = ltm.luaT_gettmbyobj(L, t, ltm.TMS.TM_INDEX); /* table's metamethod */ - if (tm.ttisnil()) { /* no metamethod? */ + 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 */ return; } @@ -1055,11 +1055,12 @@ const settable = function(L, t, key, val) { if (t.ttistable()) { let h = t.value; /* save 't' table */ let slot = ltable.luaH_set(h, key); - if (!slot.ttisnil() || (tm = ltm.luaT_gettmbyobj(L, t, ltm.TMS.TM_NEWINDEX)).ttisnil()) { + if (!slot.ttisnil() || (tm = ltm.fasttm(L, h.metatable, ltm.TMS.TM_NEWINDEX)) === null) { if (val.ttisnil()) ltable.luaH_delete(h, key); else slot.setfrom(val); + ltable.invalidateTMcache(h); return; } /* else will try the metamethod */ |