Commit bbeb09b6 authored by Terry Ellison's avatar Terry Ellison Committed by Marcel Stör
Browse files

Squashed updates do get Lua51 and Lua53 working (#3075)

-  Lots of minor but nasty bugfixes to get all tests to run clean
-  core lua and test suite fixes to allow luac -F to run cleanly against test suite
-  next tranch to get LFS working
-  luac.cross -a options plus fixes from feedback
-  UART fixes and lua.c merge
-  commit of wip prior to rebaselining against current dev
-  more tweaks
parent 99aba344
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#define ldo_c #define ldo_c
#define LUA_CORE #define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include <string.h> #include <string.h>
...@@ -254,13 +253,13 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { ...@@ -254,13 +253,13 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
return base; return base;
} }
static StkId tryfuncTM (lua_State *L, StkId func) { static StkId tryfuncTM (lua_State *L, StkId func) {
const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
StkId p; StkId p;
ptrdiff_t funcr = savestack(L, func); ptrdiff_t funcr = savestack(L, func);
if (!ttisfunction(tm)) if (!ttisfunction(tm)) {
luaG_typeerror(L, func, "call"); luaG_typeerror(L, func, "call");
}
/* Open a hole inside the stack at `func' */ /* Open a hole inside the stack at `func' */
for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
incr_top(L); incr_top(L);
...@@ -279,10 +278,10 @@ static StkId tryfuncTM (lua_State *L, StkId func) { ...@@ -279,10 +278,10 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
int luaD_precall (lua_State *L, StkId func, int nresults) { int luaD_precall (lua_State *L, StkId func, int nresults) {
ptrdiff_t funcr; ptrdiff_t funcr;
LClosure *cl = NULL; LClosure *cl = NULL;
if (!ttisfunction(func) && !ttislightfunction(func)) /* `func' is not a function? */ if (!ttisfunction(func)) /* `func' is not a function? */
func = tryfuncTM(L, func); /* check the `function' tag method */ func = tryfuncTM(L, func); /* check the `function' tag method */
funcr = savestack(L, func); funcr = savestack(L, func);
if (ttisfunction(func)) if (!ttislightfunction(func))
cl = &clvalue(func)->l; cl = &clvalue(func)->l;
L->ci->savedpc = L->savedpc; L->ci->savedpc = L->savedpc;
if (cl && !cl->isC) { /* Lua function? prepare its call */ if (cl && !cl->isC) { /* Lua function? prepare its call */
...@@ -332,10 +331,10 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { ...@@ -332,10 +331,10 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
if (L->hookmask & LUA_MASKCALL) if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1); luaD_callhook(L, LUA_HOOKCALL, -1);
lua_unlock(L); lua_unlock(L);
if (ttisfunction(ci->func)) if (ttislightfunction(ci->func))
n = (*curr_func(L)->c.f)(L); /* do the actual call */
else
n = ((lua_CFunction)fvalue(ci->func))(L); /* do the actual call */ n = ((lua_CFunction)fvalue(ci->func))(L); /* do the actual call */
else
n = (*curr_func(L)->c.f)(L); /* do the actual call */
lua_lock(L); lua_lock(L);
if (n < 0) /* yielding? */ if (n < 0) /* yielding? */
return PCRYIELD; return PCRYIELD;
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#define ldump_c #define ldump_c
#define LUA_CORE #define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include <string.h> #include <string.h>
......
// Lua EGC (Emergeny Garbage Collector) interface
#include "legc.h"
#include "lstate.h"
void legc_set_mode(lua_State *L, int mode, int limit) {
global_State *g = G(L);
g->egcmode = mode;
g->memlimit = limit;
}
// Lua EGC (Emergeny Garbage Collector) interface
#ifndef __LEGC_H__
#define __LEGC_H__
#include "lstate.h"
// EGC operations modes
#define EGC_NOT_ACTIVE 0 // EGC disabled
#define EGC_ON_ALLOC_FAILURE 1 // run EGC on allocation failure
#define EGC_ON_MEM_LIMIT 2 // run EGC when an upper memory limit is hit
#define EGC_ALWAYS 4 // always run EGC before an allocation
void legc_set_mode(lua_State *L, int mode, int limit);
#endif
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#define lflash_c #define lflash_c
#define LUA_CORE #define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include "lobject.h" #include "lobject.h"
...@@ -89,9 +88,8 @@ void dumpStrt(stringtable *tb, const char *type) { ...@@ -89,9 +88,8 @@ void dumpStrt(stringtable *tb, const char *type) {
for (i=0; i<tb->size; i++) for (i=0; i<tb->size; i++)
for(o = tb->hash[i], j=0; o; (o=o->gch.next), j++ ) { for(o = tb->hash[i], j=0; o; (o=o->gch.next), j++ ) {
TString *ts =cast(TString *, o); TString *ts =cast(TString *, o);
NODE_DBG("%5d %5d %08x %08x %5d %1s %s\n", NODE_DBG("%5d %5d %08x %08x %5d %s\n",
i, j, (size_t) ts, ts->tsv.hash, ts->tsv.len, i, j, (size_t) ts, ts->tsv.hash, ts->tsv.len, getstr(ts));
ts_isreadonly(ts) ? "R" : " ", getstr(ts));
} }
} }
...@@ -200,7 +198,6 @@ static void procFirstPass (void); ...@@ -200,7 +198,6 @@ static void procFirstPass (void);
* Library function called by node.flashreload(filename). * Library function called by node.flashreload(filename).
*/ */
LUALIB_API int luaN_reload_reboot (lua_State *L) { LUALIB_API int luaN_reload_reboot (lua_State *L) {
// luaL_dbgbreak();
const char *fn = lua_tostring(L, 1), *msg = ""; const char *fn = lua_tostring(L, 1), *msg = "";
int status; int status;
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#define lfunc_c #define lfunc_c
#define LUA_CORE #define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include <string.h> #include <string.h>
...@@ -146,7 +145,6 @@ void luaF_freeproto (lua_State *L, Proto *f) { ...@@ -146,7 +145,6 @@ void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray(L, f->k, f->sizek, TValue); luaM_freearray(L, f->k, f->sizek, TValue);
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
if (!proto_isreadonly(f)) {
luaM_freearray(L, f->code, f->sizecode, Instruction); luaM_freearray(L, f->code, f->sizecode, Instruction);
#ifdef LUA_OPTIMIZE_DEBUG #ifdef LUA_OPTIMIZE_DEBUG
if (f->packedlineinfo) { if (f->packedlineinfo) {
...@@ -155,7 +153,6 @@ void luaF_freeproto (lua_State *L, Proto *f) { ...@@ -155,7 +153,6 @@ void luaF_freeproto (lua_State *L, Proto *f) {
#else #else
luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
#endif #endif
}
luaM_free(L, f); luaM_free(L, f);
} }
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#define lgc_c #define lgc_c
#define LUA_CORE #define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include <string.h> #include <string.h>
...@@ -21,7 +20,6 @@ ...@@ -21,7 +20,6 @@
#include "lstring.h" #include "lstring.h"
#include "ltable.h" #include "ltable.h"
#include "ltm.h" #include "ltm.h"
#include "lrotable.h"
#define GCSTEPSIZE 1024u #define GCSTEPSIZE 1024u
#define GCSWEEPMAX 40 #define GCSWEEPMAX 40
...@@ -54,7 +52,6 @@ ...@@ -54,7 +52,6 @@
#define markobject(g,t) { if (iswhite(obj2gco(t))) \ #define markobject(g,t) { if (iswhite(obj2gco(t))) \
reallymarkobject(g, obj2gco(t)); } reallymarkobject(g, obj2gco(t)); }
#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
...@@ -81,7 +78,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { ...@@ -81,7 +78,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
case LUA_TUSERDATA: { case LUA_TUSERDATA: {
Table *mt = gco2u(o)->metatable; Table *mt = gco2u(o)->metatable;
gray2black(o); /* udata are never gray */ gray2black(o); /* udata are never gray */
if (mt && !luaR_isrotable(mt)) markobject(g, mt); if (mt && isrwtable(mt)) markobject(g, mt);
markobject(g, gco2u(o)->env); markobject(g, gco2u(o)->env);
return; return;
} }
...@@ -159,7 +156,6 @@ size_t luaC_separateudata (lua_State *L, int all) { ...@@ -159,7 +156,6 @@ size_t luaC_separateudata (lua_State *L, int all) {
return deadmem; return deadmem;
} }
static int traversetable (global_State *g, Table *h) { static int traversetable (global_State *g, Table *h) {
int i; int i;
int weakkey = 0; int weakkey = 0;
...@@ -167,7 +163,7 @@ static int traversetable (global_State *g, Table *h) { ...@@ -167,7 +163,7 @@ static int traversetable (global_State *g, Table *h) {
const TValue *mode = luaO_nilobject; const TValue *mode = luaO_nilobject;
if (h->metatable) { if (h->metatable) {
if (!luaR_isrotable(h->metatable)) if (isrwtable(h->metatable))
markobject(g, h->metatable); markobject(g, h->metatable);
mode = gfasttm(g, h->metatable, TM_MODE); mode = gfasttm(g, h->metatable, TM_MODE);
} }
...@@ -330,13 +326,11 @@ static l_mem propagatemark (global_State *g) { ...@@ -330,13 +326,11 @@ static l_mem propagatemark (global_State *g) {
sizeof(TValue) * p->sizek + sizeof(TValue) * p->sizek +
sizeof(LocVar) * p->sizelocvars + sizeof(LocVar) * p->sizelocvars +
sizeof(TString *) * p->sizeupvalues + sizeof(TString *) * p->sizeupvalues +
(proto_isreadonly(p) ? 0 : sizeof(Instruction) * p->sizecode + sizeof(Instruction) * p->sizecode +
#ifdef LUA_OPTIMIZE_DEBUG #ifdef LUA_OPTIMIZE_DEBUG
(p->packedlineinfo ? (p->packedlineinfo ? strlen(cast(char *, p->packedlineinfo))+1 : 0);
strlen(cast(char *, p->packedlineinfo))+1 :
0));
#else #else
sizeof(int) * p->sizelineinfo); sizeof(int) * p->sizelineinfo;
#endif #endif
} }
default: lua_assert(0); return 0; default: lua_assert(0); return 0;
...@@ -522,7 +516,7 @@ void luaC_freeall (lua_State *L) { ...@@ -522,7 +516,7 @@ void luaC_freeall (lua_State *L) {
static void markmt (global_State *g) { static void markmt (global_State *g) {
int i; int i;
for (i=0; i<NUM_TAGS; i++) for (i=0; i<NUM_TAGS; i++)
if (g->mt[i] && !luaR_isrotable(g->mt[i])) markobject(g, g->mt[i]); if (g->mt[i] && isrwtable(g->mt[i])) markobject(g, g->mt[i]);
} }
...@@ -712,7 +706,7 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { ...@@ -712,7 +706,7 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
global_State *g = G(L); global_State *g = G(L);
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
lua_assert(o->gch.tt != LUA_TTABLE); lua_assert((gettt(o) & LUA_TMASK) != LUA_TTABLE);
/* must keep invariant? */ /* must keep invariant? */
if (g->gcstate == GCSpropagate) if (g->gcstate == GCSpropagate)
reallymarkobject(g, v); /* Restore invariant */ reallymarkobject(g, v); /* Restore invariant */
......
...@@ -7,109 +7,106 @@ ...@@ -7,109 +7,106 @@
#define linit_c #define linit_c
#define LUA_LIB #define LUA_LIB
#define LUAC_CROSS_FILE
/*
** NodeMCU uses RO segment based static ROTable declarations for all library
** tables, including the index of library tables itself (the ROM table). These
** tables can be moved from RAM to flash ROM on the ESPs.
**
** On the ESPs targets, we can marshal the table entries through linker-based
** PSECTs to enable the library initiation tables to be bound during the link
** process rather than being statically declared here. This simplifies the
** addition of new modules and configuring builds with a subset of the total
** modules available.
**
** Such a linker-based approach is not practical for cross compiler builds that
** must link on a range of platforms, and where we don't have control of PSECT
** placement. However unlike the target builds, the luac.cross builds only
** use a small and fixed list of libraries and so in this case all of libraries
** are defined here, avoiding the need for linker magic on host builds.
**
** Note that a separate ROTable is defined in lbaselib.c on luac.cross builds
** for the base functions. (These use linker based entries on target builds)
** and there is a metatable index cascade from _G to this base function table
** to the master rotables table. In the target build, the linker marshals the
** table, hence the LROT_BREAK() macros which don't 0 terminate the lists and
** skip generating the ROtable header.
*/
#include "lua.h" #include "lua.h"
#include "lualib.h" #include "lualib.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "luaconf.h"
#include "module.h"
#include "lstate.h" #include "lstate.h"
#include "lnodemcu.h"
LROT_EXTERN(strlib); extern LROT_TABLE(strlib);
LROT_EXTERN(tab_funcs); extern LROT_TABLE(tab_funcs);
LROT_EXTERN(dblib); extern LROT_TABLE(dblib);
LROT_EXTERN(co_funcs); extern LROT_TABLE(co_funcs);
LROT_EXTERN(math); extern LROT_TABLE(math);
#if defined(LUA_CROSS_COMPILER)
LROT_EXTERN(oslib);
LROT_EXTERN(iolib);
#endif
/*
* The NodeMCU Lua initalisation has been adapted to use linker-based module
* registration. This uses a PSECT naming convention to allow the ROTable and
* initialisation function entries to be collected by the linker into two
* consoliated ROTables. This significantly simplifies adding new modules and
* configuring builds with a small subset of the total modules.
*
* This linker-based approach is not practical for cross compiler builds which
* must link on a range of platforms, and where we don't have control of PSECT
* placement. However unlike the target builds, the luac.cross builds only
* used a small and fixed list of libraries and so in this case the table can
* be defined in this source file, so in this case all library ROTables are
* defined here, avoiding the need for linker magic is avoided on host builds.
*
* Note that a separate ROTable is defined in lbaselib.c for the base functions
* and there is a metatable index cascade from _G to this base function table to
* the master rotables table. In the target build, the linker marshals the
* table, hence the LROT_BREAK() macros which don't 0 terminate the lists.
*/
#ifdef _MSC_VER #define LROT_ROM_ENTRIES \
//MSVC requires us to declare these sections before we refer to them LROT_TABENTRY( string, strlib ) \
#pragma section(__ROSECNAME(A), read) LROT_TABENTRY( table, tab_funcs ) \
#pragma section(__ROSECNAME(zzzzzzzz), read) LROT_TABENTRY( debug, dblib) \
#pragma section(__ROSECNAME(libs), read) LROT_TABENTRY( coroutine, co_funcs ) \
#pragma section(__ROSECNAME(rotable), read) LROT_TABENTRY( math, math ) \
//These help us to find the beginning and ending of the RO data. NOTE: linker LROT_TABENTRY( ROM, rotables )
//magic is used; the section names are lexically sorted, so 'a' and 'z' are
//important to keep the other sections lexically between these two dummy
//variables. Check your mapfile output if you need to fiddle with this stuff.
const LOCK_IN_SECTION(A) char _ro_start[1] = {0};
const LOCK_IN_SECTION(zzzzzzzz) char _ro_end[1] = {0};
#endif
LROT_PUBLIC_TABLE(lua_rotables) #define LROT_LIB_ENTRIES \
LROT_FUNCENTRY( _G, luaopen_base ) /* This MUST be called first */ \
LROT_FUNCENTRY( package, luaopen_package ) \
LROT_FUNCENTRY( string, luaopen_string ) \
LROT_FUNCENTRY( debug, luaopen_debug )
LROT_PUBLIC_BEGIN(LOCK_IN_SECTION(rotable) lua_rotables) #if defined(LUA_CROSS_COMPILER)
LROT_TABENTRY( string, strlib ) extern LROT_TABLE(base_func);
LROT_TABENTRY( table, tab_funcs ) LROT_BEGIN(rotables_meta, NULL, LROT_MASK_INDEX)
LROT_TABENTRY( debug, dblib) LROT_TABENTRY( _index, base_func)
LROT_TABENTRY( coroutine, co_funcs ) LROT_END(rotables_meta, NULL, LROT_MASK_INDEX)
LROT_TABENTRY( math, math )
LROT_TABENTRY( ROM, lua_rotables ) extern LROT_TABLE(oslib);
#ifdef LUA_CROSS_COMPILER extern LROT_TABLE(iolib);
LROT_BEGIN(rotables, LROT_TABLEREF(rotables_meta), 0)
LROT_ROM_ENTRIES
LROT_TABENTRY( os, oslib ) LROT_TABENTRY( os, oslib )
LROT_TABENTRY( io, iolib ) LROT_TABENTRY( io, iolib )
LROT_END(lua_rotables, NULL, 0) LROT_END(rotables, LROT_TABLEREF(rotables_meta), 0)
#else
LROT_BREAK(lua_rotables)
#endif
LROT_PUBLIC_BEGIN(LOCK_IN_SECTION(libs) lua_libs) LROT_BEGIN(lua_libs, NULL, 0)
LROT_FUNCENTRY( _, luaopen_base ) LROT_LIB_ENTRIES
LROT_FUNCENTRY( package, luaopen_package )
LROT_FUNCENTRY( string, luaopen_string )
LROT_FUNCENTRY( table, luaopen_table )
LROT_FUNCENTRY( debug, luaopen_debug )
#ifndef LUA_CROSS_COMPILER
LROT_BREAK(lua_rotables)
#else
LROT_FUNCENTRY( io, luaopen_io ) LROT_FUNCENTRY( io, luaopen_io )
LROT_END( lua_libs, NULL, 0) LROT_END(lua_libs, NULL, 0)
#endif
#else
extern const ROTable_entry lua_libs_base[];
extern const ROTable_entry lua_rotable_base[];
ROTable rotables_ROTable;
LROT_ENTRIES_IN_SECTION(rotables, rotable)
LROT_ROM_ENTRIES
LROT_BREAK(rotables)
LROT_ENTRIES_IN_SECTION(lua_libs, libs)
LROT_LIB_ENTRIES
LROT_BREAK(lua_libs)
#ifndef LUA_CROSS_COMPILER
extern void luaL_dbgbreak(void);
#endif #endif
void luaL_openlibs (lua_State *L) {
lua_pushrotable(L, LROT_TABLEREF(lua_libs)); void luaL_openlibs (lua_State *L) {
lua_pushnil(L); /* first key */ #ifdef LUA_CROSS_COMPILER
/* loop round and open libraries */ const ROTable_entry *p = LROT_TABLEREF(lua_libs)->entry;
#ifndef LUA_CROSS_COMPILER #else
// luaL_dbgbreak(); // This is a test point for debugging library start ups const ROTable_entry *p = lua_libs_base;
lua_createrotable(L, LROT_TABLEREF(rotables), lua_rotable_base, NULL);
#endif #endif
while (lua_next(L, -2) != 0) { while (p->key) {
if (lua_islightfunction(L,-1) && if (ttislightfunction(&p->value) && fvalue(&p->value)) {
fvalue(L->top-1)) { // only process function entries lua_pushcfunction(L, fvalue(&p->value));
lua_pushvalue(L, -2); lua_pushstring(L, p->key);
lua_call(L, 1, 0); // call luaopen_XXX(libname) lua_call(L, 1, 0); // call luaopen_XXX(libname)
} else {
lua_pop(L, 1);
} }
p++;
} }
lua_pop(L, 1); //cleanup stack
} }
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#define llex_c #define llex_c
#define LUA_CORE #define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include <ctype.h> #include <ctype.h>
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#define lmathlib_c #define lmathlib_c
#define LUA_LIB #define LUA_LIB
#define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include <stdlib.h> #include <stdlib.h>
...@@ -15,7 +14,7 @@ ...@@ -15,7 +14,7 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lrotable.h" #include "lnodemcu.h"
#undef PI #undef PI
#define PI (3.14159265358979323846) #define PI (3.14159265358979323846)
...@@ -309,7 +308,7 @@ static int math_randomseed (lua_State *L) { ...@@ -309,7 +308,7 @@ static int math_randomseed (lua_State *L) {
return 0; return 0;
} }
LROT_PUBLIC_BEGIN(math) LROT_BEGIN(math, NULL, 0)
#ifdef LUA_NUMBER_INTEGRAL #ifdef LUA_NUMBER_INTEGRAL
LROT_FUNCENTRY( abs, math_abs ) LROT_FUNCENTRY( abs, math_abs )
LROT_FUNCENTRY( ceil, math_identity ) LROT_FUNCENTRY( ceil, math_identity )
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#define lmem_c #define lmem_c
#define LUA_CORE #define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
......
...@@ -18,10 +18,9 @@ ...@@ -18,10 +18,9 @@
#include "lstring.h" #include "lstring.h"
#include "ltable.h" #include "ltable.h"
#include "ltm.h" #include "ltm.h"
#include "lrotable.h" #include "lnodemcu.h"
#include "platform.h" #include "platform.h"
extern int debug_errorfb (lua_State *L);
/* /*
** Error Reporting Task. We can't pass a string parameter to the error reporter ** Error Reporting Task. We can't pass a string parameter to the error reporter
** directly through the task interface the call is wrapped in a C closure with ** directly through the task interface the call is wrapped in a C closure with
...@@ -39,14 +38,16 @@ static int report_traceback (lua_State *L) { ...@@ -39,14 +38,16 @@ static int report_traceback (lua_State *L) {
** Catch all error handler for CB calls. This uses debug.traceback() to ** Catch all error handler for CB calls. This uses debug.traceback() to
** generate a full Lua traceback. ** generate a full Lua traceback.
*/ */
int luaN_traceback (lua_State *L) { LUALIB_API int luaL_traceback (lua_State *L) {
if (lua_isstring(L, 1)) { if (lua_isstring(L, 1)) {
lua_pushlightfunction(L, &debug_errorfb); lua_getglobal(L, "debug");
lua_getfield(L, -1, "traceback");
lua_remove(L, -2);
lua_pushvalue(L, 1); /* pass error message */ lua_pushvalue(L, 1); /* pass error message */
lua_pushinteger(L, 2); /* skip this function and traceback */ lua_pushinteger(L, 2); /* skip this function and traceback */
lua_call(L, 2, 1); /* call debug.traceback and return it as a string */ lua_call(L, 2, 1); /* call debug.traceback and return it as a string */
lua_pushcclosure(L, report_traceback, 1); /* report with str as upval */ lua_pushcclosure(L, report_traceback, 1); /* report with str as upval */
luaN_posttask(L, LUA_TASK_HIGH); luaL_posttask(L, LUA_TASK_HIGH);
} }
return 0; return 0;
} }
...@@ -56,18 +57,15 @@ int luaN_traceback (lua_State *L) { ...@@ -56,18 +57,15 @@ int luaN_traceback (lua_State *L) {
** an error handler which will catch any error and then post this to the ** an error handler which will catch any error and then post this to the
** registered reporter function as a separate follow-on task. ** registered reporter function as a separate follow-on task.
*/ */
int luaN_call (lua_State *L, int narg, int nres, int doGC) { // [-narg, +0, v] LUALIB_API int luaL_pcallx (lua_State *L, int narg, int nres) { // [-narg, +0, v]
int status; int status;
int base = lua_gettop(L) - narg; int base = lua_gettop(L) - narg;
lua_pushcfunction(L, luaN_traceback); lua_pushcfunction(L, luaL_traceback);
lua_insert(L, base); /* put under args */ lua_insert(L, base); /* put under args */
status = lua_pcall(L, narg, (nres < 0 ? LUA_MULTRET : nres), base); status = lua_pcall(L, narg, (nres < 0 ? LUA_MULTRET : nres), base);
lua_remove(L, base); /* remove traceback function */ lua_remove(L, base); /* remove traceback function */
if (status && nres >=0) if (status && nres >=0)
lua_settop(L, base + nres); /* balance the stack on error */ lua_settop(L, base + nres); /* balance the stack on error */
/* force a complete garbage collection if requested */
if (doGC)
lua_gc(L, LUA_GCCOLLECT, 0);
return status; return status;
} }
...@@ -84,21 +82,21 @@ static void do_task (platform_task_param_t task_fn_ref, uint8_t prio) { ...@@ -84,21 +82,21 @@ static void do_task (platform_task_param_t task_fn_ref, uint8_t prio) {
/* Pop the CB func from the Reg */ /* Pop the CB func from the Reg */
//dbg_printf("calling Reg[%u]\n", task_fn_ref); //dbg_printf("calling Reg[%u]\n", task_fn_ref);
lua_rawgeti(L, LUA_REGISTRYINDEX, (int) task_fn_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
luaL_checkanyfunction(L, -1); luaL_checkfunction(L, -1);
luaL_unref(L, LUA_REGISTRYINDEX, (int) task_fn_ref); luaL_unref(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
lua_pushinteger(L, prio); lua_pushinteger(L, prio);
luaN_call (L, 1, 0, 1); luaL_pcallx(L, 1, 0);
} }
/* /*
** Schedule a Lua function for task execution ** Schedule a Lua function for task execution
*/ */
#include "lstate.h" /*DEBUG*/ #include "lstate.h" /*DEBUG*/
LUA_API int luaN_posttask( lua_State* L, int prio ) { // [-1, +0, -] LUALIB_API int luaL_posttask( lua_State* L, int prio ) { // [-1, +0, -]
if (!task_handle) if (!task_handle)
task_handle = platform_task_get_id(do_task); task_handle = platform_task_get_id(do_task);
if (!lua_isanyfunction(L, -1) || prio < LUA_TASK_LOW|| prio > LUA_TASK_HIGH) if (!lua_isfunction(L, -1) || prio < LUA_TASK_LOW|| prio > LUA_TASK_HIGH)
luaL_error(L, "invalid posk task"); luaL_error(L, "invalid posk task");
//void *cl = clvalue(L->top-1); //void *cl = clvalue(L->top-1);
int task_fn_ref = luaL_ref(L, LUA_REGISTRYINDEX); int task_fn_ref = luaL_ref(L, LUA_REGISTRYINDEX);
...@@ -110,3 +108,29 @@ LUA_API int luaN_posttask( lua_State* L, int prio ) { // [-1, +0, -] ...@@ -110,3 +108,29 @@ LUA_API int luaN_posttask( lua_State* L, int prio ) { // [-1, +0, -]
return task_fn_ref; return task_fn_ref;
} }
LUA_API void lua_createrotable (lua_State *L, ROTable *t, const ROTable_entry *e, ROTable *mt) {
int i, j;
lu_byte flags = ~0;
const char *plast = (char *)"_";
for (i = 0; e[i].key; i++) {
if (e[i].key[0] == '_' && strcmp(e[i].key,plast)) {
plast = e[i].key;
lua_pushstring(L,e[i].key);
for (j=0; j<TM_EQ; j++){
if(rawtsvalue(L->top-1)==G(L)->tmname[i]) {
flags |= cast_byte(1u<<i);
break;
}
}
lua_pop(L,1);
}
}
t->next = (GCObject *)1;
t->tt = LUA_TROTABLE;
t->marked = LROT_MARKED;
t->flags = flags;
t->lsizenode = i;
t->metatable = cast(Table *, mt);
t->entry = cast(ROTable_entry *, e);
}
/* Read-only tables for Lua */
#ifndef lnodemcu_h
#define lnodemcu_h
#include "lua.h"
#include "lobject.h"
#include "llimits.h"
#include "ltm.h"
#ifdef LUA_USE_HOST
#define LRO_STRKEY(k) k
#define LOCK_IN_SECTION(s)
#else
#define LRO_STRKEY(k) ((STORE_ATTR char *) k)
#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".lua_" #s)))
#endif
/* Macros one can use to define rotable entries */
#define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION}
#define LRO_LUDATA(v) {{.p = cast(void*,v)}, LUA_TLIGHTUSERDATA}
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
#define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
#define LRO_INTVAL(v) LRO_NUMVAL(v)
#define LRO_FLOATVAL(v) LRO_NUMVAL(v)
#define LRO_ROVAL(v) {{.gc = cast(GCObject *, &(v ## _ROTable))}, LUA_TROTABLE}
#define LROT_MARKED 0 //<<<<<<<<<<*** TBD *** >>>>>>>>>>>
#define LROT_FUNCENTRY(n,f) {LRO_STRKEY(#n), LRO_FUNCVAL(f)},
#define LROT_LUDENTRY(n,x) {LRO_STRKEY(#n), LRO_LUDATA(x)},
#define LROT_NUMENTRY(n,x) {LRO_STRKEY(#n), LRO_NUMVAL(x)},
#define LROT_INTENTRY(n,x) LROT_NUMENTRY(n,x)
#define LROT_FLOATENTRY(n,x) LROT_NUMENTRY(n,x)
#define LROT_TABENTRY(n,t) {LRO_STRKEY(#n), LRO_ROVAL(t)},
#define LROT_TABLE(rt) const ROTable rt ## _ROTable
#define LROT_ENTRYREF(rt) (rt ##_entries)
#define LROT_TABLEREF(rt) (&rt ##_ROTable)
#define LROT_BEGIN(rt,mt,f) LROT_TABLE(rt); \
static const ROTable_entry rt ## _entries[] = {
#define LROT_ENTRIES_IN_SECTION(rt,s) \
static const ROTable_entry LOCK_IN_SECTION(s) rt ## _entries[] = {
#define LROT_END(rt,mt,f) {NULL, LRO_NILVAL} }; \
const ROTable rt ## _ROTable = { \
(GCObject *)1, LUA_TROTABLE, LROT_MARKED, \
cast(lu_byte, ~(f)), (sizeof(rt ## _entries)/sizeof(ROTable_entry)) - 1, \
cast(Table *, mt), cast(ROTable_entry *, rt ## _entries) };
#define LROT_BREAK(rt) };
#define LROT_MASK(m) cast(lu_byte, 1<<TM_ ## m)
/*
* These are statically coded can be any combination of the fast index tags
* listed in ltm.h: EQ, GC, INDEX, LEN, MODE, NEWINDEX or combined by anding
* GC+INDEX is the only common combination used, hence the combinaton macro
*/
#define LROT_MASK_EQ LROT_MASK(EQ)
#define LROT_MASK_GC LROT_MASK(GC)
#define LROT_MASK_INDEX LROT_MASK(INDEX)
#define LROT_MASK_LEN LROT_MASK(LEN)
#define LROT_MASK_MODE LROT_MASK(MODE)
#define LROT_MASK_NEWINDEX LROT_MASK(NEWINDEX)
#define LROT_MASK_GC_INDEX (LROT_MASK_GC | LROT_MASK_INDEX)
/* Maximum length of a rotable name and of a string key*/
#endif
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#define loadlib_c #define loadlib_c
#define LUA_LIB #define LUA_LIB
#define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include <stdlib.h> #include <stdlib.h>
...@@ -24,7 +23,7 @@ ...@@ -24,7 +23,7 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lrotable.h" #include "lnodemcu.h"
/* prefix for open functions in C libraries */ /* prefix for open functions in C libraries */
#define LUA_POF "luaopen_" #define LUA_POF "luaopen_"
...@@ -394,11 +393,7 @@ static int loader_Lua (lua_State *L) { ...@@ -394,11 +393,7 @@ static int loader_Lua (lua_State *L) {
const char *name = luaL_checkstring(L, 1); const char *name = luaL_checkstring(L, 1);
filename = findfile(L, name, "path"); filename = findfile(L, name, "path");
if (filename == NULL) return 1; /* library not found in this path */ if (filename == NULL) return 1; /* library not found in this path */
#ifdef LUA_CROSS_COMPILER
if (luaL_loadfile(L, filename) != 0)
#else
if (luaL_loadfile(L, filename) != 0) if (luaL_loadfile(L, filename) != 0)
#endif
loaderror(L, filename); loaderror(L, filename);
return 1; /* library loaded successfully */ return 1; /* library loaded successfully */
} }
...@@ -657,9 +652,9 @@ static const luaL_Reg ll_funcs[] = { ...@@ -657,9 +652,9 @@ static const luaL_Reg ll_funcs[] = {
static const lua_CFunction loaders[] = static const lua_CFunction loaders[] =
{loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
LROT_PUBLIC_BEGIN(lmt) LROT_BEGIN(lmt, NULL, LROT_MASK_GC)
LROT_FUNCENTRY(__gc,gctm) LROT_FUNCENTRY( __gc, gctm )
LROT_END(lmt,lmt, LROT_MASK_GC) LROT_END(lmt, NULL, LROT_MASK_GC)
LUALIB_API int luaopen_package (lua_State *L) { LUALIB_API int luaopen_package (lua_State *L) {
int i; int i;
......
/* /*
** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ ** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $
** Some generic functions over Lua objects ** Some generic functions over Lua objects
...@@ -7,7 +8,6 @@ ...@@ -7,7 +8,6 @@
#define lobject_c #define lobject_c
#define LUA_CORE #define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include <stdio.h> #include <stdio.h>
...@@ -88,7 +88,7 @@ int luaO_rawequalObj (const TValue *t1, const TValue *t2) { ...@@ -88,7 +88,7 @@ int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
case LUA_TLIGHTUSERDATA: case LUA_TLIGHTUSERDATA:
return pvalue(t1) == pvalue(t2); return pvalue(t1) == pvalue(t2);
case LUA_TROTABLE: case LUA_TROTABLE:
return rvalue(t1) == rvalue(t2); return hvalue(t1) == hvalue(t2);
case LUA_TLIGHTFUNCTION: case LUA_TLIGHTFUNCTION:
return fvalue(t1) == fvalue(t2); return fvalue(t1) == fvalue(t2);
default: default:
......
...@@ -28,15 +28,18 @@ ...@@ -28,15 +28,18 @@
#define LUA_TUPVAL (LAST_TAG+2) #define LUA_TUPVAL (LAST_TAG+2)
#define LUA_TDEADKEY (LAST_TAG+3) #define LUA_TDEADKEY (LAST_TAG+3)
#ifdef __XTENSA__ #ifdef LUA_USE_ESP
/* /*
** force aligned access to critical fields in Flash-based structures ** force aligned access to critical fields in Flash-based structures
** wo is the offset of aligned word in bytes 0,4,8,.. ** wo is the offset of aligned word in bytes 0,4,8,..
** bo is the field within the word in bits 0..31 ** bo is the field within the word in bits 0..31
**
** Note that this returns a lu_int32 as returning a byte can cause the
** gcc code generator to emit an extra extui instruction.
*/ */
#define GET_BYTE_FN(name,t,wo,bo) \ #define GET_BYTE_FN(name,t,wo,bo) \
static inline lu_byte get ## name(void *o) { \ static inline lu_int32 get ## name(void *o) { \
lu_byte res; /* extract named field */ \ lu_int32 res; /* extract named field */ \
asm ("l32i %0, %1, " #wo "; extui %0, %0, " #bo ", 8;" : "=r"(res) : "r"(o) : );\ asm ("l32i %0, %1, " #wo "; extui %0, %0, " #bo ", 8;" : "=r"(res) : "r"(o) : );\
return res; } return res; }
#else #else
...@@ -91,43 +94,47 @@ typedef union { ...@@ -91,43 +94,47 @@ typedef union {
#define TValuefields Value value; int tt #define TValuefields Value value; int tt
#define LUA_TVALUE_NIL {NULL}, LUA_TNIL #define LUA_TVALUE_NIL {NULL}, LUA_TNIL
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER) #ifdef LUA_USE_ESP
#pragma pack(4) # pragma pack(4)
#endif #endif
typedef struct lua_TValue { typedef struct lua_TValue {
TValuefields; TValuefields;
} TValue; } TValue;
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
#pragma pack() #ifdef LUA_USE_ESP
# pragma pack()
#endif #endif
/* Macros to test type */ /* Macros to test type */
#define ttisnil(o) (ttype(o) == LUA_TNIL) #define ttisnil(o) (ttype(o) == LUA_TNIL)
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) #define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
#define ttisstring(o) (ttype(o) == LUA_TSTRING) #define ttisstring(o) (ttype(o) == LUA_TSTRING)
#define ttistable(o) (ttype(o) == LUA_TTABLE) #define ttistable(o) (basettype(o) == LUA_TTABLE)
#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) #define ttisrwtable(o) (type(o) == LUA_TTABLE)
#define ttisrotable(o) (ttype(o) & LUA_TISROTABLE)
#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) #define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) #define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
#define ttisthread(o) (ttype(o) == LUA_TTHREAD) #define ttisthread(o) (ttype(o) == LUA_TTHREAD)
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) #define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
#define ttisrotable(o) (ttype(o) == LUA_TROTABLE)
#define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION) #define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION)
#define ttisanyfunction(o) (ttisfunction(o) || ttislightfunction(o)) #define ttisclfunction(o) (ttype(o) == LUA_TFUNCTION)
#define ttisfunction(o) (basettype(o) == LUA_TFUNCTION)
/* Macros to access values */ /* Macros to access values */
#define ttype(o) ((void) (o)->value, (o)->tt) #define ttype(o) ((void) (o)->value, (o)->tt)
#define basettype(o) ((void) (o)->value, ((o)->tt & LUA_TMASK))
#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
#define rvalue(o) check_exp(ttisrotable(o), (o)->value.p)
#define fvalue(o) check_exp(ttislightfunction(o), (o)->value.p) #define fvalue(o) check_exp(ttislightfunction(o), (o)->value.p)
#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) #define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) #define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
#define tsvalue(o) (&rawtsvalue(o)->tsv) #define tsvalue(o) (&rawtsvalue(o)->tsv)
#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) #define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
#define uvalue(o) (&rawuvalue(o)->uv) #define uvalue(o) (&rawuvalue(o)->uv)
#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) #define clvalue(o) check_exp(ttisclfunction(o), &(o)->value.gc->cl)
#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) #define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) #define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) #define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
...@@ -154,9 +161,6 @@ typedef struct lua_TValue { ...@@ -154,9 +161,6 @@ typedef struct lua_TValue {
#define setpvalue(obj,x) \ #define setpvalue(obj,x) \
{ void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TLIGHTUSERDATA; } { void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TLIGHTUSERDATA; }
#define setrvalue(obj,x) \
{ void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TROTABLE; }
#define setfvalue(obj,x) \ #define setfvalue(obj,x) \
{ void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TLIGHTFUNCTION; } { void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TLIGHTFUNCTION; }
...@@ -190,7 +194,7 @@ typedef struct lua_TValue { ...@@ -190,7 +194,7 @@ typedef struct lua_TValue {
#define sethvalue(L,obj,x) \ #define sethvalue(L,obj,x) \
{ GCObject *i_x = cast(GCObject *, (x)); \ { GCObject *i_x = cast(GCObject *, (x)); \
TValue *i_o=(obj); \ TValue *i_o=(obj); \
i_o->value.gc=i_x; i_o->tt=LUA_TTABLE; \ i_o->value.gc=i_x; i_o->tt=gettt(x); \
checkliveness(G(L),i_o); } checkliveness(G(L),i_o); }
#define setptvalue(L,obj,x) \ #define setptvalue(L,obj,x) \
...@@ -225,7 +229,7 @@ typedef struct lua_TValue { ...@@ -225,7 +229,7 @@ typedef struct lua_TValue {
#define setttype(obj, stt) ((void) (obj)->value, (obj)->tt = (stt)) #define setttype(obj, stt) ((void) (obj)->value, (obj)->tt = (stt))
#define iscollectable(o) (ttype(o) >= LUA_TSTRING) #define iscollectable(o) (ttype(o) >= LUA_TSTRING && ttype(o) <= LUA_TMASK)
typedef TValue *StkId; /* index to stack elements */ typedef TValue *StkId; /* index to stack elements */
...@@ -243,19 +247,10 @@ typedef union TString { ...@@ -243,19 +247,10 @@ typedef union TString {
} tsv; } tsv;
} TString; } TString;
#ifdef LUA_CROSS_COMPILER #define getstr(ts) cast(const char *, (ts) + 1)
#define isreadonly(o) (0)
#else
#define isreadonly(o) ((o).marked & READONLYMASK)
#endif
#define ts_isreadonly(ts) isreadonly((ts)->tsv)
#define getstr(ts) (ts_isreadonly(ts) ? \
cast(const char *, *(const char**)((ts) + 1)) : \
cast(const char *, (ts) + 1))
#define svalue(o) getstr(rawtsvalue(o)) #define svalue(o) getstr(rawtsvalue(o))
typedef union Udata { typedef union Udata {
L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
struct { struct {
...@@ -266,7 +261,12 @@ typedef union Udata { ...@@ -266,7 +261,12 @@ typedef union Udata {
} uv; } uv;
} Udata; } Udata;
#ifdef LUA_CROSS_COMPILER
#define isreadonly(o) (0)
#else
#define isreadonly(o) (getmarked(o) & READONLYMASK)
#endif
#define islfs(o) (getmarked(o) & LFSMASK)
/* /*
...@@ -301,7 +301,6 @@ typedef struct Proto { ...@@ -301,7 +301,6 @@ typedef struct Proto {
lu_byte is_vararg; lu_byte is_vararg;
lu_byte maxstacksize; lu_byte maxstacksize;
} Proto; } Proto;
#define proto_isreadonly(p) isreadonly(*(p))
/* masks for new-style vararg */ /* masks for new-style vararg */
...@@ -371,6 +370,18 @@ typedef union Closure { ...@@ -371,6 +370,18 @@ typedef union Closure {
** Tables ** Tables
*/ */
/*
** Common Table fields for both table versions (like CommonHeader in
** macro form, to be included in table structure definitions).
**
** Note that the sethvalue() macro works much like the setsvalue()
** macro and handles the abstracted type. the hvalue(o) macro can be
** used to access CommonTable fields and rw Table fields
*/
#define CommonTable CommonHeader; \
lu_byte flags; lu_byte lsizenode; struct Table *metatable;
typedef union TKey { typedef union TKey {
struct { struct {
TValuefields; TValuefields;
...@@ -388,10 +399,7 @@ typedef struct Node { ...@@ -388,10 +399,7 @@ typedef struct Node {
typedef struct Table { typedef struct Table {
CommonHeader; CommonTable;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of `node' array */
struct Table *metatable;
TValue *array; /* array part */ TValue *array; /* array part */
Node *node; Node *node;
Node *lastfree; /* any free position is before this position */ Node *lastfree; /* any free position is before this position */
...@@ -399,7 +407,23 @@ typedef struct Table { ...@@ -399,7 +407,23 @@ typedef struct Table {
int sizearray; /* size of `array' array */ int sizearray; /* size of `array' array */
} Table; } Table;
typedef const struct luaR_entry ROTable; GET_BYTE_FN(flags,Table,4,16)
GET_BYTE_FN(lsizenode,Table,4,24)
typedef struct ROTable_entry {
const char *key;
const TValue value;
} ROTable_entry;
typedef struct ROTable {
/* next always has the value (GCObject *)((size_t) 1); */
/* flags & 1<<p means tagmethod(p) is not present */
/* lsizenode is unused */
/* Like TStrings, the ROTable_entry vector follows the ROTable */
CommonTable;
ROTable_entry *entry;
} ROTable;
/* /*
** `module' operation for hashing (size is always a power of 2) ** `module' operation for hashing (size is always a power of 2)
......
...@@ -6,9 +6,7 @@ ...@@ -6,9 +6,7 @@
#define lopcodes_c #define lopcodes_c
#define LUA_CORE #define LUA_CORE
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include "lopcodes.h" #include "lopcodes.h"
/* ORDER OP */ /* ORDER OP */
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#define lparser_c #define lparser_c
#define LUA_CORE #define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h" #include "lua.h"
#include <string.h> #include <string.h>
......
/* Read-only tables helper */
#ifndef lrodefs_h
#define lrodefs_h
#include "lrotable.h"
#undef LUA_REG_TYPE
#undef LSTRKEY
#undef LNILKEY
#undef LNUMKEY
#undef LFUNCVAL
#undef LNUMVAL
#undef LROVAL
#undef LNILVAL
#undef LREGISTER
#if LUA_OPTIMIZE_MEMORY >=1
#define LUA_REG_TYPE luaR_entry
#define LSTRKEY LRO_STRKEY
#define LNUMKEY LRO_NUMKEY
#define LNILKEY LRO_NILKEY
#define LFUNCVAL LRO_FUNCVAL
#define LUDATA LRO_LUDATA
#define LNUMVAL LRO_NUMVAL
#define LROVAL LRO_ROVAL
#define LNILVAL LRO_NILVAL
#define LREGISTER(L, name, table) return 0
#else
#define LUA_REG_TYPE luaL_reg
#define LSTRKEY(x) x
#define LNILKEY NULL
#define LFUNCVAL(x) x
#define LNILVAL NULL
#define LREGISTER(L, name, table)\
luaL_register(L, name, table);\
return 1
#endif
#define LROT_TABLE(t) static const LUA_REG_TYPE t ## _map[];
#define LROT_TABLEREF(t) ((void *) t ## _map)
#define LROT_BEGIN(t) static const LUA_REG_TYPE t ## _map [] = {
#define LROT_PUBLIC_BEGIN(t) const LUA_REG_TYPE t ## _map[] = {
#define LROT_EXTERN(t) extern const LUA_REG_TYPE t ## _map[]
#define LROT_TABENTRY(n,t) {LRO_STRKEY(#n), LRO_ROVAL(t ## _map)},
#define LROT_FUNCENTRY(n,f) {LRO_STRKEY(#n), LRO_FUNCVAL(f)},
#define LROT_NUMENTRY(n,x) {LRO_STRKEY(#n), LRO_NUMVAL(x)},
#define LROT_LUDENTRY(n,x) {LRO_STRKEY(#n), LRO_LUDATA((void *) x)},
#define LROT_END(t,mt, f) {LRO_NILKEY, LRO_NILVAL} };
#define LREGISTER(L, name, table) return 0
#endif /* lrodefs_h */
/* Read-only tables for Lua */
#define LUAC_CROSS_FILE
#include "lua.h"
#include <string.h>
#include "lrotable.h"
#include "lauxlib.h"
#include "lstring.h"
#include "lobject.h"
#include "lapi.h"
#ifdef _MSC_VER
#define ALIGNED_STRING (__declspec( align( 4 ) ) char*)
#else
#define ALIGNED_STRING (__attribute__((aligned(4))) char *)
#endif
#define LA_LINES 32
#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) (unsigned)((((519*(size_t)(a)))>>4) + ((b) ? (b)->tsv.hash: 0))
typedef struct {
unsigned hash;
unsigned addr:24;
unsigned ndx:8;
} cache_line_t;
static cache_line_t 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++) {
cache_line_t cl = cache[i][j];
if (cl.hash == hash && ((size_t)rotable & 0xffffffu) == cl.addr) {
COUNT(0);
return cl.ndx;
}
}
COUNT(1);
return -1;
}
static void update_cache(unsigned hash, ROTable *rotable, unsigned ndx) {
int i = (hash)>>2 & (LA_LINES-1), j;
#ifndef _MSC_VER
cache_line_t cl = {hash, (size_t) rotable, ndx};
#else
cache_line_t cl; // MSC doesn't allow non-scalar initialisers, which
cl.hash = hash; // is a pity because xtensa gcc generates optimum
cl.addr = (size_t) rotable; // code using them.
cl.ndx = ndx;
#endif
COUNT(2);
if (ndx>0xffu)
return;
for (j = LA_SLOTS-1; j>0; j--)
cache[i][j] = cache[i][j-1];
cache[i][0] = cl;
}
/*
* 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" ;
unsigned hash = HASH(rotable, key);
unsigned i = 0;
int j = lookup_cache(hash, rotable);
unsigned l = key ? key->tsv.len : sizeof("__metatable")-1;
if (pentry) {
if (j >= 0 && !strcmp(pentry[j].key, strkey)) {
if (ppos)
*ppos = j;
//dbg_printf("%3d hit %p %s\n", (hash>>2) & (LA_LINES-1), rotable, strkey);
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, mask4 = l > 2 ? (~0u) : (~0u)>>((3-l)*8);
memcpy(&name4, strkey, sizeof(name4));
for(;pentry->key != NULL; i++, pentry++) {
if (((*(unsigned *)pentry->key ^ name4) & mask4) == 0 &&
!strcmp(pentry->key, strkey)) {
//dbg_printf("%p %s hit after %d probes \n", rotable, strkey, (int)(rotable-pentry));
if (ppos)
*ppos = i;
update_cache(hash, rotable, pentry - rotable);
//dbg_printf("%3d %3d %p %s\n", (hash>>2) & (LA_LINES-1), (int)(pentry-rotable), rotable, strkey);
return &pentry->value;
}
}
}
//dbg_printf("%p %s miss after %d probes \n", rotable, strkey, (int)(rotable-pentry));
return luaO_nilobject;
}
/* Find the metatable of a given table */
void* luaR_getmeta(ROTable *rotable) {
const TValue *res = luaR_findentry(rotable, NULL, NULL);
return res && ttisrotable(res) ? rvalue(res) : NULL;
}
static void luaR_next_helper(lua_State *L, ROTable *pentries, int pos,
TValue *key, TValue *val) {
if (pentries[pos].key) {
/* Found an entry */
setsvalue(L, key, luaS_new(L, pentries[pos].key));
setobj2s(L, val, &pentries[pos].value);
} else {
setnilvalue(key);
setnilvalue(val);
}
}
/* next (used for iteration) */
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, rotable, 0, key, val);
else if (ttisstring(key)) {
/* Find the previous key again */
if (ttisstring(key)) {
luaR_findentry(rotable, rawtsvalue(key), &keypos);
}
/* Advance to next key */
keypos ++;
luaR_next_helper(L, rotable, keypos, key, val);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment