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 @@
#define ldo_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <string.h>
......@@ -254,13 +253,13 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
return base;
}
static StkId tryfuncTM (lua_State *L, StkId func) {
const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
StkId p;
ptrdiff_t funcr = savestack(L, func);
if (!ttisfunction(tm))
if (!ttisfunction(tm)) {
luaG_typeerror(L, func, "call");
}
/* Open a hole inside the stack at `func' */
for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
incr_top(L);
......@@ -279,10 +278,10 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
int luaD_precall (lua_State *L, StkId func, int nresults) {
ptrdiff_t funcr;
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 */
funcr = savestack(L, func);
if (ttisfunction(func))
if (!ttislightfunction(func))
cl = &clvalue(func)->l;
L->ci->savedpc = L->savedpc;
if (cl && !cl->isC) { /* Lua function? prepare its call */
......@@ -332,10 +331,10 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1);
lua_unlock(L);
if (ttisfunction(ci->func))
n = (*curr_func(L)->c.f)(L); /* do the actual call */
else
if (ttislightfunction(ci->func))
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);
if (n < 0) /* yielding? */
return PCRYIELD;
......
......@@ -6,7 +6,6 @@
#define ldump_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.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 @@
#define lflash_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lobject.h"
......@@ -89,9 +88,8 @@ void dumpStrt(stringtable *tb, const char *type) {
for (i=0; i<tb->size; i++)
for(o = tb->hash[i], j=0; o; (o=o->gch.next), j++ ) {
TString *ts =cast(TString *, o);
NODE_DBG("%5d %5d %08x %08x %5d %1s %s\n",
i, j, (size_t) ts, ts->tsv.hash, ts->tsv.len,
ts_isreadonly(ts) ? "R" : " ", getstr(ts));
NODE_DBG("%5d %5d %08x %08x %5d %s\n",
i, j, (size_t) ts, ts->tsv.hash, ts->tsv.len, getstr(ts));
}
}
......@@ -200,7 +198,6 @@ static void procFirstPass (void);
* Library function called by node.flashreload(filename).
*/
LUALIB_API int luaN_reload_reboot (lua_State *L) {
// luaL_dbgbreak();
const char *fn = lua_tostring(L, 1), *msg = "";
int status;
......
......@@ -6,7 +6,6 @@
#define lfunc_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <string.h>
......@@ -146,7 +145,6 @@ void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray(L, f->k, f->sizek, TValue);
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
if (!proto_isreadonly(f)) {
luaM_freearray(L, f->code, f->sizecode, Instruction);
#ifdef LUA_OPTIMIZE_DEBUG
if (f->packedlineinfo) {
......@@ -155,7 +153,6 @@ void luaF_freeproto (lua_State *L, Proto *f) {
#else
luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
#endif
}
luaM_free(L, f);
}
......
......@@ -6,7 +6,6 @@
#define lgc_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <string.h>
......@@ -21,7 +20,6 @@
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lrotable.h"
#define GCSTEPSIZE 1024u
#define GCSWEEPMAX 40
......@@ -54,7 +52,6 @@
#define markobject(g,t) { if (iswhite(obj2gco(t))) \
reallymarkobject(g, obj2gco(t)); }
#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
......@@ -81,7 +78,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
case LUA_TUSERDATA: {
Table *mt = gco2u(o)->metatable;
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);
return;
}
......@@ -159,7 +156,6 @@ size_t luaC_separateudata (lua_State *L, int all) {
return deadmem;
}
static int traversetable (global_State *g, Table *h) {
int i;
int weakkey = 0;
......@@ -167,7 +163,7 @@ static int traversetable (global_State *g, Table *h) {
const TValue *mode = luaO_nilobject;
if (h->metatable) {
if (!luaR_isrotable(h->metatable))
if (isrwtable(h->metatable))
markobject(g, h->metatable);
mode = gfasttm(g, h->metatable, TM_MODE);
}
......@@ -330,13 +326,11 @@ static l_mem propagatemark (global_State *g) {
sizeof(TValue) * p->sizek +
sizeof(LocVar) * p->sizelocvars +
sizeof(TString *) * p->sizeupvalues +
(proto_isreadonly(p) ? 0 : sizeof(Instruction) * p->sizecode +
sizeof(Instruction) * p->sizecode +
#ifdef LUA_OPTIMIZE_DEBUG
(p->packedlineinfo ?
strlen(cast(char *, p->packedlineinfo))+1 :
0));
(p->packedlineinfo ? strlen(cast(char *, p->packedlineinfo))+1 : 0);
#else
sizeof(int) * p->sizelineinfo);
sizeof(int) * p->sizelineinfo;
#endif
}
default: lua_assert(0); return 0;
......@@ -522,7 +516,7 @@ void luaC_freeall (lua_State *L) {
static void markmt (global_State *g) {
int 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) {
global_State *g = G(L);
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
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? */
if (g->gcstate == GCSpropagate)
reallymarkobject(g, v); /* Restore invariant */
......
......@@ -7,109 +7,106 @@
#define linit_c
#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 "lualib.h"
#include "lauxlib.h"
#include "luaconf.h"
#include "module.h"
#include "lstate.h"
#include "lnodemcu.h"
LROT_EXTERN(strlib);
LROT_EXTERN(tab_funcs);
LROT_EXTERN(dblib);
LROT_EXTERN(co_funcs);
LROT_EXTERN(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.
*/
extern LROT_TABLE(strlib);
extern LROT_TABLE(tab_funcs);
extern LROT_TABLE(dblib);
extern LROT_TABLE(co_funcs);
extern LROT_TABLE(math);
#ifdef _MSC_VER
//MSVC requires us to declare these sections before we refer to them
#pragma section(__ROSECNAME(A), read)
#pragma section(__ROSECNAME(zzzzzzzz), read)
#pragma section(__ROSECNAME(libs), read)
#pragma section(__ROSECNAME(rotable), read)
//These help us to find the beginning and ending of the RO data. NOTE: linker
//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
#define LROT_ROM_ENTRIES \
LROT_TABENTRY( string, strlib ) \
LROT_TABENTRY( table, tab_funcs ) \
LROT_TABENTRY( debug, dblib) \
LROT_TABENTRY( coroutine, co_funcs ) \
LROT_TABENTRY( math, math ) \
LROT_TABENTRY( ROM, rotables )
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)
LROT_TABENTRY( string, strlib )
LROT_TABENTRY( table, tab_funcs )
LROT_TABENTRY( debug, dblib)
LROT_TABENTRY( coroutine, co_funcs )
LROT_TABENTRY( math, math )
LROT_TABENTRY( ROM, lua_rotables )
#ifdef LUA_CROSS_COMPILER
#if defined(LUA_CROSS_COMPILER)
extern LROT_TABLE(base_func);
LROT_BEGIN(rotables_meta, NULL, LROT_MASK_INDEX)
LROT_TABENTRY( _index, base_func)
LROT_END(rotables_meta, NULL, LROT_MASK_INDEX)
extern LROT_TABLE(oslib);
extern LROT_TABLE(iolib);
LROT_BEGIN(rotables, LROT_TABLEREF(rotables_meta), 0)
LROT_ROM_ENTRIES
LROT_TABENTRY( os, oslib )
LROT_TABENTRY( io, iolib )
LROT_END(lua_rotables, NULL, 0)
#else
LROT_BREAK(lua_rotables)
#endif
LROT_END(rotables, LROT_TABLEREF(rotables_meta), 0)
LROT_PUBLIC_BEGIN(LOCK_IN_SECTION(libs) lua_libs)
LROT_FUNCENTRY( _, luaopen_base )
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_BEGIN(lua_libs, NULL, 0)
LROT_LIB_ENTRIES
LROT_FUNCENTRY( io, luaopen_io )
LROT_END( lua_libs, NULL, 0)
#endif
LROT_END(lua_libs, NULL, 0)
#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
void luaL_openlibs (lua_State *L) {
lua_pushrotable(L, LROT_TABLEREF(lua_libs));
lua_pushnil(L); /* first key */
/* loop round and open libraries */
#ifndef LUA_CROSS_COMPILER
// luaL_dbgbreak(); // This is a test point for debugging library start ups
void luaL_openlibs (lua_State *L) {
#ifdef LUA_CROSS_COMPILER
const ROTable_entry *p = LROT_TABLEREF(lua_libs)->entry;
#else
const ROTable_entry *p = lua_libs_base;
lua_createrotable(L, LROT_TABLEREF(rotables), lua_rotable_base, NULL);
#endif
while (lua_next(L, -2) != 0) {
if (lua_islightfunction(L,-1) &&
fvalue(L->top-1)) { // only process function entries
lua_pushvalue(L, -2);
while (p->key) {
if (ttislightfunction(&p->value) && fvalue(&p->value)) {
lua_pushcfunction(L, fvalue(&p->value));
lua_pushstring(L, p->key);
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 @@
#define llex_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <ctype.h>
......
......@@ -7,7 +7,6 @@
#define lmathlib_c
#define LUA_LIB
#define LUAC_CROSS_FILE
#include "lua.h"
#include <stdlib.h>
......@@ -15,7 +14,7 @@
#include "lauxlib.h"
#include "lualib.h"
#include "lrotable.h"
#include "lnodemcu.h"
#undef PI
#define PI (3.14159265358979323846)
......@@ -309,7 +308,7 @@ static int math_randomseed (lua_State *L) {
return 0;
}
LROT_PUBLIC_BEGIN(math)
LROT_BEGIN(math, NULL, 0)
#ifdef LUA_NUMBER_INTEGRAL
LROT_FUNCENTRY( abs, math_abs )
LROT_FUNCENTRY( ceil, math_identity )
......
......@@ -7,7 +7,6 @@
#define lmem_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
......
......@@ -18,10 +18,9 @@
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lrotable.h"
#include "lnodemcu.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
** 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) {
** Catch all error handler for CB calls. This uses debug.traceback() to
** generate a full Lua traceback.
*/
int luaN_traceback (lua_State *L) {
LUALIB_API int luaL_traceback (lua_State *L) {
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_pushinteger(L, 2); /* skip this function and traceback */
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 */
luaN_posttask(L, LUA_TASK_HIGH);
luaL_posttask(L, LUA_TASK_HIGH);
}
return 0;
}
......@@ -56,18 +57,15 @@ int luaN_traceback (lua_State *L) {
** an error handler which will catch any error and then post this to the
** 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 base = lua_gettop(L) - narg;
lua_pushcfunction(L, luaN_traceback);
lua_pushcfunction(L, luaL_traceback);
lua_insert(L, base); /* put under args */
status = lua_pcall(L, narg, (nres < 0 ? LUA_MULTRET : nres), base);
lua_remove(L, base); /* remove traceback function */
if (status && nres >=0)
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;
}
......@@ -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 */
//dbg_printf("calling Reg[%u]\n", 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);
lua_pushinteger(L, prio);
luaN_call (L, 1, 0, 1);
luaL_pcallx(L, 1, 0);
}
/*
** Schedule a Lua function for task execution
*/
#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)
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");
//void *cl = clvalue(L->top-1);
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, -]
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 @@
#define loadlib_c
#define LUA_LIB
#define LUAC_CROSS_FILE
#include "lua.h"
#include <stdlib.h>
......@@ -24,7 +23,7 @@
#include "lauxlib.h"
#include "lualib.h"
#include "lrotable.h"
#include "lnodemcu.h"
/* prefix for open functions in C libraries */
#define LUA_POF "luaopen_"
......@@ -394,11 +393,7 @@ static int loader_Lua (lua_State *L) {
const char *name = luaL_checkstring(L, 1);
filename = findfile(L, name, "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)
#endif
loaderror(L, filename);
return 1; /* library loaded successfully */
}
......@@ -657,9 +652,9 @@ static const luaL_Reg ll_funcs[] = {
static const lua_CFunction loaders[] =
{loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
LROT_PUBLIC_BEGIN(lmt)
LROT_FUNCENTRY(__gc,gctm)
LROT_END(lmt,lmt, LROT_MASK_GC)
LROT_BEGIN(lmt, NULL, LROT_MASK_GC)
LROT_FUNCENTRY( __gc, gctm )
LROT_END(lmt, NULL, LROT_MASK_GC)
LUALIB_API int luaopen_package (lua_State *L) {
int i;
......
/*
** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $
** Some generic functions over Lua objects
......@@ -7,7 +8,6 @@
#define lobject_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <stdio.h>
......@@ -88,7 +88,7 @@ int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
case LUA_TLIGHTUSERDATA:
return pvalue(t1) == pvalue(t2);
case LUA_TROTABLE:
return rvalue(t1) == rvalue(t2);
return hvalue(t1) == hvalue(t2);
case LUA_TLIGHTFUNCTION:
return fvalue(t1) == fvalue(t2);
default:
......
......@@ -28,15 +28,18 @@
#define LUA_TUPVAL (LAST_TAG+2)
#define LUA_TDEADKEY (LAST_TAG+3)
#ifdef __XTENSA__
#ifdef LUA_USE_ESP
/*
** force aligned access to critical fields in Flash-based structures
** wo is the offset of aligned word in bytes 0,4,8,..
** 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) \
static inline lu_byte get ## name(void *o) { \
lu_byte res; /* extract named field */ \
static inline lu_int32 get ## name(void *o) { \
lu_int32 res; /* extract named field */ \
asm ("l32i %0, %1, " #wo "; extui %0, %0, " #bo ", 8;" : "=r"(res) : "r"(o) : );\
return res; }
#else
......@@ -91,43 +94,47 @@ typedef union {
#define TValuefields Value value; int tt
#define LUA_TVALUE_NIL {NULL}, LUA_TNIL
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
#pragma pack(4)
#ifdef LUA_USE_ESP
# pragma pack(4)
#endif
typedef struct lua_TValue {
TValuefields;
} TValue;
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
#pragma pack()
#ifdef LUA_USE_ESP
# pragma pack()
#endif
/* Macros to test type */
#define ttisnil(o) (ttype(o) == LUA_TNIL)
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
#define ttisstring(o) (ttype(o) == LUA_TSTRING)
#define ttistable(o) (ttype(o) == LUA_TTABLE)
#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
#define ttistable(o) (basettype(o) == LUA_TTABLE)
#define ttisrwtable(o) (type(o) == LUA_TTABLE)
#define ttisrotable(o) (ttype(o) & LUA_TISROTABLE)
#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
#define ttisrotable(o) (ttype(o) == LUA_TROTABLE)
#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 */
#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 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 nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
#define tsvalue(o) (&rawtsvalue(o)->tsv)
#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
#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 bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
......@@ -154,9 +161,6 @@ typedef struct lua_TValue {
#define setpvalue(obj,x) \
{ 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) \
{ 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 {
#define sethvalue(L,obj,x) \
{ GCObject *i_x = cast(GCObject *, (x)); \
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); }
#define setptvalue(L,obj,x) \
......@@ -225,7 +229,7 @@ typedef struct lua_TValue {
#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 */
......@@ -243,19 +247,10 @@ typedef union TString {
} tsv;
} TString;
#ifdef LUA_CROSS_COMPILER
#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 getstr(ts) cast(const char *, (ts) + 1)
#define svalue(o) getstr(rawtsvalue(o))
typedef union Udata {
L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
struct {
......@@ -266,7 +261,12 @@ typedef union Udata {
} uv;
} 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 {
lu_byte is_vararg;
lu_byte maxstacksize;
} Proto;
#define proto_isreadonly(p) isreadonly(*(p))
/* masks for new-style vararg */
......@@ -371,6 +370,18 @@ typedef union Closure {
** 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 {
struct {
TValuefields;
......@@ -388,10 +399,7 @@ typedef struct Node {
typedef struct Table {
CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of `node' array */
struct Table *metatable;
CommonTable;
TValue *array; /* array part */
Node *node;
Node *lastfree; /* any free position is before this position */
......@@ -399,7 +407,23 @@ typedef struct Table {
int sizearray; /* size of `array' array */
} 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)
......
......@@ -6,9 +6,7 @@
#define lopcodes_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include "lopcodes.h"
/* ORDER OP */
......
......@@ -7,7 +7,6 @@
#define lparser_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.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