diff --git a/src/blua/ltm.c b/src/blua/ltm.c
index 031a2811e943da067610537c5ed29066e8b65f43..570bded69701e91524c3ee1e22991e5d24132798 100644
--- a/src/blua/ltm.c
+++ b/src/blua/ltm.c
@@ -31,9 +31,9 @@ void luaT_init (lua_State *L) {
   static const char *const luaT_eventname[] = {  /* ORDER TM */
     "__index", "__newindex",
     "__usedindex",
-    "__gc", "__mode", "__eq",
+    "__gc", "__mode", "__len", "__eq",
     "__add", "__sub", "__mul", "__div", "__mod",
-    "__pow", "__unm", "__len", "__lt", "__le",
+    "__pow", "__unm", "__lt", "__le",
     "__concat", "__call"
     ,"__strhook"
     ,"__and", "__or", "__xor", "__shl", "__shr", "__not"
diff --git a/src/blua/ltm.h b/src/blua/ltm.h
index 3d4ac8c0ec7713cccab56c92e8d32cb323d5b0ee..3f2aa4a45a623b360cbe2d35d76b733dd21b8155 100644
--- a/src/blua/ltm.h
+++ b/src/blua/ltm.h
@@ -21,6 +21,7 @@ typedef enum {
   TM_USEDINDEX,
   TM_GC,
   TM_MODE,
+  TM_LEN,
   TM_EQ,  /* last tag method with `fast' access */
   TM_ADD,
   TM_SUB,
@@ -29,7 +30,6 @@ typedef enum {
   TM_MOD,
   TM_POW,
   TM_UNM,
-  TM_LEN,
   TM_LT,
   TM_LE,
   TM_CONCAT,
diff --git a/src/blua/lvm.c b/src/blua/lvm.c
index 46a015c1eb254bc86a59d726d041e5b6461e30d2..b74fef4ee3d72d3081fdb11776ab759c337020f3 100644
--- a/src/blua/lvm.c
+++ b/src/blua/lvm.c
@@ -311,6 +311,33 @@ void luaV_concat (lua_State *L, int total, int last) {
 }
 
 
+static void objlen (lua_State *L, StkId ra, TValue *rb) {
+  const TValue *tm;
+  switch (ttype(rb)) {
+    case LUA_TTABLE: {
+      Table *h = hvalue(rb);
+      tm = fasttm(L, h->metatable, TM_LEN);
+      if (tm) break;  /* metamethod? break switch to call it */
+      setnvalue(ra, cast_num(luaH_getn(h)));  /* else primitive len */
+      return;
+    }
+    case LUA_TSTRING: {
+      tm = fasttm(L, G(L)->mt[LUA_TSTRING], TM_LEN);
+      if (tm) break;  /* metamethod? break switch to call it */
+      setnvalue(ra, cast_num(tsvalue(rb)->len));
+      return;
+    }
+    default: {  /* try metamethod */
+      tm = luaT_gettmbyobj(L, rb, TM_LEN);
+      if (ttisnil(tm))  /* no metamethod? */
+        luaG_typeerror(L, rb, "get length of");
+      break;
+    }
+  }
+  callTMres(L, ra, tm, rb, luaO_nilobject);
+}
+
+
 static void Arith (lua_State *L, StkId ra, TValue *rb,
                    TValue *rc, TMS op) {
   TValue tempb, tempc;
@@ -568,23 +595,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
         continue;
       }
       case OP_LEN: {
-        TValue *rb = RB(i);
-        switch (ttype(rb)) {
-          case LUA_TTABLE: {
-            setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
-            break;
-          }
-          case LUA_TSTRING: {
-            setnvalue(ra, cast_num(tsvalue(rb)->len));
-            break;
-          }
-          default: {  /* try metamethod */
-            Protect(
-              if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
-                luaG_typeerror(L, rb, "get length of");
-            )
-          }
-        }
+        Protect(objlen(L, ra, RB(i)));
         continue;
       }
       case OP_CONCAT: {