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.
This commit is contained in:
Terry Ellison 2018-10-13 17:14:33 +03:00 committed by GitHub
parent ff44b2f015
commit 5f67de8d48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 398 additions and 356 deletions

View File

@ -57,18 +57,8 @@
const LOCK_IN_SECTION(libs) \ const LOCK_IN_SECTION(libs) \
luaL_Reg MODULE_PASTE_(lua_lib_,cfgname) = { luaname, initfunc }; \ luaL_Reg MODULE_PASTE_(lua_lib_,cfgname) = { luaname, initfunc }; \
const LOCK_IN_SECTION(rotable) \ const LOCK_IN_SECTION(rotable) \
luaR_table MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(LUA_USE_MODULES_,cfgname))) \ luaR_entry MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(LUA_USE_MODULES_,cfgname))) \
= { luaname, map } = {LSTRKEY(luaname), LROVAL(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 }
#if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2) #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)" # error "NodeMCU modules must be built with LTR enabled (MIN_OPT_LEVEL=2 and LUA_OPTIMIZE_MEMORY=2)"

View File

@ -25,8 +25,6 @@
#define lauxlib_c #define lauxlib_c
#define LUA_LIB #define LUA_LIB
#include "lrotable.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "lgc.h" #include "lgc.h"
#include "ldo.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); if (e == NULL) e = fname + c_strlen(fname);
lua_pushlstring(L, fname, e - fname); lua_pushlstring(L, fname, e - fname);
lua_rawget(L, -2); 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? */ if (lua_isnil(L, -1)) { /* no such field? */
lua_pop(L, 1); /* remove this nil */ lua_pop(L, 1); /* remove this nil */
lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */

View File

@ -16,7 +16,7 @@
#include C_HEADER_STDLIB #include C_HEADER_STDLIB
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lrotable.h" #include "lrodefs.h"
@ -462,71 +462,62 @@ static int luaB_newproxy (lua_State *L) {
return 1; 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" #include "lrodefs.h"
const LUA_REG_TYPE base_funcs_list[] = {
LUA_BASELIB_FUNCLIST, extern const luaR_entry lua_rotable_base[];
{LNILKEY, LNILVAL}
/*
* 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 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
}; };
#endif
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;
}
}
static const luaL_Reg base_funcs[] = { 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,
#endif
{"__index", luaB_index},
{NULL, NULL} {NULL, NULL}
}; };
@ -661,7 +652,6 @@ static int luaB_corunning (lua_State *L) {
#undef MIN_OPT_LEVEL #undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 1 #define MIN_OPT_LEVEL 1
#include "lrodefs.h"
const LUA_REG_TYPE co_funcs[] = { const LUA_REG_TYPE co_funcs[] = {
{LSTRKEY("create"), LFUNCVAL(luaB_cocreate)}, {LSTRKEY("create"), LFUNCVAL(luaB_cocreate)},
{LSTRKEY("resume"), LFUNCVAL(luaB_coresume)}, {LSTRKEY("resume"), LFUNCVAL(luaB_coresume)},
@ -682,7 +672,6 @@ static void auxopen (lua_State *L, const char *name,
lua_setfield(L, -2, name); lua_setfield(L, -2, name);
} }
static void base_open (lua_State *L) { static void base_open (lua_State *L) {
/* set global _G */ /* set global _G */
lua_pushvalue(L, LUA_GLOBALSINDEX); lua_pushvalue(L, LUA_GLOBALSINDEX);
@ -692,10 +681,11 @@ static void base_open (lua_State *L) {
#if LUA_OPTIMIZE_MEMORY > 0 #if LUA_OPTIMIZE_MEMORY > 0
lua_pushvalue(L, -1); lua_pushvalue(L, -1);
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
#else lua_pushrotable(L, (void *)BASE_ROTABLE);
lua_setglobal(L, "__index");
#endif
lua_pushliteral(L, LUA_VERSION); lua_pushliteral(L, LUA_VERSION);
lua_setglobal(L, "_VERSION"); /* set global _VERSION */ lua_setglobal(L, "_VERSION"); /* set global _VERSION */
#endif
/* `ipairs' and `pairs' need auxliliary functions as upvalues */ /* `ipairs' and `pairs' need auxliliary functions as upvalues */
auxopen(L, "ipairs", luaB_ipairs, ipairsaux); auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
auxopen(L, "pairs", luaB_pairs, luaB_next); auxopen(L, "pairs", luaB_pairs, luaB_next);

View File

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

View File

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

View File

@ -15,60 +15,71 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "luaconf.h" #include "luaconf.h"
#include "module.h" #include "module.h"
#if defined(LUA_CROSS_COMPILER)
BUILTIN_LIB( start_list, NULL, NULL); #if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2)
BUILTIN_LIB_INIT( start_list, NULL, NULL); # error "NodeMCU modules must be built with LTR enabled (MIN_OPT_LEVEL=2 and LUA_OPTIMIZE_MEMORY=2)"
#endif #endif
extern const luaR_entry strlib[], tab_funcs[], dblib[], extern const luaR_entry strlib[], tab_funcs[], dblib[],
co_funcs[], math_map[], syslib[]; 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); * 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
BUILTIN_LIB( STRING, LUA_STRLIBNAME, strlib); * entries to be collected by the linker into consoliated tables. The linker
BUILTIN_LIB_INIT( STRING, LUA_STRLIBNAME, luaopen_string); * defines lua_libs_base and lua_rotable_base.
*
BUILTIN_LIB( TABLE, LUA_TABLIBNAME, tab_funcs); * This is not practical on Posix builds which use a standard loader declaration
BUILTIN_LIB_INIT( TABLE, LUA_TABLIBNAME, luaopen_table); * 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
BUILTIN_LIB( DBG, LUA_DBLIBNAME, dblib); * meta-method. In this case all library ROTables are defined here, avoiding the
BUILTIN_LIB_INIT( DBG, LUA_DBLIBNAME, luaopen_debug); * need for linker magic is avoided on host builds.
*/
BUILTIN_LIB( CO, LUA_COLIBNAME, co_funcs);
BUILTIN_LIB( MATH, LUA_MATHLIBNAME, math_map);
#if defined(LUA_CROSS_COMPILER) #if defined(LUA_CROSS_COMPILER)
extern const luaR_entry syslib[], iolib[]; #define LUA_ROTABLES lua_rotable_base
BUILTIN_LIB( OS, LUA_OSLIBNAME, syslib); #define LUA_LIBS lua_libs_base
BUILTIN_LIB_INIT( IO, LUA_IOLIBNAME, luaopen_io); #else /* declare Xtensa toolchain linker defined constants */
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.
*/
#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 */
extern const luaL_Reg lua_libs_base[]; extern const luaL_Reg lua_libs_base[];
extern const luaR_table lua_rotable_base[]; extern const luaR_entry lua_rotable_base[];
static const luaL_Reg *lua_libs = lua_libs_base; #define LUA_ROTABLES lua_rotable_core
const luaR_table *lua_rotable = lua_rotable_base; #define LUA_LIBS lua_libs_core
#endif #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
};
#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)
,ENTRY(LUA_OSLIBNAME, syslib),
LROT_END
#endif
};
void luaL_openlibs (lua_State *L) { void luaL_openlibs (lua_State *L) {
#if defined(LUA_CROSS_COMPILER) const luaL_Reg *lib = lua_libs_base;
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; /* loop round and open libraries */
#endif
const luaL_Reg *lib = lua_libs;
for (; lib->name; lib++) { for (; lib->name; lib++) {
if (lib->func) if (lib->func) {
{
lua_pushcfunction(L, lib->func); lua_pushcfunction(L, lib->func);
lua_pushstring(L, lib->name); lua_pushstring(L, lib->name);
lua_call(L, 1, 0); lua_call(L, 1, 0);

View File

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

View File

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

View File

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

View File

@ -38,5 +38,10 @@
return 1 return 1
#endif #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 */ #endif /* lrodefs_h */

View File

@ -9,77 +9,139 @@
#include "lobject.h" #include "lobject.h"
#include "lapi.h" #include "lapi.h"
/* Local defines */ #define ALIGNED_STRING (__attribute__((aligned(4))) char *)
#define LUAR_FINDFUNCTION 0 #define LA_LINES 16
#define LUAR_FINDVALUE 1 #define LA_SLOTS 4
//#define COLLECT_STATS
/* Externally defined read-only table array */ /*
extern const luaR_table *lua_rotable; * 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))
/* Find a global "read only table" in the constant lua_rotable array */ static struct {
void* luaR_findglobal(const char *name, unsigned len) { unsigned hash;
unsigned i; unsigned addr:24;
unsigned ndx:8;
} cache[LA_LINES][LA_SLOTS];
if (c_strlen(name) > LUA_MAX_ROTABLE_NAME) #ifdef COLLECT_STATS
return NULL; unsigned cache_stats[3];
for (i=0; lua_rotable[i].name; i ++) #define COUNT(i) cache_stats[i]++
if (*lua_rotable[i].name != '\0' && c_strlen(lua_rotable[i].name) == len && !c_strncmp(lua_rotable[i].name, name, len)) { #else
return (void*)(lua_rotable[i].pentries); #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;
} }
}
COUNT(1);
return -1;
}
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;
}
}
}
return luaO_nilobject;
}
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;
}
}
}
return NULL; return NULL;
} }
/* 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;
}
i ++; pentry ++;
}
if (res && ppos)
*ppos = i;
return res;
}
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;
}
else
return 0;
}
/* 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 */ /* Find the metatable of a given table */
void* luaR_getmeta(void *data) { void* luaR_getmeta(ROTable *rotable) {
#ifdef LUA_META_ROTABLES const TValue *res = luaR_findentry(rotable, NULL, NULL);
const TValue *res = luaR_auxfind((const luaR_entry*)data, "__metatable", 0, NULL);
return res && ttisrotable(res) ? rvalue(res) : 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(key);
setnilvalue(val); setnilvalue(val);
if (pentries[pos].key.type != LUA_TNIL) { 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); setobj2s(L, val, &pentries[pos].value);
} }
} }
/* next (used for iteration) */ /* next (used for iteration) */
void luaR_next(lua_State *L, void *data, TValue *key, TValue *val) { void luaR_next(lua_State *L, ROTable *rotable, 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;
unsigned keypos; unsigned keypos;
/* Special case: if key is nil, return the first element of the rotable */ /* Special case: if key is nil, return the first element of the rotable */
if (ttisnil(key)) if (ttisnil(key))
luaR_next_helper(L, pentries, 0, key, val); luaR_next_helper(L, rotable, 0, key, val);
else if (ttisstring(key) || ttisnumber(key)) { else if (ttisstring(key) || ttisnumber(key)) {
/* Find the previoud key again */ /* Find the previous key again */
if (ttisstring(key)) { if (ttisstring(key)) {
luaR_getcstr(strkey, rawtsvalue(key), LUA_MAX_ROTABLE_NAME); luaR_findentry(rotable, rawtsvalue(key), &keypos);
pstrkey = strkey; } else {
} else luaR_findentryN(rotable, (luaR_numkey)nvalue(key), &keypos);
numkey = (luaR_numkey)nvalue(key); }
luaR_findentry(data, pstrkey, numkey, &keypos);
/* Advance to next key */ /* Advance to next key */
keypos ++; keypos ++;
luaR_next_helper(L, pentries, keypos, key, val); 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

View File

@ -14,7 +14,11 @@
#define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER} #define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
#define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE} #define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE}
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL} #define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
#ifdef LUA_CROSS_COMPILER
#define LRO_STRKEY(k) {LUA_TSTRING, {.strkey = k}} #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_NUMKEY(k) {LUA_TNUMBER, {.numkey = k}}
#define LRO_NILKEY {LUA_TNIL, {.strkey=NULL}} #define LRO_NILKEY {LUA_TNIL, {.strkey=NULL}}
@ -25,40 +29,58 @@
typedef int luaR_numkey; typedef int luaR_numkey;
/* The next structure defines the type of a key */ /* The next structure defines the type of a key */
typedef struct typedef struct {
{
int type; int type;
union union {
{
const char* strkey; const char* strkey;
luaR_numkey numkey; luaR_numkey numkey;
} id; } id;
} luaR_key; } luaR_key;
/* An entry in the read only table */ /* An entry in the read only table */
typedef struct typedef struct luaR_entry {
{
const luaR_key key; const luaR_key key;
const TValue value; const TValue value;
} luaR_entry; } luaR_entry;
/* A rotable */ /*
typedef struct * 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
const char *name; * as a logical ROTable.
const luaR_entry *pentries; */
} luaR_table; typedef const struct luaR_entry ROTable;
void* luaR_findglobal(const char *key, unsigned len); const TValue* luaR_findentry(ROTable *tab, TString *key, unsigned *ppos);
int luaR_findfunction(lua_State *L, const luaR_entry *ptable); const TValue* luaR_findentryN(ROTable *tab, luaR_numkey numkey, unsigned *ppos);
const TValue* luaR_findentry(void *data, const char *strkey, luaR_numkey numkey, unsigned *ppos); void luaR_next(lua_State *L, ROTable *tab, TValue *key, TValue *val);
void luaR_getcstr(char *dest, const TString *src, size_t maxsize); void* luaR_getmeta(ROTable *tab);
void luaR_next(lua_State *L, void *data, TValue *key, TValue *val);
void* luaR_getmeta(void *data);
#ifdef LUA_META_ROTABLES
int luaR_isrotable(void *p); 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 #else
#define luaR_isrotable(p) (0) #define _RODATA_END _edata
#endif #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 #endif

View File

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

View File

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

View File

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

View File

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

View File

@ -50,14 +50,22 @@ void luaT_init (lua_State *L) {
** tag methods ** tag methods
*/ */
const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { 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); 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 */ events->flags |= cast_byte(1u<<event); /* cache this fact */
return NULL; return NULL;
}
} }
else return tm; return tm;
} }

View File

@ -9,7 +9,7 @@
#include "lobject.h" #include "lobject.h"
#include "lrotable.h"
/* /*
* WARNING: if you change the order of this enumeration, * WARNING: if you change the order of this enumeration,
@ -36,12 +36,10 @@ typedef enum {
TM_N /* number of elements in the enum */ TM_N /* number of elements in the enum */
} TMS; } TMS;
#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ #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[]; LUAI_DATA const char *const luaT_typenames[];

View File

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

View File

@ -18,7 +18,6 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lrotable.h"
#define IO_INPUT 1 #define IO_INPUT 1
#define IO_OUTPUT 2 #define IO_OUTPUT 2
@ -28,7 +27,11 @@
#define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f])) #define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f]))
/* "Pseudo-random" keys for the registry */ /* "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"}; static const char *const fnames[] = {"input", "output"};
@ -452,20 +455,6 @@ const LUA_REG_TYPE iolib_funcs[] = {
{LNILKEY, LNILVAL} {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" #include "lrodefs.h"
const LUA_REG_TYPE flib[] = { const LUA_REG_TYPE flib[] = {
{LSTRKEY("close"), LFUNCVAL(io_close)}, {LSTRKEY("close"), LFUNCVAL(io_close)},
@ -481,6 +470,7 @@ const LUA_REG_TYPE flib[] = {
{LNILKEY, LNILVAL} {LNILKEY, LNILVAL}
}; };
static const luaL_Reg io_base[] = {{NULL, NULL}};
static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
*newfile(L) = f; *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); lua_setfield(L, -2, fname);
} }
LUALIB_API int luaopen_io (lua_State *L) { LUALIB_API int luaopen_io(lua_State *L) {
luaL_rometatable(L, LUA_FILEHANDLE, (void*)flib); /* create metatable for file handles */ luaL_rometatable(L, LUA_FILEHANDLE, (void*) flib); /* create metatable for file handles */
luaL_register_light(L, LUA_IOLIBNAME, iolib); luaL_register_light(L, LUA_IOLIBNAME, io_base);
lua_pushvalue(L, -1); lua_pushvalue(L, -1);
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
lua_pushliteral(L, "__index");
lua_pushrotable(L, (void *)iolib_funcs);
lua_rawset(L, -3);
/* create (and set) default files */ /* create (and set) default files */
createstdfile(L, stdin, IO_INPUT, "stdin"); createstdfile(L, stdin, IO_INPUT, "stdin");
createstdfile(L, stdout, IO_OUTPUT, "stdout"); createstdfile(L, stdout, IO_OUTPUT, "stdout");
createstdfile(L, stderr, 0, "stderr"); createstdfile(L, stderr, IO_STDERR, "stderr");
return 1; return 1;
} }

View File

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

View File

@ -896,13 +896,6 @@ union luai_Cast { double l_d; long l_l; };
** without modifying the main part of the file. ** 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) #if LUA_OPTIMIZE_MEMORY == 2 && defined(LUA_USE_POPEN)
#error "Pipes not supported in aggresive optimization mode (LUA_OPTIMIZE_MEMORY=2)" #error "Pipes not supported in aggresive optimization mode (LUA_OPTIMIZE_MEMORY=2)"
#endif #endif

View File

@ -130,11 +130,21 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
TValue temp; TValue temp;
for (loop = 0; loop < MAXTAGLOOP; loop++) { for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm; const TValue *tm;
if (ttistable(t) || ttisrotable(t)) { /* `t' is a table? */
void *h = ttistable(t) ? hvalue(t) : rvalue(t); if (ttistable(t)) { /* `t' is a table? */
const TValue *res = ttistable(t) ? luaH_get((Table*)h, key) : luaH_get_ro(h, key); /* do a primitive get */ Table *h = hvalue(t);
const TValue *res = luaH_get(h, key); /* do a primitive get */
if (!ttisnil(res) || /* result is no nil? */ 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); setobj2s(L, val, res);
return; return;
} }
@ -142,6 +152,7 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
} }
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
luaG_typeerror(L, t, "index"); luaG_typeerror(L, t, "index");
if (ttisfunction(tm) || ttislightfunction(tm)) { if (ttisfunction(tm) || ttislightfunction(tm)) {
callTMres(L, val, tm, t, key); callTMres(L, val, tm, t, key);
return; return;
@ -161,25 +172,27 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
L->top++; L->top++;
fixedstack(L); fixedstack(L);
for (loop = 0; loop < MAXTAGLOOP; loop++) { for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm; const TValue *tm = NULL;
if (ttistable(t) || ttisrotable(t)) { /* `t' is a table? */ if (ttistable(t)) { /* `t' is a table? */
void *h = ttistable(t) ? hvalue(t) : rvalue(t); Table *h = hvalue(t);
TValue *oldval = ttistable(t) ? luaH_set(L, (Table*)h, key) : NULL; /* do a primitive set */ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
if ((oldval && !ttisnil(oldval)) || /* result is no nil? */ if ((!ttisnil(oldval)) || /* result is no nil? */
(tm = fasttm(L, ttistable(t) ? ((Table*)h)->metatable : (Table*)luaR_getmeta(h), TM_NEWINDEX)) == NULL) { /* or no TM? */ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) {
if(oldval) { L->top--;
L->top--; unfixedstack(L);
unfixedstack(L); setobj2t(L, oldval, val);
setobj2t(L, oldval, val); ((Table *)h)->flags = 0;
((Table *)h)->flags = 0; luaC_barriert(L, (Table*)h, val);
luaC_barriert(L, (Table*)h, val);
}
return; return;
} }
/* else will try the tag method */ /* 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))) else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
luaG_typeerror(L, t, "index"); luaG_typeerror(L, t, "index");
if (ttisfunction(tm) || ttislightfunction(tm)) { if (ttisfunction(tm) || ttislightfunction(tm)) {
L->top--; L->top--;
unfixedstack(L); unfixedstack(L);
@ -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; if (G(L)->memlimit < max_sizet) max_sizet = G(L)->memlimit;
do { do {
/* Any call which does a memory allocation may trim the stack, /* 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; StkId top = L->base + last + 1;
fixedstack(L); fixedstack(L);
int n = 2; /* number of elements handled in this pass (at least 2) */ int n = 2; /* number of elements handled in this pass (at least 2) */

View File

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

View File

@ -131,20 +131,20 @@ int main(int argc, char *argv[]) {
assert(sizeof(unsigned int) == 4); assert(sizeof(unsigned int) == 4);
/* allocate and zero the in and out Blocks */ /* allocate and zero the in and out Blocks */
assert(in = uz_malloc(sizeof(*in))); assert((in = uz_malloc(sizeof(*in))) != NULL);
assert(out = uz_malloc(sizeof(*out))); assert((out = uz_malloc(sizeof(*out))) != NULL);
memset(in, 0, sizeof(*in)); memset(in, 0, sizeof(*in));
memset(out, 0, sizeof(*out)); memset(out, 0, sizeof(*out));
/* open input files and probe end to read the expanded length */ /* 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); fseek(in->fin, -4, SEEK_END);
assert(fread((uchar*)&(out->len), 1, 4, in->fin) == 4); assert(fread((uchar*)&(out->len), 1, 4, in->fin) == 4);
in->len = ftell(in->fin); in->len = ftell(in->fin);
fseek(in->fin, 0, SEEK_SET); 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); 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 : n = (out->len > DICTIONARY_WINDOW) ? WRITE_BLOCKS :
1 + (out->len-1) / WRITE_BLOCKSIZE; 1 + (out->len-1) / WRITE_BLOCKSIZE;
for(i = WRITE_BLOCKS - n + 1; i <= WRITE_BLOCKS; i++) 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->breakNdx = (out->len < WRITE_BLOCKSIZE) ? out->len : WRITE_BLOCKSIZE;
out->fullBlkCB = processOutRec; out->fullBlkCB = processOutRec;