Browse Source

Optimise ROTable accesses and interface (#2505)

-  Optimise ROTable accesses and interface

This includes some refinements to the ROTable cache which remove the linker cludges on the CROSS_COMPILE builds.  Also keyhole tweaks to some of the Lua VM code to implrove runtimes.

I also noticed some compile time warnings during the build; the change to uz_unzip.c doesn't impact the compiled code, but does remove the compiler warnings.
Terry Ellison 5 years ago
parent
commit
5f67de8d48

+ 2 - 12
app/include/module.h

@@ -57,18 +57,8 @@
   const LOCK_IN_SECTION(libs) \
     luaL_Reg MODULE_PASTE_(lua_lib_,cfgname) = { luaname, initfunc }; \
   const LOCK_IN_SECTION(rotable) \
-    luaR_table MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(LUA_USE_MODULES_,cfgname))) \
-    = { luaname, map }
-
-
-/* System module registration support, not using LUA_USE_MODULES_XYZ. */
-#define BUILTIN_LIB_INIT(name, luaname, initfunc) \
-  const LOCK_IN_SECTION(libs) \
-    luaL_Reg MODULE_PASTE_(lua_lib_,name) = { luaname, initfunc }
-
-#define BUILTIN_LIB(name, luaname, map) \
-  const LOCK_IN_SECTION(rotable) \
-    luaR_table MODULE_PASTE_(lua_rotable_,name) = { luaname, map }
+    luaR_entry MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(LUA_USE_MODULES_,cfgname))) \
+    = {LSTRKEY(luaname), LROVAL(map)}
 
 #if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2)
 # error "NodeMCU modules must be built with LTR enabled (MIN_OPT_LEVEL=2 and LUA_OPTIMIZE_MEMORY=2)"

+ 1 - 10
app/lua/lauxlib.c

@@ -25,8 +25,6 @@
 #define lauxlib_c
 #define LUA_LIB
 
-#include "lrotable.h"
-
 #include "lauxlib.h"
 #include "lgc.h"
 #include "ldo.h"
@@ -555,14 +553,7 @@ LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
     if (e == NULL) e = fname + c_strlen(fname);
     lua_pushlstring(L, fname, e - fname);
     lua_rawget(L, -2);
-    if (lua_isnil(L, -1)) {
-      /* If looking for a global variable, check the rotables too */
-      void *ptable = luaR_findglobal(fname, e - fname);
-      if (ptable) {
-        lua_pop(L, 1);
-        lua_pushrotable(L, ptable);
-      }
-    }
+
     if (lua_isnil(L, -1)) {  /* no such field? */
       lua_pop(L, 1);  /* remove this nil */
       lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */

+ 56 - 66
app/lua/lbaselib.c

@@ -16,7 +16,7 @@
 #include C_HEADER_STDLIB
 #include "lauxlib.h"
 #include "lualib.h"
-#include "lrotable.h"
+#include "lrodefs.h"
 
 
 
@@ -462,71 +462,62 @@ static int luaB_newproxy (lua_State *L) {
   return 1;
 }
 
-#define LUA_BASELIB_FUNCLIST\
-  {LSTRKEY("assert"), LFUNCVAL(luaB_assert)},\
-  {LSTRKEY("collectgarbage"), LFUNCVAL(luaB_collectgarbage)},\
-  {LSTRKEY("dofile"), LFUNCVAL(luaB_dofile)},\
-  {LSTRKEY("error"), LFUNCVAL(luaB_error)},\
-  {LSTRKEY("gcinfo"), LFUNCVAL(luaB_gcinfo)},\
-  {LSTRKEY("getfenv"), LFUNCVAL(luaB_getfenv)},\
-  {LSTRKEY("getmetatable"), LFUNCVAL(luaB_getmetatable)},\
-  {LSTRKEY("loadfile"), LFUNCVAL(luaB_loadfile)},\
-  {LSTRKEY("load"), LFUNCVAL(luaB_load)},\
-  {LSTRKEY("loadstring"), LFUNCVAL(luaB_loadstring)},\
-  {LSTRKEY("next"), LFUNCVAL(luaB_next)},\
-  {LSTRKEY("pcall"), LFUNCVAL(luaB_pcall)},\
-  {LSTRKEY("print"), LFUNCVAL(luaB_print)},\
-  {LSTRKEY("rawequal"), LFUNCVAL(luaB_rawequal)},\
-  {LSTRKEY("rawget"), LFUNCVAL(luaB_rawget)},\
-  {LSTRKEY("rawset"), LFUNCVAL(luaB_rawset)},\
-  {LSTRKEY("select"), LFUNCVAL(luaB_select)},\
-  {LSTRKEY("setfenv"), LFUNCVAL(luaB_setfenv)},\
-  {LSTRKEY("setmetatable"), LFUNCVAL(luaB_setmetatable)},\
-  {LSTRKEY("tonumber"), LFUNCVAL(luaB_tonumber)},\
-  {LSTRKEY("tostring"), LFUNCVAL(luaB_tostring)},\
-  {LSTRKEY("type"), LFUNCVAL(luaB_type)},\
-  {LSTRKEY("unpack"), LFUNCVAL(luaB_unpack)},\
-  {LSTRKEY("xpcall"), LFUNCVAL(luaB_xpcall)}
-  
-#if LUA_OPTIMIZE_MEMORY == 2
-#undef MIN_OPT_LEVEL
-#define MIN_OPT_LEVEL 2
 #include "lrodefs.h"
-const LUA_REG_TYPE base_funcs_list[] = {
-  LUA_BASELIB_FUNCLIST,
-  {LNILKEY, LNILVAL}
-};
-#endif
 
+extern const luaR_entry lua_rotable_base[];
 
-static int luaB_index(lua_State *L) {
-#if LUA_OPTIMIZE_MEMORY == 2
-  int fres;
-  if ((fres = luaR_findfunction(L, base_funcs_list)) != 0)
-    return fres;
-#endif  
-  const char *keyname = luaL_checkstring(L, 2);
-  if (!c_strcmp(keyname, "_VERSION")) {
-    lua_pushliteral(L, LUA_VERSION);
-    return 1;
-  }
-  void *res = luaR_findglobal(keyname, c_strlen(keyname));
-  if (!res)
-    return 0;
-  else {
-    lua_pushrotable(L, res);
-    return 1;
-  }
-}
+/*
+ * ESP builds use specific linker directives to marshal all ROTable declarations
+ * into a single ROTable in the PSECT ".lua_rotable".  
+ *
+ * This is not practical on Posix builds using a standard link so for cross
+ * compiler builds, separate ROTables are used for the base functions and library
+ * ROTables, with the latter chained from the former using its __index meta-method.
+ * In this case all library ROTables are defined in linit.c.
+ */
+#ifdef LUA_CROSS_COMPILER
+#define BASE_ROTABLE    base_func_map
+#define LOCK_IN_ROTABLE
+static const LUA_REG_TYPE base_func_meta[] = {
+  LROT_TABENTRY(__index, lua_rotable_base),     
+  LROT_END};
+#else
+#define BASE_ROTABLE    lua_rotable_base
+#define LOCK_IN_ROTABLE __attribute__((used,unused,section(".lua_rotable")))
+#endif
 
-static const luaL_Reg base_funcs[] = {
-#if LUA_OPTIMIZE_MEMORY != 2
-#undef MIN_OPT_LEVEL
-#define MIN_OPT_LEVEL 0
-#include "lrodefs.h"
-  LUA_BASELIB_FUNCLIST,
+static const LUA_REG_TYPE LOCK_IN_ROTABLE base_func_map[] = {
+  LROT_FUNCENTRY(assert,         luaB_assert),     
+  LROT_FUNCENTRY(collectgarbage, luaB_collectgarbage),     
+  LROT_FUNCENTRY(dofile,         luaB_dofile),     
+  LROT_FUNCENTRY(error,          luaB_error),     
+  LROT_FUNCENTRY(gcinfo,         luaB_gcinfo),     
+  LROT_FUNCENTRY(getfenv,        luaB_getfenv),     
+  LROT_FUNCENTRY(getmetatable,   luaB_getmetatable),     
+  LROT_FUNCENTRY(loadfile,       luaB_loadfile),     
+  LROT_FUNCENTRY(load,           luaB_load),     
+  LROT_FUNCENTRY(loadstring,     luaB_loadstring),     
+  LROT_FUNCENTRY(next,           luaB_next),     
+  LROT_FUNCENTRY(pcall,          luaB_pcall),     
+  LROT_FUNCENTRY(print,          luaB_print),     
+  LROT_FUNCENTRY(rawequal,       luaB_rawequal),     
+  LROT_FUNCENTRY(rawget,         luaB_rawget),     
+  LROT_FUNCENTRY(rawset,         luaB_rawset),     
+  LROT_FUNCENTRY(select,         luaB_select),     
+  LROT_FUNCENTRY(setfenv,        luaB_setfenv),     
+  LROT_FUNCENTRY(setmetatable,   luaB_setmetatable),     
+  LROT_FUNCENTRY(tonumber,       luaB_tonumber),     
+  LROT_FUNCENTRY(tostring,       luaB_tostring),     
+  LROT_FUNCENTRY(type,           luaB_type),     
+  LROT_FUNCENTRY(unpack,         luaB_unpack),     
+  LROT_FUNCENTRY(xpcall,         luaB_xpcall)     
+#ifdef LUA_CROSS_COMPILER
+ ,LROT_TABENTRY(__metatable,     base_func_meta),   
+  LROT_END
 #endif
-  {"__index", luaB_index},
+};
+
+static const luaL_Reg base_funcs[] = {
   {NULL, NULL}
 };
 
@@ -661,7 +652,6 @@ static int luaB_corunning (lua_State *L) {
 
 #undef MIN_OPT_LEVEL
 #define MIN_OPT_LEVEL 1
-#include "lrodefs.h"
 const LUA_REG_TYPE co_funcs[] = {
   {LSTRKEY("create"), LFUNCVAL(luaB_cocreate)},
   {LSTRKEY("resume"), LFUNCVAL(luaB_coresume)},
@@ -682,7 +672,6 @@ static void auxopen (lua_State *L, const char *name,
   lua_setfield(L, -2, name);
 }
 
-
 static void base_open (lua_State *L) {
   /* set global _G */
   lua_pushvalue(L, LUA_GLOBALSINDEX);
@@ -691,11 +680,12 @@ static void base_open (lua_State *L) {
   luaL_register_light(L, "_G", base_funcs);
 #if LUA_OPTIMIZE_MEMORY > 0
   lua_pushvalue(L, -1);
-  lua_setmetatable(L, -2);  
-#else
+  lua_setmetatable(L, -2);
+  lua_pushrotable(L, (void *)BASE_ROTABLE);
+  lua_setglobal(L, "__index");
+#endif
   lua_pushliteral(L, LUA_VERSION);
   lua_setglobal(L, "_VERSION");  /* set global _VERSION */
-#endif
   /* `ipairs' and `pairs' need auxliliary functions as upvalues */
   auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
   auxopen(L, "pairs", luaB_pairs, luaB_next);

+ 0 - 1
app/lua/ldblib.c

@@ -16,7 +16,6 @@
 
 #include "lauxlib.h"
 #include "lualib.h"
-#include "lrotable.h"
 #include "lstring.h"
 #include "lflash.h"
 #include "user_modules.h"

+ 8 - 4
app/lua/lgc.c

@@ -168,10 +168,14 @@ static int traversetable (global_State *g, Table *h) {
   int i;
   int weakkey = 0;
   int weakvalue = 0;
-  const TValue *mode;
-  if (h->metatable && !luaR_isrotable(h->metatable))
-    markobject(g, h->metatable);
-  mode = gfasttm(g, h->metatable, TM_MODE);
+  const TValue *mode = luaO_nilobject;
+
+  if (h->metatable) {
+    if (!luaR_isrotable(h->metatable))
+      markobject(g, h->metatable);
+    mode = gfasttm(g, h->metatable, TM_MODE);
+  }
+    
   if (mode && ttisstring(mode)) {  /* is there a weak mode? */
     weakkey = (c_strchr(svalue(mode), 'k') != NULL);
     weakvalue = (c_strchr(svalue(mode), 'v') != NULL);

+ 53 - 42
app/lua/linit.c

@@ -15,60 +15,71 @@
 #include "lauxlib.h"
 #include "luaconf.h"
 #include "module.h"
-#if defined(LUA_CROSS_COMPILER)
-BUILTIN_LIB(      start_list,  NULL,               NULL);
-BUILTIN_LIB_INIT( start_list,  NULL,               NULL);
+
+#if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2)
+# error "NodeMCU modules must be built with LTR enabled (MIN_OPT_LEVEL=2 and LUA_OPTIMIZE_MEMORY=2)"
 #endif
+
 extern const luaR_entry strlib[], tab_funcs[],  dblib[], 
                         co_funcs[], math_map[], syslib[];
+extern const luaR_entry syslib[], io_funcs[];  // Only used on cross-compile builds
 
-BUILTIN_LIB_INIT( BASE,      "",                luaopen_base);
-BUILTIN_LIB_INIT( LOADLIB,   LUA_LOADLIBNAME,   luaopen_package);
-
-BUILTIN_LIB(      STRING,    LUA_STRLIBNAME,    strlib);
-BUILTIN_LIB_INIT( STRING,    LUA_STRLIBNAME,    luaopen_string);
-
-BUILTIN_LIB(      TABLE,     LUA_TABLIBNAME,    tab_funcs);
-BUILTIN_LIB_INIT( TABLE,     LUA_TABLIBNAME,    luaopen_table);
-
-BUILTIN_LIB(      DBG,       LUA_DBLIBNAME,     dblib);
-BUILTIN_LIB_INIT( DBG,       LUA_DBLIBNAME,     luaopen_debug);
-
-BUILTIN_LIB(      CO,        LUA_COLIBNAME,     co_funcs);
-
-BUILTIN_LIB(      MATH,      LUA_MATHLIBNAME,   math_map);
-
-#if defined(LUA_CROSS_COMPILER)
-extern const luaR_entry syslib[], iolib[];
-BUILTIN_LIB(      OS,        LUA_OSLIBNAME,     syslib);
-BUILTIN_LIB_INIT( IO,        LUA_IOLIBNAME,     luaopen_io);
-BUILTIN_LIB(      end_list,  NULL,               NULL);
-BUILTIN_LIB_INIT( end_list,  NULL,               NULL);
 /*
- * These base addresses are internal to this module for cross compile builds
- * This also exploits feature of the GCC code generator that the variables are
- * emitted in either normal OR reverse order within PSECT.
+ * The NodeMCU Lua initalisation has been adapted to use linker-based module 
+ * registration.  This uses a PSECT naming convention to allow the lib and rotab
+ * entries to be collected by the linker into consoliated tables.  The linker
+ * defines lua_libs_base and lua_rotable_base.
+ *
+ * This is not practical on Posix builds which use a standard loader declaration
+ * so for cross compiler builds, separate ROTables are used for the base functions
+ * and library ROTables, with the latter chained from the former using its __index 
+ * meta-method. In this case all library ROTables are defined here, avoiding the
+ * need for linker magic is avoided on host builds. 
  */
-#define isascending(n) ((&(n ## _end_list)-&(n ## _start_list))>0)
-static const luaL_Reg   *lua_libs;
-const        luaR_table *lua_rotable;
-#else 
-/* These base addresses are Xtensa toolchain linker constants for Firmware builds */ 
+
+#if defined(LUA_CROSS_COMPILER)
+#define LUA_ROTABLES lua_rotable_base
+#define LUA_LIBS     lua_libs_base
+#else /* declare Xtensa toolchain linker defined constants */ 
 extern const luaL_Reg    lua_libs_base[];
-extern const luaR_table  lua_rotable_base[];
-static const luaL_Reg   *lua_libs    = lua_libs_base;
-const        luaR_table *lua_rotable = lua_rotable_base;
+extern const luaR_entry  lua_rotable_base[];
+#define LUA_ROTABLES lua_rotable_core
+#define LUA_LIBS     lua_libs_core
 #endif
+             
+static const LOCK_IN_SECTION(libs) luaL_reg LUA_LIBS[] = {
+  {"",              luaopen_base},
+  {LUA_LOADLIBNAME, luaopen_package},
+  {LUA_STRLIBNAME,  luaopen_string},
+  {LUA_TABLIBNAME,  luaopen_table},
+  {LUA_DBLIBNAME,   luaopen_debug}
+#if defined(LUA_CROSS_COMPILER)
+ ,{LUA_IOLIBNAME,   luaopen_io},
+  {NULL,            NULL}
+#endif
+};
 
-void luaL_openlibs (lua_State *L) {
+#define ENTRY(n,t)  {LSTRKEY(n), LRO_ROVAL(t)}
+
+const LOCK_IN_SECTION(rotable) ROTable LUA_ROTABLES[] = {
+  ENTRY("ROM",           LUA_ROTABLES),
+  ENTRY(LUA_STRLIBNAME,  strlib),
+  ENTRY(LUA_TABLIBNAME,  tab_funcs),
+  ENTRY(LUA_DBLIBNAME,   dblib),
+  ENTRY(LUA_COLIBNAME,   co_funcs),
+  ENTRY(LUA_MATHLIBNAME, math_map)
 #if defined(LUA_CROSS_COMPILER)
-lua_libs    = (isascending(lua_lib) ? &lua_lib_start_list : &lua_lib_end_list) + 1;
-lua_rotable = (isascending(lua_rotable) ? &lua_rotable_start_list : &lua_rotable_end_list) + 1;
+ ,ENTRY(LUA_OSLIBNAME,   syslib),
+  LROT_END
 #endif
-  const luaL_Reg *lib = lua_libs;
+  };
+
+void luaL_openlibs (lua_State *L) {
+  const luaL_Reg *lib = lua_libs_base;
+
+  /* loop round and open libraries */
   for (; lib->name; lib++) {
-    if (lib->func)
-    {
+    if (lib->func) {
       lua_pushcfunction(L, lib->func);
       lua_pushstring(L, lib->name);
       lua_call(L, 1, 0);

+ 0 - 1
app/lua/lmathlib.c

@@ -15,7 +15,6 @@
 
 #include "lauxlib.h"
 #include "lualib.h"
-#include "lrotable.h"
 
 #undef PI
 #define PI (3.14159265358979323846)

+ 10 - 5
app/lua/loadlib.c

@@ -24,7 +24,6 @@
 
 #include "lauxlib.h"
 #include "lualib.h"
-#include "lrotable.h"
 
 /* prefix for open functions in C libraries */
 #define LUA_POF		"luaopen_"
@@ -474,10 +473,11 @@ static int ll_require (lua_State *L) {
     return 1;  /* package is already loaded */
   }
   /* Is this a readonly table? */
-  void *res = luaR_findglobal(name, c_strlen(name));
-  if (res) {
-    lua_pushrotable(L, res);
+  lua_getfield(L, LUA_GLOBALSINDEX, name);
+  if(lua_isrotable(L,-1)) {
     return 1;
+  } else {
+    lua_pop(L, 1);
   }
   /* else must load it; iterate over available loaders */
   lua_getfield(L, LUA_ENVIRONINDEX, "loaders");
@@ -563,8 +563,13 @@ static void modinit (lua_State *L, const char *modname) {
 
 static int ll_module (lua_State *L) {
   const char *modname = luaL_checkstring(L, 1);
-  if (luaR_findglobal(modname, c_strlen(modname)))
+  /* Is this a readonly table? */
+  lua_getfield(L, LUA_GLOBALSINDEX, modname);
+  if(lua_isrotable(L,-1)) {
     return 0;
+  } else {
+    lua_pop(L, 1);
+  }
   int loaded = lua_gettop(L) + 1;  /* index of _LOADED table */
   lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
   lua_getfield(L, loaded, modname);  /* get _LOADED[modname] */

+ 1 - 0
app/lua/lobject.h

@@ -405,6 +405,7 @@ typedef struct Table {
   int sizearray;  /* size of `array' array */
 } Table;
 
+typedef const struct luaR_entry ROTable;
 
 /*
 ** `module' operation for hashing (size is always a power of 2)

+ 5 - 0
app/lua/lrodefs.h

@@ -38,5 +38,10 @@
   return 1
 #endif
 
+#define LROT_TABENTRY(n,t)  {LSTRKEY(#n), LRO_ROVAL(t)}
+#define LROT_FUNCENTRY(n,f) {LSTRKEY(#n), LRO_FUNCVAL(f)}
+#define LROT_NUMENTRY(n,x)  {LSTRKEY(#n), LRO_NUMVAL(x)}
+#define LROT_END            {LNILKEY, LNILVAL}
+
 #endif /* lrodefs_h */
 

+ 131 - 101
app/lua/lrotable.c

@@ -9,77 +9,139 @@
 #include "lobject.h"
 #include "lapi.h"
 
-/* Local defines */
-#define LUAR_FINDFUNCTION     0
-#define LUAR_FINDVALUE        1
-
-/* Externally defined read-only table array */
-extern const luaR_table *lua_rotable;
-
-/* Find a global "read only table" in the constant lua_rotable array */
-void* luaR_findglobal(const char *name, unsigned len) {
-  unsigned i;
-
-  if (c_strlen(name) > LUA_MAX_ROTABLE_NAME)
-    return NULL;
-  for (i=0; lua_rotable[i].name; i ++)
-    if (*lua_rotable[i].name != '\0' && c_strlen(lua_rotable[i].name) == len && !c_strncmp(lua_rotable[i].name, name, len)) {
-      return (void*)(lua_rotable[i].pentries);
+#define ALIGNED_STRING (__attribute__((aligned(4))) char *)
+#define LA_LINES 16
+#define LA_SLOTS 4
+//#define COLLECT_STATS
+
+/*
+ * All keyed ROtable access passes through luaR_findentry().  ROTables
+ * are simply a list of <key><TValue value> pairs.  The existing algo
+ * did a linear scan of this vector of pairs looking for a match.
+ *
+ * A N×M lookaside cache has been added, with a simple hash on the key's
+ * TString addr and the ROTable addr to identify one of N lines.  Each
+ * line has M slots which are scanned. This is all done in RAM and is
+ * perhaps 20x faster than the corresponding random Flash accesses which
+ * will cause flash faults.
+ *
+ * If a match is found and the table addresses match, then this entry is
+ * probed first. In practice the hit-rate here is over 99% so the code
+ * rarely fails back to doing the linear scan in ROM.
+ *
+ * Note that this hash does a couple of prime multiples and a modulus 2^X
+ * with is all evaluated in H/W, and adequately randomizes the lookup.
+ */
+#define HASH(a,b) (519*((size_t)(a)>>4) + 17*((size_t)(b)>>4))
+
+static struct {
+  unsigned hash;
+  unsigned addr:24;
+  unsigned ndx:8;
+} cache[LA_LINES][LA_SLOTS];
+
+#ifdef COLLECT_STATS
+unsigned cache_stats[3];
+#define COUNT(i) cache_stats[i]++
+#else
+#define COUNT(i)
+#endif
+
+static int lookup_cache(unsigned hash, ROTable *rotable) {
+  int i = (hash>>2) & (LA_LINES-1), j;
+
+  for (j = 0; j<LA_SLOTS; j++) {
+    if (cache[i][j].hash == hash &&
+        ((size_t)rotable & 0xffffffu) == cache[i][j].addr) {
+      COUNT(0);
+      return cache[i][j].ndx;
     }
-  return NULL;
+  }
+  COUNT(1);
+  return -1;
 }
 
-/* Find an entry in a rotable and return it */
-static const TValue* luaR_auxfind(const luaR_entry *pentry, const char *strkey, luaR_numkey numkey, unsigned *ppos) {
-  const TValue *res = NULL;
-  unsigned i = 0;
-  
-  if (pentry == NULL)
-    return NULL;  
-  while(pentry->key.type != LUA_TNIL) {
-    if ((strkey && (pentry->key.type == LUA_TSTRING) && (!c_strcmp(pentry->key.id.strkey, strkey))) || 
-        (!strkey && (pentry->key.type == LUA_TNUMBER) && ((luaR_numkey)pentry->key.id.numkey == numkey))) {
-      res = &pentry->value;
-      break;
+static void update_cache(unsigned hash, ROTable *rotable, unsigned ndx) {
+  int i = (hash)>>2 & (LA_LINES-1), j;
+  COUNT(2);
+  if (ndx>0xffu)
+    return;
+  for (j = LA_SLOTS-1; j>0; j--)
+    cache[i][j] = cache[i][j-1];
+  cache[i][0].hash = hash;
+  cache[i][0].addr = (size_t) rotable;
+  cache[i][0].ndx  = ndx;
+}
+/*
+ * Find a string key entry in a rotable and return it.  Note that this internally
+ * uses a null key to denote a metatable search.
+ */
+const TValue* luaR_findentry(ROTable *rotable, TString *key, unsigned *ppos) {
+  const luaR_entry *pentry = rotable;
+  const char *strkey = key ? getstr(key) : ALIGNED_STRING "__metatable" ;
+  size_t      hash   = HASH(rotable, key);
+  unsigned    i      = 0;
+  int         j      = lookup_cache(hash, rotable);
+
+  if (pentry) {
+    if (j >= 0){
+      if ((pentry[j].key.type == LUA_TSTRING) &&
+        !c_strcmp(pentry[j].key.id.strkey, strkey)) {
+        if (ppos)
+          *ppos = j;
+        return &pentry[j].value;
+      }
+    }
+    /*
+     * The invariants for 1st word comparison are deferred to here since they
+     * aren't needed if there is a cache hit. Note that the termination null
+     * is included so a "on\0" has a mask of 0xFFFFFF and "a\0" has 0xFFFF.
+     */
+    unsigned name4 = *(unsigned *)strkey;
+    unsigned l     = key ? key->tsv.len : sizeof("__metatable")-1;
+    unsigned mask4 = l > 2 ? (~0u) : (~0u)>>((3-l)*8);
+    for(;pentry->key.type != LUA_TNIL; i++, pentry++) {
+      if ((pentry->key.type == LUA_TSTRING) &&
+          ((*(unsigned *)pentry->key.id.strkey ^ name4) & mask4) == 0 &&
+          !c_strcmp(pentry->key.id.strkey, strkey)) {
+        if (ppos)
+          *ppos = i;
+        if (j==-1) {
+          update_cache(hash, rotable, pentry - rotable);
+        } else if (j != (pentry - rotable)) {
+          j = 0;
+        }
+        return &pentry->value;
+      }
     }
-    i ++; pentry ++;
   }
-  if (res && ppos)
-    *ppos = i;   
-  return res;
+  return luaO_nilobject;
 }
 
-int luaR_findfunction(lua_State *L, const luaR_entry *ptable) {
-  const TValue *res = NULL;
-  const char *key = luaL_checkstring(L, 2);
-    
-  res = luaR_auxfind(ptable, key, 0, NULL);  
-  if (res && ttislightfunction(res)) {
-    luaA_pushobject(L, res);
-    return 1;
+const TValue* luaR_findentryN(ROTable *rotable, luaR_numkey numkey, unsigned *ppos) {
+  unsigned i = 0;
+  const luaR_entry *pentry = rotable;
+  if (pentry) {
+    for ( ;pentry->key.type != LUA_TNIL; i++, pentry++) {
+      if (pentry->key.type == LUA_TNUMBER && (luaR_numkey) pentry->key.id.numkey == numkey) {
+        if (ppos)
+          *ppos = i;
+        return &pentry->value;
+      }
+    }
   }
-  else
-    return 0;
+  return NULL;
 }
 
-/* Find an entry in a rotable and return its type 
-   If "strkey" is not NULL, the function will look for a string key,
-   otherwise it will look for a number key */
-const TValue* luaR_findentry(void *data, const char *strkey, luaR_numkey numkey, unsigned *ppos) {
-  return luaR_auxfind((const luaR_entry*)data, strkey, numkey, ppos);
-}
 
 /* Find the metatable of a given table */
-void* luaR_getmeta(void *data) {
-#ifdef LUA_META_ROTABLES
-  const TValue *res = luaR_auxfind((const luaR_entry*)data, "__metatable", 0, NULL);
+void* luaR_getmeta(ROTable *rotable) {
+  const TValue *res = luaR_findentry(rotable, NULL, NULL);
   return res && ttisrotable(res) ? rvalue(res) : NULL;
-#else
-  return NULL;
-#endif
 }
 
-static void luaR_next_helper(lua_State *L, const luaR_entry *pentries, int pos, TValue *key, TValue *val) {
+static void luaR_next_helper(lua_State *L, ROTable *pentries, int pos,
+                             TValue *key, TValue *val) {
   setnilvalue(key);
   setnilvalue(val);
   if (pentries[pos].key.type != LUA_TNIL) {
@@ -91,56 +153,24 @@ static void luaR_next_helper(lua_State *L, const luaR_entry *pentries, int pos,
    setobj2s(L, val, &pentries[pos].value);
   }
 }
+
+
 /* next (used for iteration) */
-void luaR_next(lua_State *L, void *data, TValue *key, TValue *val) {
-  const luaR_entry* pentries = (const luaR_entry*)data;
-  char strkey[LUA_MAX_ROTABLE_NAME + 1], *pstrkey = NULL;
-  luaR_numkey numkey = 0;
+void luaR_next(lua_State *L, ROTable *rotable, TValue *key, TValue *val) {
   unsigned keypos;
-  
+
   /* Special case: if key is nil, return the first element of the rotable */
-  if (ttisnil(key)) 
-    luaR_next_helper(L, pentries, 0, key, val);
+  if (ttisnil(key))
+    luaR_next_helper(L, rotable, 0, key, val);
   else if (ttisstring(key) || ttisnumber(key)) {
-    /* Find the previoud key again */  
+    /* Find the previous key again */
     if (ttisstring(key)) {
-      luaR_getcstr(strkey, rawtsvalue(key), LUA_MAX_ROTABLE_NAME);          
-      pstrkey = strkey;
-    } else   
-      numkey = (luaR_numkey)nvalue(key);
-    luaR_findentry(data, pstrkey, numkey, &keypos);
+      luaR_findentry(rotable, rawtsvalue(key), &keypos);
+    } else {
+      luaR_findentryN(rotable, (luaR_numkey)nvalue(key), &keypos);
+    }
     /* Advance to next key */
-    keypos ++;    
-    luaR_next_helper(L, pentries, keypos, key, val);
+    keypos ++;
+    luaR_next_helper(L, rotable, keypos, key, val);
   }
 }
-
-/* Convert a Lua string to a C string */
-void luaR_getcstr(char *dest, const TString *src, size_t maxsize) {
-  if (src->tsv.len+1 > maxsize)
-    dest[0] = '\0';
-  else {
-    c_memcpy(dest, getstr(src), src->tsv.len);
-    dest[src->tsv.len] = '\0';
-  } 
-}
-
-#ifdef LUA_META_ROTABLES  
-/* Set in RO check depending on platform */
-#if defined(LUA_CROSS_COMPILER) && defined(__CYGWIN__)
-extern char __end__[];
-#define IN_RO_AREA(p) ((p) < __end__)
-#elif defined(LUA_CROSS_COMPILER)
-extern char  _edata[];
-#define IN_RO_AREA(p) ((p) < _edata)
-#else  /* xtensa tool chain for ESP target */
-extern char _irom0_text_start[];
-extern char _irom0_text_end[];
-#define IN_RO_AREA(p) ((p) >= _irom0_text_start && (p) <= _irom0_text_end)
-#endif
-
-/* Return 1 if the given pointer is a rotable */
-int luaR_isrotable(void *p) {
-  return IN_RO_AREA((char *)p);
-}
-#endif

+ 43 - 21
app/lua/lrotable.h

@@ -14,7 +14,11 @@
 #define LRO_NUMVAL(v)   {{.n = v}, LUA_TNUMBER}
 #define LRO_ROVAL(v)    {{.p = (void*)v}, LUA_TROTABLE}
 #define LRO_NILVAL      {{.p = NULL}, LUA_TNIL}
+#ifdef LUA_CROSS_COMPILER
 #define LRO_STRKEY(k)   {LUA_TSTRING, {.strkey = k}}
+#else
+#define LRO_STRKEY(k)   {LUA_TSTRING, {.strkey = (STORE_ATTR char *) k}}
+#endif
 #define LRO_NUMKEY(k)   {LUA_TNUMBER, {.numkey = k}}
 #define LRO_NILKEY      {LUA_TNIL, {.strkey=NULL}}
 
@@ -25,40 +29,58 @@
 typedef int luaR_numkey;
 
 /* The next structure defines the type of a key */
-typedef struct
-{
+typedef struct {
   int type;
-  union
-  {
+  union {
     const char*   strkey;
     luaR_numkey   numkey;
   } id;
 } luaR_key;
 
 /* An entry in the read only table */
-typedef struct
-{
+typedef struct luaR_entry {
   const luaR_key key;
   const TValue value;
 } luaR_entry;
 
-/* A rotable */
-typedef struct
-{
-  const char *name;
-  const luaR_entry *pentries;
-} luaR_table;
-
-void* luaR_findglobal(const char *key, unsigned len);
-int luaR_findfunction(lua_State *L, const luaR_entry *ptable);
-const TValue* luaR_findentry(void *data, const char *strkey, luaR_numkey numkey, unsigned *ppos);
-void luaR_getcstr(char *dest, const TString *src, size_t maxsize);
-void luaR_next(lua_State *L, void *data, TValue *key, TValue *val);
-void* luaR_getmeta(void *data);
-#ifdef LUA_META_ROTABLES
+/*
+ * The current ROTable implmentation is a vector of luaR_entry terminated by a
+ * nil record.  The convention is to use ROtable * to refer to the entire vector 
+ * as a logical ROTable.
+ */
+typedef const struct luaR_entry ROTable;
+
+const TValue* luaR_findentry(ROTable *tab, TString *key, unsigned *ppos);
+const TValue* luaR_findentryN(ROTable *tab, luaR_numkey numkey, unsigned *ppos);
+void luaR_next(lua_State *L, ROTable *tab, TValue *key, TValue *val);
+void* luaR_getmeta(ROTable *tab);
 int luaR_isrotable(void *p);
+
+/*
+ * Set inRO check depending on platform. Note that this implementation needs 
+ * to work on both the host (luac.cross) and ESP targets.  The luac.cross 
+ * VM is used for the -e option, and is primarily used to be able to debug 
+ * VM changes on the more developer-friendly hot gdb environment.
+ */
+#if defined(LUA_CROSS_COMPILER)
+
+#if defined(__CYGWIN__)
+#define _RODATA_END __end__
 #else
-#define luaR_isrotable(p)     (0)
+#define _RODATA_END _edata
+#endif 
+extern const char _RODATA_END[];
+#define IN_RODATA_AREA(p) (((const char *)(p)) < _RODATA_END)
+
+#else  /* xtensa tool chain for ESP target */
+
+extern const char _irom0_text_start[];
+extern const char _irom0_text_end[];
+#define IN_RODATA_AREA(p) (((const char *)(p)) >= _irom0_text_start && ((const char *)(p)) <= _irom0_text_end)
+
 #endif
 
+/* Return 1 if the given pointer is a rotable */
+#define luaR_isrotable(p) IN_RODATA_AREA(p)
+
 #endif

+ 5 - 9
app/lua/lstring.c

@@ -80,16 +80,12 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
   return ts;
 }
 
-#ifdef LUA_CROSS_COMPILER
-#define IN_RO_AREA(p) (0)
-#else /* xtensa tool chain for ESP */
-extern char _irom0_text_start[];
-extern char _irom0_text_end[];
-#define IN_RO_AREA(p) ((p) >= _irom0_text_start && (p) <= _irom0_text_end)
+static int lua_is_ptr_in_ro_area(const char *p) {
+#ifdef LUA_CROSS_COMPILER 
+  return 0;         // TStrings are never in RO in luac.cross
+#else
+  return IN_RODATA_AREA(p);
 #endif
-
-int lua_is_ptr_in_ro_area(const char *p) {
-  return IN_RO_AREA(p);
 }
 
 /*

+ 0 - 1
app/lua/lstrlib.c

@@ -15,7 +15,6 @@
 
 #include "lauxlib.h"
 #include "lualib.h"
-#include "lrotable.h"
 
 /* macro to `unsign' a character */
 #define uchar(c)        ((unsigned char)(c))

+ 5 - 9
app/lua/ltable.c

@@ -580,7 +580,7 @@ const TValue *luaH_getnum (Table *t, int key) {
 
 /* same thing for rotables */
 const TValue *luaH_getnum_ro (void *t, int key) {
-  const TValue *res = luaR_findentry(t, NULL, key, NULL);
+  const TValue *res = luaR_findentryN(t, key, NULL);
   return res ? res : luaO_nilobject;
 }
 
@@ -599,14 +599,10 @@ const TValue *luaH_getstr (Table *t, TString *key) {
 }
 
 /* same thing for rotables */
-const TValue *luaH_getstr_ro (void *t, TString *key) {
-  char keyname[LUA_MAX_ROTABLE_NAME + 1];
-  const TValue *res;  
-  if (!t)
+const TValue *luaH_getstr_ro (void *t, TString *key) {  
+  if (!t || key->tsv.len>LUA_MAX_ROTABLE_NAME)
     return luaO_nilobject;
-  luaR_getcstr(keyname, key, LUA_MAX_ROTABLE_NAME);   
-  res = luaR_findentry(t, keyname, 0, NULL);
-  return res ? res : luaO_nilobject;
+  return luaR_findentry(t, key, NULL);
 }
 
 
@@ -745,7 +741,7 @@ int luaH_getn (Table *t) {
 int luaH_getn_ro (void *t) {
   int i = 1, len=0;
   
-  while(luaR_findentry(t, NULL, i ++, NULL))
+  while(luaR_findentryN(t, i ++, NULL))
     len ++;
   return len;
 }

+ 0 - 1
app/lua/ltablib.c

@@ -13,7 +13,6 @@
 
 #include "lauxlib.h"
 #include "lualib.h"
-#include "lrotable.h"
 
 
 #define aux_getn(L,n)	(luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))

+ 14 - 6
app/lua/ltm.c

@@ -50,14 +50,22 @@ void luaT_init (lua_State *L) {
 ** tag methods
 */
 const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
-  const TValue *tm = luaR_isrotable(events) ? luaH_getstr_ro(events, ename) : luaH_getstr(events, ename); 
+  const TValue *tm;
   lua_assert(event <= TM_EQ);
-  if (ttisnil(tm)) {  /* no tag method? */
-    if (!luaR_isrotable(events))
+
+  if (luaR_isrotable(events)) {
+    tm =  luaH_getstr_ro(events, ename); 
+    if (ttisnil(tm)) {  /* no tag method? */
+      return NULL;
+    }
+  } else {
+    tm = luaH_getstr(events, ename); 
+    if (ttisnil(tm)) {  /* no tag method? */
       events->flags |= cast_byte(1u<<event);  /* cache this fact */
-    return NULL;
-  }
-  else return tm;
+      return NULL;
+    }
+  } 
+  return tm;
 }
 
 

+ 3 - 5
app/lua/ltm.h

@@ -9,7 +9,7 @@
 
 
 #include "lobject.h"
-
+#include "lrotable.h"
 
 /*
 * WARNING: if you change the order of this enumeration,
@@ -36,12 +36,10 @@ typedef enum {
   TM_N		/* number of elements in the enum */
 } TMS;
 
-
-
 #define gfasttm(g,et,e) ((et) == NULL ? NULL : \
-  !luaR_isrotable(et) && ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
+  (!luaR_isrotable(et) && ((et)->flags & (1u<<(e)))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
 
-#define fasttm(l,et,e)	gfasttm(G(l), et, e)
+#define fasttm(l,et,e) gfasttm(G(l), et, e)
 
 LUAI_DATA const char *const luaT_typenames[];
 

+ 1 - 0
app/lua/luac_cross/Makefile

@@ -18,6 +18,7 @@ TARGET = host
 ifeq ($(FLAVOR),debug)
     CCFLAGS        += -O0 -g
     TARGET_LDFLAGS += -O0 -g
+    DEFINES        += -DLUA_DEBUG_BUILD
 else
     FLAVOR         =  release
     CCFLAGS        += -O2

+ 14 - 20
app/lua/luac_cross/liolib.c

@@ -18,7 +18,6 @@
 
 #include "lauxlib.h"
 #include "lualib.h"
-#include "lrotable.h"
 
 #define IO_INPUT	1
 #define IO_OUTPUT	2
@@ -28,7 +27,11 @@
 #define LUA_IO_SETFIELD(f)  lua_rawseti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f]))
 
 /* "Pseudo-random" keys for the registry */
-static const size_t liolib_keys[] = {(size_t)&luaL_callmeta, (size_t)&luaL_typerror, (size_t)&luaL_argerror};
+static const size_t liolib_keys[] = {
+  (size_t)&luaL_callmeta, 
+  (size_t)&luaL_typerror, 
+  (size_t)&luaL_argerror
+ };
 
 static const char *const fnames[] = {"input", "output"};
 
@@ -452,20 +455,6 @@ const LUA_REG_TYPE iolib_funcs[] = {
   {LNILKEY, LNILVAL}
 };
 
-/* Note that IO objects use a RAM metatable created to allow extensibility */
-
-static int io_index(lua_State *L)
-{
-  return luaR_findfunction(L, iolib_funcs);
-}
-
-const luaL_Reg iolib[] = {
-  {"__index", io_index},
-  {NULL, NULL}
-};
-
-#undef MIN_OPT_LEVEL
-#define MIN_OPT_LEVEL 1
 #include "lrodefs.h"
 const LUA_REG_TYPE flib[] = {
   {LSTRKEY("close"),      LFUNCVAL(io_close)},
@@ -481,6 +470,7 @@ const LUA_REG_TYPE flib[] = {
   {LNILKEY, LNILVAL}
 };
 
+static const luaL_Reg io_base[] = {{NULL, NULL}};
 
 static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
   *newfile(L) = f;
@@ -490,14 +480,18 @@ static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
   lua_setfield(L, -2, fname);
 }
 
-LUALIB_API int luaopen_io (lua_State *L) {
-  luaL_rometatable(L, LUA_FILEHANDLE, (void*)flib);  /* create metatable for file handles */
-  luaL_register_light(L, LUA_IOLIBNAME, iolib);
+LUALIB_API int luaopen_io(lua_State *L) {
+  luaL_rometatable(L, LUA_FILEHANDLE, (void*) flib);  /* create metatable for file handles */
+  luaL_register_light(L, LUA_IOLIBNAME, io_base);
   lua_pushvalue(L, -1);
   lua_setmetatable(L, -2);
+  lua_pushliteral(L, "__index");  
+  lua_pushrotable(L, (void *)iolib_funcs);
+  lua_rawset(L, -3);
+
   /* create (and set) default files */
   createstdfile(L, stdin, IO_INPUT, "stdin");
   createstdfile(L, stdout, IO_OUTPUT, "stdout");
-  createstdfile(L, stderr, 0, "stderr");
+  createstdfile(L, stderr, IO_STDERR, "stderr");
   return 1;
 }

+ 0 - 2
app/lua/luac_cross/loslib.c

@@ -20,8 +20,6 @@
 
 #include "lauxlib.h"
 #include "lualib.h"
-#include "lrotable.h"
-
 
 static int os_pushresult (lua_State *L, int i, const char *filename) {
   int en = errno;  /* calls to Lua API may change this value */

+ 0 - 7
app/lua/luaconf.h

@@ -896,13 +896,6 @@ union luai_Cast { double l_d; long l_l; };
 ** without modifying the main part of the file.
 */
 
-/* If you define the next macro you'll get the ability to set rotables as
-   metatables for tables/userdata/types (but the VM might run slower)
-*/
-#if (LUA_OPTIMIZE_MEMORY == 2)
-#define LUA_META_ROTABLES 
-#endif
-
 #if LUA_OPTIMIZE_MEMORY == 2 && defined(LUA_USE_POPEN)
 #error "Pipes not supported in aggresive optimization mode (LUA_OPTIMIZE_MEMORY=2)"
 #endif

+ 34 - 21
app/lua/lvm.c

@@ -130,18 +130,29 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
   TValue temp;
   for (loop = 0; loop < MAXTAGLOOP; loop++) {
     const TValue *tm;
-    if (ttistable(t) || ttisrotable(t)) {  /* `t' is a table? */
-      void *h = ttistable(t) ? hvalue(t) : rvalue(t);
-      const TValue *res = ttistable(t) ? luaH_get((Table*)h, key) : luaH_get_ro(h, key); /* do a primitive get */
+
+    if (ttistable(t)) {  /* `t' is a table? */
+      Table *h = hvalue(t);
+      const TValue *res = luaH_get(h, key); /* do a primitive get */
       if (!ttisnil(res) ||  /* result is no nil? */
-          (tm = fasttm(L, ttistable(t) ? ((Table*)h)->metatable : (Table*)luaR_getmeta(h), TM_INDEX)) == NULL) { /* or no TM? */
+          (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
         setobj2s(L, val, res);
         return;
-      }      
+      }
+      /* else will try the tag method */
+    } else if (ttisrotable(t)) {  /* `t' is a table? */
+      void *h = rvalue(t);
+      const TValue *res = luaH_get_ro(h, key); /* do a primitive get */
+      if (!ttisnil(res) ||  /* result is no nil? */
+          (tm = fasttm(L, (Table*)luaR_getmeta(h), TM_INDEX)) == NULL) { /* or no TM? */
+        setobj2s(L, val, res);
+        return;
+      }
       /* else will try the tag method */
     }
     else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
         luaG_typeerror(L, t, "index");
+
     if (ttisfunction(tm) || ttislightfunction(tm)) {
       callTMres(L, val, tm, t, key);
       return;
@@ -161,25 +172,27 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
   L->top++;
   fixedstack(L);
   for (loop = 0; loop < MAXTAGLOOP; loop++) {
-    const TValue *tm;
-    if (ttistable(t) || ttisrotable(t)) {  /* `t' is a table? */
-      void *h = ttistable(t) ? hvalue(t) : rvalue(t);
-      TValue *oldval = ttistable(t) ? luaH_set(L, (Table*)h, key) : NULL; /* do a primitive set */
-      if ((oldval && !ttisnil(oldval)) ||  /* result is no nil? */
-          (tm = fasttm(L, ttistable(t) ? ((Table*)h)->metatable : (Table*)luaR_getmeta(h), TM_NEWINDEX)) == NULL) { /* or no TM? */
-        if(oldval) {
-          L->top--;
-          unfixedstack(L);
-          setobj2t(L, oldval, val);
-          ((Table *)h)->flags = 0;
-          luaC_barriert(L, (Table*)h, val);
-        }
+    const TValue *tm = NULL;
+    if (ttistable(t)) {  /* `t' is a table? */
+      Table *h = hvalue(t);
+      TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
+      if ((!ttisnil(oldval)) ||  /* result is no nil? */
+          (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) {
+        L->top--;
+        unfixedstack(L);
+        setobj2t(L, oldval, val);
+        ((Table *)h)->flags = 0;
+        luaC_barriert(L, (Table*)h, val);
         return;
       }
       /* else will try the tag method */
     }
+    else if (ttisrotable(t)) {
+      luaG_runerror(L, "invalid write to ROM variable");
+    }
     else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
       luaG_typeerror(L, t, "index");
+
     if (ttisfunction(tm) || ttislightfunction(tm)) {
       L->top--;
       unfixedstack(L);
@@ -294,7 +307,7 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
     case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */
     case LUA_TROTABLE:
       return rvalue(t1) == rvalue(t2);
-    case LUA_TLIGHTUSERDATA: 
+    case LUA_TLIGHTUSERDATA:
     case LUA_TLIGHTFUNCTION:
       return pvalue(t1) == pvalue(t2);
     case LUA_TUSERDATA: {
@@ -321,7 +334,7 @@ void luaV_concat (lua_State *L, int total, int last) {
   if (G(L)->memlimit < max_sizet) max_sizet = G(L)->memlimit;
   do {
     /* Any call which does a memory allocation may trim the stack,
-       invalidating top unless the stack is fixed duri  ng the allocation */ 
+       invalidating top unless the stack is fixed during the allocation */
     StkId top = L->base + last + 1;
     fixedstack(L);
     int n = 2;  /* number of elements handled in this pass (at least 2) */
@@ -570,7 +583,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
       case OP_LEN: {
         const TValue *rb = RB(i);
         switch (ttype(rb)) {
-          case LUA_TTABLE: 
+          case LUA_TTABLE:
           case LUA_TROTABLE: {
             setnvalue(ra, ttistable(rb) ? cast_num(luaH_getn(hvalue(rb))) : cast_num(luaH_getn_ro(rvalue(rb))));
             break;

+ 3 - 3
app/modules/wifi_monitor.c

@@ -570,9 +570,9 @@ static int packet_map_lookup(lua_State *L) {
     }
 
     // Now search the packet function map
-    const TValue *res = luaR_findentry((void *) packet_function_map, field, 0, NULL);
-    if (res) {
-      luaA_pushobject(L, res);
+    lua_pushrotable(L, (void *)packet_function_map);
+    lua_getfield(L, -1, field);
+    if (!lua_isnil(L, -1)) {
       return 1;
     }
   }

+ 5 - 5
app/uzlib/host/uz_unzip.c

@@ -131,20 +131,20 @@ int main(int argc, char *argv[]) {
   assert(sizeof(unsigned int) == 4);
 
   /* allocate and zero the in and out Blocks */
-  assert(in  = uz_malloc(sizeof(*in)));
-  assert(out = uz_malloc(sizeof(*out)));
+  assert((in  = uz_malloc(sizeof(*in))) != NULL);
+  assert((out = uz_malloc(sizeof(*out))) != NULL);
 
   memset(in, 0, sizeof(*in));
   memset(out, 0, sizeof(*out));
 
   /* open input files and probe end to read the expanded length */
-  assert((in->fin = fopen(inFile, "rb")));
+  assert((in->fin = fopen(inFile, "rb")) != NULL);
   fseek(in->fin, -4, SEEK_END);
   assert(fread((uchar*)&(out->len), 1, 4, in->fin) == 4);
   in->len = ftell(in->fin);
   fseek(in->fin, 0, SEEK_SET);
   
-  assert((out->fout = fopen(outFile, "wb")));
+  assert((out->fout = fopen(outFile, "wb")) != NULL);
 
   printf ("Inflating in=%s out=%s\n", inFile, outFile);
 
@@ -152,7 +152,7 @@ int main(int argc, char *argv[]) {
   n = (out->len > DICTIONARY_WINDOW) ? WRITE_BLOCKS : 
                                       1 + (out->len-1) / WRITE_BLOCKSIZE;
   for(i = WRITE_BLOCKS - n + 1;  i <= WRITE_BLOCKS; i++)
-    assert(out->block[i % WRITE_BLOCKS] = uz_malloc(sizeof(outBlock)));
+    assert((out->block[i % WRITE_BLOCKS] = uz_malloc(sizeof(outBlock))) != NULL);
   
   out->breakNdx  = (out->len < WRITE_BLOCKSIZE) ? out->len : WRITE_BLOCKSIZE;
   out->fullBlkCB = processOutRec;