aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lapi.js1
-rw-r--r--src/ltable.js6
-rw-r--r--src/ltm.js17
-rw-r--r--src/lvm.js25
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;
diff --git a/src/ltm.js b/src/ltm.js
index 3e24c9c..ad09c26 100644
--- a/src/ltm.js
+++ b/src/ltm.js
@@ -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;
diff --git a/src/lvm.js b/src/lvm.js
index c89714e..a5b10e0 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -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 */