Unverified Commit 27a83feb authored by Terry Ellison's avatar Terry Ellison Committed by GitHub
Browse files

Merge pull request #2301 from TerryE/dev-LFS

LFS evaluation version -- second release
parents 2cc195d5 a3c2f48f
...@@ -15,55 +15,6 @@ ...@@ -15,55 +15,6 @@
#include "c_stdlib.h" #include "c_stdlib.h"
#include "c_types.h" #include "c_types.h"
#include "c_string.h" #include "c_string.h"
// const char *lua_init_value = "print(\"Hello world\")";
const char *lua_init_value = "@init.lua";
// int c_abs(int x){
// return x>0?x:0-x;
// }
// void c_exit(int e){
// }
const char *c_getenv(const char *__string)
{
if (c_strcmp(__string, "LUA_INIT") == 0)
{
return lua_init_value;
}
return NULL;
}
// make sure there is enough memory before real malloc, otherwise malloc will panic and reset
// void *c_malloc(size_t __size){
// if(__size>system_get_free_heap_size()){
// NODE_ERR("malloc: not enough memory\n");
// return NULL;
// }
// return (void *)os_malloc(__size);
// }
// void *c_zalloc(size_t __size){
// if(__size>system_get_free_heap_size()){
// NODE_ERR("zalloc: not enough memory\n");
// return NULL;
// }
// return (void *)os_zalloc(__size);
// }
// void c_free(void *p){
// // NODE_ERR("free1: %d\n", system_get_free_heap_size());
// os_free(p);
// // NODE_ERR("-free1: %d\n", system_get_free_heap_size());
// }c_stdlib.s
// int c_rand(void){
// }
// void c_srand(unsigned int __seed){
// }
// int c_atoi(const char *__nptr){
// }
#include <_ansi.h> #include <_ansi.h>
//#include <reent.h> //#include <reent.h>
//#include "mprec.h" //#include "mprec.h"
......
...@@ -46,8 +46,7 @@ ...@@ -46,8 +46,7 @@
// void c_exit(int); // void c_exit(int);
// c_getenv() get env "LUA_INIT" string for lua initialization. //const char *c_getenv(const char *__string);
const char *c_getenv(const char *__string);
// void *c_malloc(size_t __size); // void *c_malloc(size_t __size);
// void *c_zalloc(size_t __size); // void *c_zalloc(size_t __size);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
# a generated lib/image xxx.a () # a generated lib/image xxx.a ()
# #
ifndef PDIR ifndef PDIR
SUBDIRS = luac_cross
GEN_LIBS = liblua.a GEN_LIBS = liblua.a
endif endif
...@@ -24,7 +25,8 @@ STD_CFLAGS=-std=gnu11 -Wimplicit ...@@ -24,7 +25,8 @@ STD_CFLAGS=-std=gnu11 -Wimplicit
# makefile at its root level - these are then overridden # makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein # for a subtree within the makefile rooted therein
# #
#DEFINES += #DEFINES += -DDEVELOPMENT_TOOLS -DDEVELOPMENT_USE_GDB -DDEVELOPMENT_BREAK_ON_STARTUP_PIN=1
#EXTRA_CCFLAGS += -ggdb -O0
############################################################# #############################################################
# Recursion Magic - Don't touch this!! # Recursion Magic - Don't touch this!!
......
...@@ -414,7 +414,7 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) { ...@@ -414,7 +414,7 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) {
case LUA_TROTABLE: case LUA_TROTABLE:
return rvalue(o); return rvalue(o);
case LUA_TLIGHTFUNCTION: case LUA_TLIGHTFUNCTION:
return pvalue(o); return fvalue(o);
default: return NULL; default: return NULL;
} }
} }
...@@ -459,15 +459,6 @@ LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { ...@@ -459,15 +459,6 @@ LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
} }
LUA_API void lua_pushrolstring (lua_State *L, const char *s, size_t len) {
lua_lock(L);
luaC_checkGC(L);
setsvalue2s(L, L->top, luaS_newrolstr(L, s, len));
api_incr_top(L);
lua_unlock(L);
}
LUA_API void lua_pushstring (lua_State *L, const char *s) { LUA_API void lua_pushstring (lua_State *L, const char *s) {
if (s == NULL) if (s == NULL)
lua_pushnil(L); lua_pushnil(L);
......
...@@ -45,6 +45,149 @@ ...@@ -45,6 +45,149 @@
#define LUA_USECCLOSURES 0 #define LUA_USECCLOSURES 0
#define LUA_USELIGHTFUNCTIONS 1 #define LUA_USELIGHTFUNCTIONS 1
//#define DEBUG_ALLOCATOR
#ifdef DEBUG_ALLOCATOR
#ifdef LUA_CROSS_COMPILER
static void break_hook(void) {}
#define ASSERT(s) if (!(s)) {break_hook();}
#else
#define ASSERT(s) if (!(s)) {asm ("break 0,0" ::);}
#endif
/*
** {======================================================================
** Diagnosticd version for realloc. This is enabled only if the
** DEBUG_ALLOCATOR is defined. It is a cutdown version of the allocator
** used in the Lua Test Suite -- a compromise between the ability catch
** most alloc/free errors and overruns and working within the RAM limits
** of the ESP8266 architecture. ONLY FOR HEAVY HACKERS
** =======================================================================
*/
#define this_realloc debug_realloc
#define MARK 0x55 /* 01010101 (a nice pattern) */
#define MARKSIZE 2*sizeof(size_t) /* size of marks after each block */
#define fillmem(mem,size) memset(mem, ~MARK, size)
typedef union MemHeader MemHeader;
union MemHeader {
L_Umaxalign a; /* ensures maximum alignment for Header */
struct {
size_t size;
MemHeader *next;
size_t mark[2];
};
};
typedef struct Memcontrol { /* memory-allocator control variables */
MemHeader *start;
lu_int32 numblocks;
lu_int32 total;
lu_int32 maxmem;
lu_int32 memlimit;
} Memcontrol;
static Memcontrol mc = {NULL,0,0,0,32768*64};
static size_t marker[2] = {0,0};
static void scanBlocks (void) {
MemHeader *p = mc.start;
int i;
char s,e;
for (i=0; p ;i++) {
s = memcmp(p->mark, marker, MARKSIZE) ? '<' : ' ';
e = memcmp(cast(char *, p+1) + p->size, marker, MARKSIZE) ? '>' : ' ';
c_printf("%4u %p %8lu %c %c\n", i, p, p->size, s, e);
ASSERT(p->next);
p = p->next;
}
}
static int checkBlocks (void) {
MemHeader *p = mc.start;
while(p) {
if (memcmp(p->mark, marker, MARKSIZE) ||
memcmp(cast(char *, p+1) + p->size, marker, MARKSIZE)) {
scanBlocks();
return 0;
}
p = p->next;
}
return 1;
}
static void freeblock (MemHeader *block) {
if (block) {
MemHeader *p = mc.start;
MemHeader *next = block->next;
size_t size = block->size;
ASSERT(checkBlocks());
if (p == block) {
mc.start = next;
} else {
while (p->next != block) {
ASSERT(p);
p = p->next;
}
p->next = next;
}
fillmem(block, sizeof(MemHeader) + size + MARKSIZE); /* erase block */
c_free(block); /* actually free block */
mc.numblocks--; /* update counts */
mc.total -= size;
}
}
void *debug_realloc (void *b, size_t oldsize, size_t size) {
MemHeader *block = cast(MemHeader *, b);
ASSERT(checkBlocks());
if (!marker[0]) memset(marker, MARK, MARKSIZE);
if (block == NULL) {
oldsize = 0;
} else {
block--; /* go to real header */
ASSERT(!memcmp(block->mark, marker, MARKSIZE))
ASSERT(oldsize == block->size);
ASSERT(!memcmp(cast(char *, b)+oldsize, marker, MARKSIZE));
}
if (size == 0) {
freeblock(block);
return NULL;
} else if (size > oldsize && mc.total+size-oldsize > mc.memlimit)
return NULL; /* fake a memory allocation error */
else {
MemHeader *newblock;
size_t commonsize = (oldsize < size) ? oldsize : size;
size_t realsize = sizeof(MemHeader) + size + MARKSIZE;
newblock = cast(MemHeader *, c_malloc(realsize)); /* alloc a new block */
if (newblock == NULL)
return NULL; /* really out of memory? */
if (block) {
memcpy(newblock + 1, block + 1, commonsize); /* copy old contents */
freeblock(block); /* erase (and check) old copy */
}
/* initialize new part of the block with something weird */
if (size > commonsize)
fillmem(cast(char *, newblock + 1) + commonsize, size - commonsize);
/* initialize marks after block */
memset(newblock->mark, MARK, MARKSIZE);
newblock->size = size;
newblock->next = mc.start;
mc.start = newblock;
memset(cast(char *, newblock + 1)+ size, MARK, MARKSIZE);
mc.total += size;
if (mc.total > mc.maxmem)
mc.maxmem = mc.total;
mc.numblocks++;
return (newblock + 1);
}
}
/* }====================================================================== */
#else
#define this_realloc(p,os,s) c_realloc(p,s)
#endif /* DEBUG_ALLOCATOR */
/* /*
** {====================================================== ** {======================================================
** Error-report functions ** Error-report functions
...@@ -633,7 +776,8 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { ...@@ -633,7 +776,8 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
lf.f = c_freopen(filename, "rb", lf.f); /* reopen in binary mode */ lf.f = c_freopen(filename, "rb", lf.f); /* reopen in binary mode */
if (lf.f == NULL) return errfile(L, "reopen", fnameindex); if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
/* skip eventual `#!...' */ /* skip eventual `#!...' */
while ((c = c_getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; while ((c = c_getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) {}
lf.extraline = 0; lf.extraline = 0;
} }
c_ungetc(c, lf.f); c_ungetc(c, lf.f);
...@@ -787,8 +931,12 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { ...@@ -787,8 +931,12 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
void *nptr; void *nptr;
if (nsize == 0) { if (nsize == 0) {
#ifdef DEBUG_ALLOCATOR
return (void *)this_realloc(ptr, osize, nsize);
#else
c_free(ptr); c_free(ptr);
return NULL; return NULL;
#endif
} }
if (L != NULL && (mode & EGC_ALWAYS)) /* always collect memory if requested */ if (L != NULL && (mode & EGC_ALWAYS)) /* always collect memory if requested */
luaC_fullgc(L); luaC_fullgc(L);
...@@ -804,17 +952,44 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { ...@@ -804,17 +952,44 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
if(G(L)->memlimit > 0 && (mode & EGC_ON_MEM_LIMIT) && l_check_memlimit(L, nsize - osize)) if(G(L)->memlimit > 0 && (mode & EGC_ON_MEM_LIMIT) && l_check_memlimit(L, nsize - osize))
return NULL; return NULL;
} }
nptr = (void *)c_realloc(ptr, nsize); nptr = (void *)this_realloc(ptr, osize, nsize);
if (nptr == NULL && L != NULL && (mode & EGC_ON_ALLOC_FAILURE)) { if (nptr == NULL && L != NULL && (mode & EGC_ON_ALLOC_FAILURE)) {
luaC_fullgc(L); /* emergency full collection. */ luaC_fullgc(L); /* emergency full collection. */
nptr = (void *)c_realloc(ptr, nsize); /* try allocation again */ nptr = (void *)this_realloc(ptr, osize, nsize); /* try allocation again */
} }
return nptr; return nptr;
} }
LUALIB_API void luaL_assertfail(const char *file, int line, const char *message) { LUALIB_API void luaL_assertfail(const char *file, int line, const char *message) {
dbg_printf("ASSERT@%s(%d): %s\n", file, line, message); dbg_printf("ASSERT@%s(%d): %s\n", file, line, message);
#if defined(LUA_CROSS_COMPILER)
exit(1);
#endif
}
#ifdef DEVELOPMENT_USE_GDB
/*
* This is a simple stub used by lua_assert() if DEVELOPMENT_USE_GDB is defined.
* Instead of crashing out with an assert error, this hook starts the GDB remote
* stub if not already running and then issues a break. The rationale here is
* that when testing the developer migght be using screen/PuTTY to work ineractively
* with the Lua Interpreter via UART0. However if an assert triggers, then there
* is the option to exit the interactive session and start the Xtensa remote GDB
* which will then sync up with the remote GDB client to allow forensics of the error.
*/
extern void gdbstub_init(void);
LUALIB_API void luaL_dbgbreak(void) {
static int repeat_entry = 0;
if (repeat_entry == 0) {
dbg_printf("Start up the gdb stub if not already started\n");
gdbstub_init();
repeat_entry = 1;
}
asm("break 0,0" ::);
} }
#endif
static int panic (lua_State *L) { static int panic (lua_State *L) {
(void)L; /* to avoid warnings */ (void)L; /* to avoid warnings */
......
...@@ -712,10 +712,5 @@ static void base_open (lua_State *L) { ...@@ -712,10 +712,5 @@ static void base_open (lua_State *L) {
LUALIB_API int luaopen_base (lua_State *L) { LUALIB_API int luaopen_base (lua_State *L) {
base_open(L); base_open(L);
#if LUA_OPTIMIZE_MEMORY == 0
luaL_register(L, LUA_COLIBNAME, co_funcs);
return 2;
#else
return 1; return 1;
#endif
} }
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lrotable.h" #include "lrotable.h"
#include "lstring.h"
#include "lflash.h"
#include "user_modules.h" #include "user_modules.h"
...@@ -26,6 +28,39 @@ static int db_getregistry (lua_State *L) { ...@@ -26,6 +28,39 @@ static int db_getregistry (lua_State *L) {
return 1; return 1;
} }
static int db_getstrings (lua_State *L) {
size_t i,n;
stringtable *tb;
GCObject *o;
#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER)
const char *opt = lua_tolstring (L, 1, &n);
if (n==3 && memcmp(opt, "ROM", 4) == 0) {
if (G(L)->ROstrt.hash == NULL)
return 0;
tb = &G(L)->ROstrt;
}
else
#endif
tb = &G(L)->strt;
lua_settop(L, 0);
lua_createtable(L, tb->nuse, 0); /* create table the same size as the strt */
for (i=0, n=1; i<tb->size; i++) {
for(o = tb->hash[i]; o; o=o->gch.next) {
TString *ts =cast(TString *, o);
lua_pushnil(L);
setsvalue2s(L, L->top-1, ts);
lua_rawseti(L, -2, n++); /* enumerate the strt, adding elements */
}
}
lua_getfield(L, LUA_GLOBALSINDEX, "table");
lua_getfield(L, -1, "sort"); /* look up table.sort function */
lua_replace(L, -2); /* dump the table table */
lua_pushvalue(L, -2); /* duplicate the strt_copy ref */
lua_call(L, 1, 0); /* table.sort(strt_copy) */
return 1;
}
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL #ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
static int db_getmetatable (lua_State *L) { static int db_getmetatable (lua_State *L) {
...@@ -395,6 +430,7 @@ const LUA_REG_TYPE dblib[] = { ...@@ -395,6 +430,7 @@ const LUA_REG_TYPE dblib[] = {
{LSTRKEY("getlocal"), LFUNCVAL(db_getlocal)}, {LSTRKEY("getlocal"), LFUNCVAL(db_getlocal)},
#endif #endif
{LSTRKEY("getregistry"), LFUNCVAL(db_getregistry)}, {LSTRKEY("getregistry"), LFUNCVAL(db_getregistry)},
{LSTRKEY("getstrings"), LFUNCVAL(db_getstrings)},
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL #ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
{LSTRKEY("getmetatable"), LFUNCVAL(db_getmetatable)}, {LSTRKEY("getmetatable"), LFUNCVAL(db_getmetatable)},
{LSTRKEY("getupvalue"), LFUNCVAL(db_getupvalue)}, {LSTRKEY("getupvalue"), LFUNCVAL(db_getupvalue)},
......
/*
** $Id: lflash.c
** See Copyright Notice in lua.h
*/
#define lflash_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#ifdef LUA_FLASH_STORE
#include "lobject.h"
#include "lauxlib.h"
#include "lstate.h"
#include "lfunc.h"
#include "lflash.h"
#include "platform.h"
#include "vfs.h"
#include "c_fcntl.h"
#include "c_stdio.h"
#include "c_stdlib.h"
#include "c_string.h"
/*
* Flash memory is a fixed memory addressable block that is serially allocated by the
* luac build process and the out image can be downloaded into SPIFSS and loaded into
* flash with a node.flash.load() command. See luac_cross/lflashimg.c for the build
* process.
*/
static char *flashAddr;
static uint32_t flashAddrPhys;
static uint32_t flashSector;
static uint32_t curOffset;
#define ALIGN(s) (((s)+sizeof(size_t)-1) & ((size_t) (- (signed) sizeof(size_t))))
#define ALIGN_BITS(s) (((uint32_t)s) & (sizeof(size_t)-1))
#define ALL_SET cast(uint32_t, -1)
#define FLASH_SIZE LUA_FLASH_STORE
#define FLASH_PAGE_SIZE INTERNAL_FLASH_SECTOR_SIZE
#define FLASH_PAGES (FLASH_SIZE/FLASH_PAGE_SIZE)
char flash_region_base[FLASH_SIZE] ICACHE_FLASH_RESERVED_ATTR;
#ifdef NODE_DEBUG
extern void dbg_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
void dumpStrt(stringtable *tb, const char *type) {
int i,j;
GCObject *o;
NODE_DBG("\nDumping %s String table\n\n========================\n", type);
NODE_DBG("No of elements: %d\nSize of table: %d\n", tb->nuse, tb->size);
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));
}
}
LUA_API void dumpStrings(lua_State *L) {
dumpStrt(&G(L)->strt, "RAM");
if (G(L)->ROstrt.hash)
dumpStrt(&G(L)->ROstrt, "ROM");
}
#endif
/* =====================================================================================
* The next 4 functions: flashPosition, flashSetPosition, flashBlock and flashErase
* wrap writing to flash. The last two are platform dependent. Also note that any
* writes are suppressed if the global writeToFlash is false. This is used in
* phase I where the pass is used to size the structures in flash.
*/
static char *flashPosition(void){
return flashAddr + curOffset;
}
static char *flashSetPosition(uint32_t offset){
NODE_DBG("flashSetPosition(%04x)\n", offset);
curOffset = offset;
return flashPosition();
}
static char *flashBlock(const void* b, size_t size) {
void *cur = flashPosition();
NODE_DBG("flashBlock((%04x),%08x,%04x)\n", curOffset,b,size);
lua_assert(ALIGN_BITS(b) == 0 && ALIGN_BITS(size) == 0);
platform_flash_write(b, flashAddrPhys+curOffset, size);
curOffset += size;
return cur;
}
static void flashErase(uint32_t start, uint32_t end){
int i;
if (start == -1) start = FLASH_PAGES - 1;
if (end == -1) end = FLASH_PAGES - 1;
NODE_DBG("flashErase(%04x,%04x)\n", flashSector+start, flashSector+end);
for (i = start; i<=end; i++)
platform_flash_erase_sector( flashSector + i );
}
/*
* Hook in lstate.c:f_luaopen() to set up ROstrt and ROpvmain if needed
*/
LUAI_FUNC void luaN_init (lua_State *L) {
// luaL_dbgbreak();
curOffset = 0;
flashAddr = flash_region_base;
flashAddrPhys = platform_flash_mapped2phys((uint32_t)flashAddr);
flashSector = platform_flash_get_sector_of_address(flashAddrPhys);
FlashHeader *fh = cast(FlashHeader *, flashAddr);
/*
* For the LFS to be valid, its signature has to be correct for this build variant,
* thr ROhash and main proto fields must be defined and the main proto address
* be within the LFS address bounds. (This last check is primarily to detect the
* direct imaging of an absolute LFS with the wrong base address.
*/
if ((fh->flash_sig & (~FLASH_SIG_ABSOLUTE)) != FLASH_SIG ) {
NODE_ERR("Flash sig not correct: %p vs %p\n",
fh->flash_sig & (~FLASH_SIG_ABSOLUTE), FLASH_SIG);
return;
}
if (fh->pROhash == ALL_SET ||
((fh->mainProto - cast(FlashAddr, fh)) >= fh->flash_size)) {
NODE_ERR("Flash size check failed: %p vs 0xFFFFFFFF; %p >= %p\n",
fh->mainProto - cast(FlashAddr, fh), fh->flash_size);
return;
}
G(L)->ROstrt.hash = cast(GCObject **, fh->pROhash);
G(L)->ROstrt.nuse = fh->nROuse ;
G(L)->ROstrt.size = fh->nROsize;
G(L)->ROpvmain = cast(Proto *,fh->mainProto);
}
#define BYTE_OFFSET(t,f) cast(size_t, &(cast(t *, NULL)->f))
/*
* Rehook address chain to correct Flash byte addressed within the mapped adress space
* Note that on input each 32-bit address field is split into 2×16-bit subfields
* - the lu_int16 offset of the target address being referenced
* - the lu_int16 offset of the next address pointer.
*/
static int rebuild_core (int fd, uint32_t size, lu_int32 *buf, int is_absolute) {
int bi; /* byte offset into memory mapped LFS of current buffer */
int wNextOffset = BYTE_OFFSET(FlashHeader,mainProto)/sizeof(lu_int32);
int wj; /* word offset into current input buffer */
for (bi = 0; bi < size; bi += FLASH_PAGE_SIZE) {
int wi = bi / sizeof(lu_int32);
int blen = ((bi + FLASH_PAGE_SIZE) < size) ? FLASH_PAGE_SIZE : size - bi;
int wlen = blen / sizeof(lu_int32);
if (vfs_read(fd, buf , blen) != blen)
return 0;
if (!is_absolute) {
for (wj = 0; wj < wlen; wj++) {
if ((wi + wj) == wNextOffset) { /* this word is the next linked address */
int wTargetOffset = buf[wj]&0xFFFF;
wNextOffset = buf[wj]>>16;
lua_assert(!wNextOffset || (wNextOffset>(wi+wj) && wNextOffset<size/sizeof(lu_int32)));
buf[wj] = cast(lu_int32, flashAddr + wTargetOffset*sizeof(lu_int32));
}
}
}
flashBlock(buf, blen);
}
return size;
}
/*
* Library function called by node.flash.load(filename).
*/
LUALIB_API int luaN_reload_reboot (lua_State *L) {
int fd, status, is_absolute;
FlashHeader fh;
const char *fn = lua_tostring(L, 1);
if (!fn || !(fd = vfs_open(fn, "r")))
return 0;
if (vfs_read(fd, &fh, sizeof(fh)) != sizeof(fh) ||
(fh.flash_sig & (~FLASH_SIG_ABSOLUTE)) != FLASH_SIG)
return 0;
if (vfs_lseek(fd, -1, VFS_SEEK_END) != fh.flash_size-1 ||
vfs_lseek(fd, 0, VFS_SEEK_SET) != 0)
return 0;
is_absolute = fh.flash_sig & FLASH_SIG_ABSOLUTE;
lu_int32 *buffer = luaM_newvector(L, FLASH_PAGE_SIZE / sizeof(lu_int32), lu_int32);
/*
* This is the point of no return. We attempt to rebuild the flash. If there
* are any problems them the Flash is going to be corrupt, so the only fallback
* is to erase it and reboot with a clean but blank flash. Otherwise the reboot
* will load the new LFS.
*
* Note that the Lua state is not passed into the lua core because from this
* point on, we make no calls on the Lua RTS.
*/
flashErase(0,-1);
if (rebuild_core(fd, fh.flash_size, buffer, is_absolute) != fh.flash_size)
flashErase(0,-1);
/*
* Issue a break 0,0. This will either enter the debugger or force a restart if
* not installed. Follow this by a H/W timeout is a robust way to insure that
* other interrupts / callbacks don't fire and reference THE old LFS context.
*/
asm("break 0,0" ::);
while (1) {}
return 0;
}
/*
* In the arg is a valid LFS module name then return the LClosure pointing to it.
* Otherwise return:
* - The Unix time that the LFS was built
* - The base address and length of the LFS
* - An array of the module names in the the LFS
*/
LUAI_FUNC int luaN_index (lua_State *L) {
int i;
int n = lua_gettop(L);
/* Return nil + the LFS base address if the LFS isn't loaded */
if(!(G(L)->ROpvmain)) {
lua_settop(L, 0);
lua_pushnil(L);
lua_pushinteger(L, (lua_Integer) flashAddr);
lua_pushinteger(L, flashAddrPhys);
return 3;
}
/* Push the LClosure of the LFS index function */
Closure *cl = luaF_newLclosure(L, 0, hvalue(gt(L)));
cl->l.p = G(L)->ROpvmain;
lua_settop(L, n+1);
setclvalue(L, L->top-1, cl);
/* Move it infront of the arguments and call the index function */
lua_insert(L, 1);
lua_call(L, n, LUA_MULTRET);
/* Return it if the response if a single value (the function) */
if (lua_gettop(L) == 1)
return 1;
lua_assert(lua_gettop(L) == 2);
/* Otherwise add the base address of the LFS, and its size bewteen the */
/* Unix time and the module list, then return all 4 params. */
lua_pushinteger(L, (lua_Integer) flashAddr);
lua_insert(L, 2);
lua_pushinteger(L, flashAddrPhys);
lua_insert(L, 3);
lua_pushinteger(L, cast(FlashHeader *, flashAddr)->flash_size);
lua_insert(L, 4);
return 5;
}
#endif
/*
** lflashe.h
** See Copyright Notice in lua.h
*/
#if defined(LUA_FLASH_STORE) && !defined(lflash_h)
#define lflash_h
#include "lobject.h"
#include "lstate.h"
#include "lzio.h"
#ifdef LUA_NUMBER_INTEGRAL
# define FLASH_SIG_B1 0x02
#else
# define FLASH_SIG_B1 0x00
#endif
#ifdef LUA_PACK_TVALUES
#ifdef LUA_NUMBER_INTEGRAL
#error "LUA_PACK_TVALUES is only valid for Floating point builds"
#endif
# define FLASH_SIG_B2 0x04
#else
# define FLASH_SIG_B2 0x00
#endif
#define FLASH_SIG_ABSOLUTE 0x01
#define FLASH_SIG_IN_PROGRESS 0x08
#define FLASH_SIG (0xfafaaf50 | FLASH_SIG_B2 | FLASH_SIG_B1)
typedef lu_int32 FlashAddr;
typedef struct {
lu_int32 flash_sig; /* a stabdard fingerprint identifying an LFS image */
lu_int32 flash_size; /* Size of LFS image */
FlashAddr mainProto; /* address of main Proto in Proto hierarchy */
FlashAddr pROhash; /* address of ROstrt hash */
lu_int32 nROuse; /* number of elements in ROstrt */
int nROsize; /* size of ROstrt */
lu_int32 fill1; /* reserved */
lu_int32 fill2; /* reserved */
} FlashHeader;
LUAI_FUNC void luaN_init (lua_State *L);
LUAI_FUNC int luaN_flashSetup (lua_State *L);
LUAI_FUNC int luaN_reload_reboot (lua_State *L);
LUAI_FUNC int luaN_index (lua_State *L);
#endif
...@@ -146,7 +146,7 @@ void luaF_freeproto (lua_State *L, Proto *f) { ...@@ -146,7 +146,7 @@ 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_is_readonly(f)) { 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) {
......
...@@ -18,9 +18,6 @@ ...@@ -18,9 +18,6 @@
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ #define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
cast(int, sizeof(TValue *)*((n)-1))) cast(int, sizeof(TValue *)*((n)-1)))
#define proto_readonly(p) l_setbit((p)->marked, READONLYBIT)
#define proto_is_readonly(p) testbit((p)->marked, READONLYBIT)
LUAI_FUNC Proto *luaF_newproto (lua_State *L); LUAI_FUNC Proto *luaF_newproto (lua_State *L);
LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#define GCSWEEPCOST 10 #define GCSWEEPCOST 10
#define GCFINALIZECOST 100 #define GCFINALIZECOST 100
#if READONLYMASK != (1<<READONLYBIT) || (defined(LUA_FLASH_STORE) && LFSMASK != (1<<LFSBIT))
#error "lgc.h and object.h out of sync on READONLYMASK / LFSMASK"
#endif
#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) #define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
...@@ -37,7 +40,7 @@ ...@@ -37,7 +40,7 @@
#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) #define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) #define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) #define stringmark(s) if (!isLFSobject(&(s)->tsv)) {reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT);}
#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) #define isfinalized(u) testbit((u)->marked, FINALIZEDBIT)
...@@ -61,12 +64,18 @@ ...@@ -61,12 +64,18 @@
static void removeentry (Node *n) { static void removeentry (Node *n) {
lua_assert(ttisnil(gval(n))); lua_assert(ttisnil(gval(n)));
if (iscollectable(gkey(n))) if (ttype(gkey(n)) != LUA_TDEADKEY && iscollectable(gkey(n)))
// The gkey is always in RAM so it can be marked as DEAD even though it
// refers to an LFS object.
setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */
} }
static void reallymarkobject (global_State *g, GCObject *o) { static void reallymarkobject (global_State *g, GCObject *o) {
/* don't mark LFS Protos (or strings) */
if (o->gch.tt == LUA_TPROTO && isLFSobject(&(o->gch)))
return;
lua_assert(iswhite(o) && !isdead(g, o)); lua_assert(iswhite(o) && !isdead(g, o));
white2gray(o); white2gray(o);
switch (o->gch.tt) { switch (o->gch.tt) {
...@@ -180,6 +189,8 @@ static int traversetable (global_State *g, Table *h) { ...@@ -180,6 +189,8 @@ static int traversetable (global_State *g, Table *h) {
while (i--) while (i--)
markvalue(g, &h->array[i]); markvalue(g, &h->array[i]);
} }
if (luaH_isdummy (h->node))
return weakkey || weakvalue;
i = sizenode(h); i = sizenode(h);
while (i--) { while (i--) {
Node *n = gnode(h, i); Node *n = gnode(h, i);
...@@ -202,6 +213,8 @@ static int traversetable (global_State *g, Table *h) { ...@@ -202,6 +213,8 @@ static int traversetable (global_State *g, Table *h) {
*/ */
static void traverseproto (global_State *g, Proto *f) { static void traverseproto (global_State *g, Proto *f) {
int i; int i;
if (isLFSobject(f))
return; /* don't traverse Protos in LFS */
if (f->source) stringmark(f->source); if (f->source) stringmark(f->source);
for (i=0; i<f->sizek; i++) /* mark literals */ for (i=0; i<f->sizek; i++) /* mark literals */
markvalue(g, &f->k[i]); markvalue(g, &f->k[i]);
...@@ -317,7 +330,7 @@ static l_mem propagatemark (global_State *g) { ...@@ -317,7 +330,7 @@ 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_is_readonly(p) ? 0 : sizeof(Instruction) * p->sizecode + (proto_isreadonly(p) ? 0 : sizeof(Instruction) * p->sizecode +
#ifdef LUA_OPTIMIZE_DEBUG #ifdef LUA_OPTIMIZE_DEBUG
(p->packedlineinfo ? (p->packedlineinfo ?
c_strlen(cast(char *, p->packedlineinfo))+1 : c_strlen(cast(char *, p->packedlineinfo))+1 :
...@@ -388,7 +401,10 @@ static void cleartable (GCObject *l) { ...@@ -388,7 +401,10 @@ static void cleartable (GCObject *l) {
static void freeobj (lua_State *L, GCObject *o) { static void freeobj (lua_State *L, GCObject *o) {
switch (o->gch.tt) { switch (o->gch.tt) {
case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; case LUA_TPROTO:
lua_assert(!isLFSobject(&(o->gch)));
luaF_freeproto(L, gco2p(o));
break;
case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
case LUA_TTABLE: luaH_free(L, gco2h(o)); break; case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
...@@ -398,6 +414,7 @@ static void freeobj (lua_State *L, GCObject *o) { ...@@ -398,6 +414,7 @@ static void freeobj (lua_State *L, GCObject *o) {
break; break;
} }
case LUA_TSTRING: { case LUA_TSTRING: {
lua_assert(!isLFSobject(&(o->gch)));
G(L)->strt.nuse--; G(L)->strt.nuse--;
luaM_freemem(L, o, sizestring(gco2ts(o))); luaM_freemem(L, o, sizestring(gco2ts(o)));
break; break;
...@@ -420,6 +437,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { ...@@ -420,6 +437,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
global_State *g = G(L); global_State *g = G(L);
int deadmask = otherwhite(g); int deadmask = otherwhite(g);
while ((curr = *p) != NULL && count-- > 0) { while ((curr = *p) != NULL && count-- > 0) {
lua_assert(!isLFSobject(&(curr->gch)) || curr->gch.tt == LUA_TTHREAD);
if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */
sweepwholelist(L, &gco2th(curr)->openupval); sweepwholelist(L, &gco2th(curr)->openupval);
if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */
...@@ -538,7 +556,7 @@ static void atomic (lua_State *L) { ...@@ -538,7 +556,7 @@ static void atomic (lua_State *L) {
size_t udsize; /* total size of userdata to be finalized */ size_t udsize; /* total size of userdata to be finalized */
/* remark occasional upvalues of (maybe) dead threads */ /* remark occasional upvalues of (maybe) dead threads */
remarkupvals(g); remarkupvals(g);
/* traverse objects cautch by write barrier and by 'remarkupvals' */ /* traverse objects caucht by write barrier and by 'remarkupvals' */
propagateall(g); propagateall(g);
/* remark weak tables */ /* remark weak tables */
g->gray = g->weak; g->gray = g->weak;
...@@ -694,10 +712,10 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { ...@@ -694,10 +712,10 @@ 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(ttype(&o->gch) != LUA_TTABLE); lua_assert(o->gch.tt != 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 */
else /* don't mind */ else /* don't mind */
makewhite(g, o); /* mark as white just to avoid other barriers */ makewhite(g, o); /* mark as white just to avoid other barriers */
} }
......
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
#define VALUEWEAKBIT 4 #define VALUEWEAKBIT 4
#define FIXEDBIT 5 #define FIXEDBIT 5
#define SFIXEDBIT 6 #define SFIXEDBIT 6
#define LFSBIT 6
#define READONLYBIT 7 #define READONLYBIT 7
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
...@@ -100,6 +101,13 @@ ...@@ -100,6 +101,13 @@
#define isfixedstack(x) testbit((x)->marked, FIXEDSTACKBIT) #define isfixedstack(x) testbit((x)->marked, FIXEDSTACKBIT)
#define fixedstack(x) l_setbit((x)->marked, FIXEDSTACKBIT) #define fixedstack(x) l_setbit((x)->marked, FIXEDSTACKBIT)
#define unfixedstack(x) resetbit((x)->marked, FIXEDSTACKBIT) #define unfixedstack(x) resetbit((x)->marked, FIXEDSTACKBIT)
#ifdef LUA_FLASH_STORE
#define isLFSobject(x) testbit((x)->marked, LFSBIT)
#define stringfix(s) if (!test2bits((s)->tsv.marked, FIXEDBIT, LFSBIT)) {l_setbit((s)->tsv.marked, FIXEDBIT);}
#else
#define isLFSobject(x) (0)
#define stringfix(s) {l_setbit((s)->tsv.marked, FIXEDBIT);}
#endif
#define luaC_checkGC(L) { \ #define luaC_checkGC(L) { \
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
......
/*
** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $
** Initialization of libraries for lua.c
** See Copyright Notice in lua.h
*/
#define linit_c
#define LUA_LIB
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "luaconf.h"
#include "module.h"
#if defined(LUA_CROSS_COMPILER)
BUILTIN_LIB( start_list, NULL, NULL);
BUILTIN_LIB_INIT( start_list, NULL, NULL);
#endif
extern const luaR_entry strlib[], tab_funcs[], dblib[],
co_funcs[], math_map[], syslib[];
BUILTIN_LIB_INIT( BASE, "", luaopen_base);
BUILTIN_LIB_INIT( LOADLIB, LUA_LOADLIBNAME, luaopen_package);
BUILTIN_LIB( STRING, LUA_STRLIBNAME, strlib);
BUILTIN_LIB_INIT( STRING, LUA_STRLIBNAME, luaopen_string);
BUILTIN_LIB( TABLE, LUA_TABLIBNAME, tab_funcs);
BUILTIN_LIB_INIT( TABLE, LUA_TABLIBNAME, luaopen_table);
BUILTIN_LIB( DBG, LUA_DBLIBNAME, dblib);
BUILTIN_LIB_INIT( DBG, LUA_DBLIBNAME, luaopen_debug);
BUILTIN_LIB( CO, LUA_COLIBNAME, co_funcs);
BUILTIN_LIB( MATH, LUA_MATHLIBNAME, math_map);
#if defined(LUA_CROSS_COMPILER)
extern const luaR_entry syslib[], iolib[];
BUILTIN_LIB( OS, LUA_OSLIBNAME, syslib);
BUILTIN_LIB_INIT( IO, LUA_IOLIBNAME, luaopen_io);
BUILTIN_LIB( end_list, NULL, NULL);
BUILTIN_LIB_INIT( end_list, NULL, NULL);
/*
* These base addresses are internal to this module for cross compile builds
* This also exploits feature of the GCC code generator that the variables are
* emitted in either normal OR reverse order within PSECT.
*/
#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 luaR_table lua_rotable_base[];
static const luaL_Reg *lua_libs = lua_libs_base;
const luaR_table *lua_rotable = lua_rotable_base;
#endif
void luaL_openlibs (lua_State *L) {
#if defined(LUA_CROSS_COMPILER)
lua_libs = (isascending(lua_lib) ? &lua_lib_start_list : &lua_lib_end_list) + 1;
lua_rotable = (isascending(lua_rotable) ? &lua_rotable_start_list : &lua_rotable_end_list) + 1;
#endif
const luaL_Reg *lib = lua_libs;
for (; lib->name; lib++) {
if (lib->func)
{
lua_pushcfunction(L, lib->func);
lua_pushstring(L, lib->name);
lua_call(L, 1, 0);
}
}
}
...@@ -326,7 +326,7 @@ const LUA_REG_TYPE math_map[] = { ...@@ -326,7 +326,7 @@ const LUA_REG_TYPE math_map[] = {
{LSTRKEY("randomseed"), LFUNCVAL(math_randomseed)}, {LSTRKEY("randomseed"), LFUNCVAL(math_randomseed)},
{LSTRKEY("sqrt"), LFUNCVAL(math_sqrt)}, {LSTRKEY("sqrt"), LFUNCVAL(math_sqrt)},
#if LUA_OPTIMIZE_MEMORY > 0 #if LUA_OPTIMIZE_MEMORY > 0
{LSTRKEY("huge"), LNUMVAL(LONG_MAX)}, {LSTRKEY("huge"), LNUMVAL(INT_MAX)},
#endif #endif
#else #else
{LSTRKEY("abs"), LFUNCVAL(math_abs)}, {LSTRKEY("abs"), LFUNCVAL(math_abs)},
...@@ -374,7 +374,7 @@ const LUA_REG_TYPE math_map[] = { ...@@ -374,7 +374,7 @@ const LUA_REG_TYPE math_map[] = {
*/ */
#if defined LUA_NUMBER_INTEGRAL #if defined LUA_NUMBER_INTEGRAL
# include "c_limits.h" /* for LONG_MAX */ # include "c_limits.h" /* for INT_MAX */
#endif #endif
LUALIB_API int luaopen_math (lua_State *L) { LUALIB_API int luaopen_math (lua_State *L) {
...@@ -383,7 +383,7 @@ LUALIB_API int luaopen_math (lua_State *L) { ...@@ -383,7 +383,7 @@ LUALIB_API int luaopen_math (lua_State *L) {
#else #else
luaL_register(L, LUA_MATHLIBNAME, math_map); luaL_register(L, LUA_MATHLIBNAME, math_map);
# if defined LUA_NUMBER_INTEGRAL # if defined LUA_NUMBER_INTEGRAL
lua_pushnumber(L, LONG_MAX); lua_pushnumber(L, INT_MAX);
lua_setfield(L, -2, "huge"); lua_setfield(L, -2, "huge");
# else # else
lua_pushnumber(L, PI); lua_pushnumber(L, PI);
......
...@@ -613,7 +613,7 @@ static int ll_seeall (lua_State *L) { ...@@ -613,7 +613,7 @@ static int ll_seeall (lua_State *L) {
static void setpath (lua_State *L, const char *fieldname, const char *envname, static void setpath (lua_State *L, const char *fieldname, const char *envname,
const char *def) { const char *def) {
const char *path = c_getenv(envname); const char *path = NULL; /* getenv(envname) not used in NodeMCU */;
if (path == NULL) /* no environment variable? */ if (path == NULL) /* no environment variable? */
lua_pushstring(L, def); /* use default */ lua_pushstring(L, def); /* use default */
else { else {
......
...@@ -53,7 +53,8 @@ int luaO_fb2int (int x) { ...@@ -53,7 +53,8 @@ int luaO_fb2int (int x) {
int luaO_log2 (unsigned int x) { int luaO_log2 (unsigned int x) {
static const lu_byte log_2[256] ICACHE_STORE_ATTR ICACHE_RODATA_ATTR = { #ifdef LUA_CROSS_COMPILER
static const lu_byte log_2[256] = {
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
...@@ -65,10 +66,12 @@ int luaO_log2 (unsigned int x) { ...@@ -65,10 +66,12 @@ int luaO_log2 (unsigned int x) {
}; };
int l = -1; int l = -1;
while (x >= 256) { l += 8; x >>= 8; } while (x >= 256) { l += 8; x >>= 8; }
#ifdef LUA_CROSS_COMPILER
return l + log_2[x]; return l + log_2[x];
#else #else
return l + byte_of_aligned_array(log_2,x); /* Use Normalization Shift Amount Unsigned: 0x1=>31 up to 0xffffffff =>0
* See Xtensa Instruction Set Architecture (ISA) Refman P 462 */
asm volatile ("nsau %0, %1;" :"=r"(x) : "r"(x));
return 31 - x;
#endif #endif
} }
...@@ -103,7 +106,7 @@ int luaO_str2d (const char *s, lua_Number *result) { ...@@ -103,7 +106,7 @@ int luaO_str2d (const char *s, lua_Number *result) {
#if defined(LUA_CROSS_COMPILER) #if defined(LUA_CROSS_COMPILER)
{ {
long lres = strtoul(s, &endptr, 16); long lres = strtoul(s, &endptr, 16);
#if LONG_MAX != 2147483647L #if INT_MAX != 2147483647L
if (lres & ~0xffffffffL) if (lres & ~0xffffffffL)
*result = cast_num(-1); *result = cast_num(-1);
else if (lres & 0x80000000L) else if (lres & 0x80000000L)
......
...@@ -23,10 +23,10 @@ ...@@ -23,10 +23,10 @@
#define NUM_TAGS (LAST_TAG+1) #define NUM_TAGS (LAST_TAG+1)
/* mask for 'read-only' objects. must match READONLYBIT in lgc.h' */ #define READONLYMASK (1<<7) /* denormalised bitmask for READONLYBIT and */
#define READONLYMASK 128 #ifdef LUA_FLASH_STORE
#define LFSMASK (1<<6) /* LFSBIT to avoid include proliferation */
#endif
/* /*
** Extra tags for non-values ** Extra tags for non-values
*/ */
...@@ -55,86 +55,39 @@ typedef struct GCheader { ...@@ -55,86 +55,39 @@ typedef struct GCheader {
CommonHeader; CommonHeader;
} GCheader; } GCheader;
#if defined(LUA_PACK_VALUE) || defined(ELUA_ENDIAN_BIG) || defined(ELUA_ENDIAN_SMALL)
# error "NodeMCU does not support the eLua LUA_PACK_VALUE and ELUA_ENDIAN defines"
#endif
/* /*
** Union of all Lua values ** Union of all Lua values
*/ */
#if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG )
typedef union {
struct {
int _pad0;
GCObject *gc;
};
struct {
int _pad1;
void *p;
};
lua_Number n;
struct {
int _pad2;
int b;
};
} Value;
#else // #if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG )
typedef union { typedef union {
GCObject *gc; GCObject *gc;
void *p; void *p;
lua_Number n; lua_Number n;
int b; int b;
} Value; } Value;
#endif // #if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG )
/* /*
** Tagged Values ** Tagged Values
*/ */
#ifndef LUA_PACK_VALUE
#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)
#pragma pack(4)
#endif
typedef struct lua_TValue { typedef struct lua_TValue {
TValuefields; TValuefields;
} TValue; } TValue;
#else // #ifndef LUA_PACK_VALUE #if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
#ifdef ELUA_ENDIAN_LITTLE #pragma pack()
#define TValuefields union { \ #endif
struct { \
int _pad0; \
int tt_sig; \
} _ts; \
struct { \
int _pad; \
short tt; \
short sig; \
} _t; \
Value value; \
}
#define LUA_TVALUE_NIL {0, add_sig(LUA_TNIL)}
#else // #ifdef ELUA_ENDIAN_LITTLE
#define TValuefields union { \
struct { \
int tt_sig; \
int _pad0; \
} _ts; \
struct { \
short sig; \
short tt; \
int _pad; \
} _t; \
Value value; \
}
#define LUA_TVALUE_NIL {add_sig(LUA_TNIL), 0}
#endif // #ifdef ELUA_ENDIAN_LITTLE
#define LUA_NOTNUMBER_SIG (-1)
#define add_sig(tt) ( 0xffff0000 | (tt) )
typedef TValuefields TValue;
#endif // #ifndef LUA_PACK_VALUE
/* Macros to test type */ /* Macros to test type */
#ifndef LUA_PACK_VALUE
#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)
...@@ -146,27 +99,11 @@ typedef TValuefields TValue; ...@@ -146,27 +99,11 @@ typedef TValuefields TValue;
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) #define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
#define ttisrotable(o) (ttype(o) == LUA_TROTABLE) #define ttisrotable(o) (ttype(o) == LUA_TROTABLE)
#define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION) #define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION)
#else // #ifndef LUA_PACK_VALUE
#define ttisnil(o) (ttype_sig(o) == add_sig(LUA_TNIL))
#define ttisnumber(o) ((o)->_t.sig != LUA_NOTNUMBER_SIG)
#define ttisstring(o) (ttype_sig(o) == add_sig(LUA_TSTRING))
#define ttistable(o) (ttype_sig(o) == add_sig(LUA_TTABLE))
#define ttisfunction(o) (ttype_sig(o) == add_sig(LUA_TFUNCTION))
#define ttisboolean(o) (ttype_sig(o) == add_sig(LUA_TBOOLEAN))
#define ttisuserdata(o) (ttype_sig(o) == add_sig(LUA_TUSERDATA))
#define ttisthread(o) (ttype_sig(o) == add_sig(LUA_TTHREAD))
#define ttislightuserdata(o) (ttype_sig(o) == add_sig(LUA_TLIGHTUSERDATA))
#define ttisrotable(o) (ttype_sig(o) == add_sig(LUA_TROTABLE))
#define ttislightfunction(o) (ttype_sig(o) == add_sig(LUA_TLIGHTFUNCTION))
#endif // #ifndef LUA_PACK_VALUE
/* Macros to access values */ /* Macros to access values */
#ifndef LUA_PACK_VALUE
#define ttype(o) ((o)->tt) #define ttype(o) ((void) (o)->value, (o)->tt)
#else // #ifndef LUA_PACK_VALUE
#define ttype(o) ((o)->_t.sig == LUA_NOTNUMBER_SIG ? (o)->_t.tt : LUA_TNUMBER)
#define ttype_sig(o) ((o)->_ts.tt_sig)
#endif // #ifndef LUA_PACK_VALUE
#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 rvalue(o) check_exp(ttisrotable(o), (o)->value.p)
...@@ -186,24 +123,15 @@ typedef TValuefields TValue; ...@@ -186,24 +123,15 @@ typedef TValuefields TValue;
/* /*
** for internal debug only ** for internal debug only
*/ */
#ifndef LUA_PACK_VALUE
#define checkconsistency(obj) \ #define checkconsistency(obj) \
lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
#define checkliveness(g,obj) \ #define checkliveness(g,obj) \
lua_assert(!iscollectable(obj) || \ lua_assert(!iscollectable(obj) || \
((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
#else // #ifndef LUA_PACK_VALUE
#define checkconsistency(obj) \
lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch._t.tt))
#define checkliveness(g,obj) \
lua_assert(!iscollectable(obj) || \
((ttype(obj) == (obj)->value.gc->gch._t.tt) && !isdead(g, (obj)->value.gc)))
#endif // #ifndef LUA_PACK_VALUE
/* Macros to set values */ /* Macros to set values */
#ifndef LUA_PACK_VALUE
#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) #define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
#define setnvalue(obj,x) \ #define setnvalue(obj,x) \
...@@ -257,69 +185,10 @@ typedef TValuefields TValue; ...@@ -257,69 +185,10 @@ typedef TValuefields TValue;
i_o->value.gc=i_x; i_o->tt=LUA_TPROTO; \ i_o->value.gc=i_x; i_o->tt=LUA_TPROTO; \
checkliveness(G(L),i_o); } checkliveness(G(L),i_o); }
#define setobj(L,obj1,obj2) \ #define setobj(L,obj1,obj2) \
{ const TValue *o2=(obj2); TValue *o1=(obj1); \ { const TValue *o2=(obj2); TValue *o1=(obj1); \
o1->value = o2->value; o1->tt=o2->tt; \ o1->value = o2->value; o1->tt=o2->tt; \
checkliveness(G(L),o1); } checkliveness(G(L),o1); }
#else // #ifndef LUA_PACK_VALUE
#define setnilvalue(obj) ( ttype_sig(obj) = add_sig(LUA_TNIL) )
#define setnvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.n=(x); }
#define setpvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TLIGHTUSERDATA);}
#define setrvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TROTABLE);}
#define setfvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TLIGHTFUNCTION);}
#define setbvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.b=(x); i_o->_ts.tt_sig=add_sig(LUA_TBOOLEAN);}
#define setsvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TSTRING); \
checkliveness(G(L),i_o); }
#define setuvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TUSERDATA); \
checkliveness(G(L),i_o); }
#define setthvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TTHREAD); \
checkliveness(G(L),i_o); }
#define setclvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TFUNCTION); \
checkliveness(G(L),i_o); }
#define sethvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TTABLE); \
checkliveness(G(L),i_o); }
#define setptvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TPROTO); \
checkliveness(G(L),i_o); }
#define setobj(L,obj1,obj2) \
{ const TValue *o2=(obj2); TValue *o1=(obj1); \
o1->value = o2->value; \
checkliveness(G(L),o1); }
#endif // #ifndef LUA_PACK_VALUE
/* /*
** different types of sets, according to destination ** different types of sets, according to destination
...@@ -340,13 +209,7 @@ typedef TValuefields TValue; ...@@ -340,13 +209,7 @@ typedef TValuefields TValue;
#define setobj2n setobj #define setobj2n setobj
#define setsvalue2n setsvalue #define setsvalue2n setsvalue
#ifndef LUA_PACK_VALUE #define setttype(obj, stt) ((void) (obj)->value, (obj)->tt = (stt))
#define setttype(obj, tt) (ttype(obj) = (tt))
#else // #ifndef LUA_PACK_VALUE
/* considering it used only in lgc to set LUA_TDEADKEY */
/* we could define it this way */
#define setttype(obj, _tt) ( ttype_sig(obj) = add_sig(_tt) )
#endif // #ifndef LUA_PACK_VALUE
#define iscollectable(o) (ttype(o) >= LUA_TSTRING) #define iscollectable(o) (ttype(o) >= LUA_TSTRING)
...@@ -367,8 +230,15 @@ typedef union TString { ...@@ -367,8 +230,15 @@ typedef union TString {
} tsv; } tsv;
} TString; } TString;
#ifdef LUA_CROSS_COMPILER
#define getstr(ts) (((ts)->tsv.marked & READONLYMASK) ? cast(const char *, *(const char**)((ts) + 1)) : 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))
...@@ -418,6 +288,7 @@ typedef struct Proto { ...@@ -418,6 +288,7 @@ 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 */
...@@ -487,7 +358,6 @@ typedef union Closure { ...@@ -487,7 +358,6 @@ typedef union Closure {
** Tables ** Tables
*/ */
#ifndef LUA_PACK_VALUE
typedef union TKey { typedef union TKey {
struct { struct {
TValuefields; TValuefields;
...@@ -497,16 +367,6 @@ typedef union TKey { ...@@ -497,16 +367,6 @@ typedef union TKey {
} TKey; } TKey;
#define LUA_TKEY_NIL {LUA_TVALUE_NIL, NULL} #define LUA_TKEY_NIL {LUA_TVALUE_NIL, NULL}
#else // #ifndef LUA_PACK_VALUE
typedef struct TKey {
TValue tvk;
struct {
struct Node *next; /* for chaining */
} nk;
} TKey;
#define LUA_TKEY_NIL {LUA_TVALUE_NIL}, {NULL}
#endif // #ifndef LUA_PACK_VALUE
typedef struct Node { typedef struct Node {
TValue i_val; TValue i_val;
......
...@@ -916,12 +916,11 @@ static int block_follow (int token) { ...@@ -916,12 +916,11 @@ static int block_follow (int token) {
static void block (LexState *ls) { static void block (LexState *ls) {
/* block -> chunk */ /* block -> chunk */
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
BlockCnt *pbl = (BlockCnt*)luaM_malloc(ls->L,sizeof(BlockCnt)); BlockCnt bl;
enterblock(fs, pbl, 0); enterblock(fs, &bl, 0);
chunk(ls); chunk(ls);
lua_assert(pbl->breaklist == NO_JUMP); lua_assert(bl.breaklist == NO_JUMP);
leaveblock(fs); leaveblock(fs);
luaM_free(ls->L,pbl);
} }
...@@ -1081,13 +1080,13 @@ static int exp1 (LexState *ls) { ...@@ -1081,13 +1080,13 @@ static int exp1 (LexState *ls) {
static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
/* forbody -> DO block */ /* forbody -> DO block */
BlockCnt *pbl = (BlockCnt*)luaM_malloc(ls->L,sizeof(BlockCnt)); BlockCnt bl;
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
int prep, endfor; int prep, endfor;
adjustlocalvars(ls, 3); /* control variables */ adjustlocalvars(ls, 3); /* control variables */
checknext(ls, TK_DO); checknext(ls, TK_DO);
prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
enterblock(fs, pbl, 0); /* scope for declared variables */ enterblock(fs, &bl, 0); /* scope for declared variables */
adjustlocalvars(ls, nvars); adjustlocalvars(ls, nvars);
luaK_reserveregs(fs, nvars); luaK_reserveregs(fs, nvars);
block(ls); block(ls);
...@@ -1097,7 +1096,6 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { ...@@ -1097,7 +1096,6 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
luaM_free(ls->L,pbl);
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#undef LNILVAL #undef LNILVAL
#undef LREGISTER #undef LREGISTER
#if (MIN_OPT_LEVEL > 0) && (LUA_OPTIMIZE_MEMORY >= MIN_OPT_LEVEL) #if LUA_OPTIMIZE_MEMORY >=1
#define LUA_REG_TYPE luaR_entry #define LUA_REG_TYPE luaR_entry
#define LSTRKEY LRO_STRKEY #define LSTRKEY LRO_STRKEY
#define LNUMKEY LRO_NUMKEY #define LNUMKEY LRO_NUMKEY
......
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