Unverified Commit 11592951 authored by Arnim Läuger's avatar Arnim Läuger Committed by GitHub
Browse files

Merge pull request #2582 from nodemcu/dev

Next master drop
parents 4095c408 61433c44
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lrotable.h"
#undef PI #undef PI
#define PI (3.14159265358979323846) #define PI (3.14159265358979323846)
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lrotable.h"
/* prefix for open functions in C libraries */ /* prefix for open functions in C libraries */
#define LUA_POF "luaopen_" #define LUA_POF "luaopen_"
...@@ -474,10 +473,11 @@ static int ll_require (lua_State *L) { ...@@ -474,10 +473,11 @@ static int ll_require (lua_State *L) {
return 1; /* package is already loaded */ return 1; /* package is already loaded */
} }
/* Is this a readonly table? */ /* Is this a readonly table? */
void *res = luaR_findglobal(name, c_strlen(name)); lua_getfield(L, LUA_GLOBALSINDEX, name);
if (res) { if(lua_isrotable(L,-1)) {
lua_pushrotable(L, res);
return 1; return 1;
} else {
lua_pop(L, 1);
} }
/* else must load it; iterate over available loaders */ /* else must load it; iterate over available loaders */
lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); lua_getfield(L, LUA_ENVIRONINDEX, "loaders");
...@@ -563,8 +563,13 @@ static void modinit (lua_State *L, const char *modname) { ...@@ -563,8 +563,13 @@ static void modinit (lua_State *L, const char *modname) {
static int ll_module (lua_State *L) { static int ll_module (lua_State *L) {
const char *modname = luaL_checkstring(L, 1); const char *modname = luaL_checkstring(L, 1);
if (luaR_findglobal(modname, c_strlen(modname))) /* Is this a readonly table? */
lua_getfield(L, LUA_GLOBALSINDEX, modname);
if(lua_isrotable(L,-1)) {
return 0; return 0;
} else {
lua_pop(L, 1);
}
int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ int loaded = lua_gettop(L) + 1; /* index of _LOADED table */
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ lua_getfield(L, loaded, modname); /* get _LOADED[modname] */
......
...@@ -34,20 +34,33 @@ ...@@ -34,20 +34,33 @@
#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__
/*
** 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
*/
#define GET_BYTE_FN(name,t,wo,bo) \
static inline lu_byte get ## name(void *o) { \
lu_byte res; /* extract named field */ \
asm ("l32i %0, %1, " #wo "; extui %0, %0, " #bo ", 8;" : "=r"(res) : "r"(o) : );\
return res; }
#else
#define GET_BYTE_FN(name,t,wo,bo) \
static inline lu_byte get ## name(void *o) { return ((t *)o)->name; }
#endif
/* /*
** Union of all collectable objects ** Union of all collectable objects
*/ */
typedef union GCObject GCObject; typedef union GCObject GCObject;
/* /*
** Common Header for all collectable objects (in macro form, to be ** Common Header for all collectable objects (in macro form, to be
** included in other objects) ** included in other objects)
*/ */
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked #define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
/* /*
** Common header in struct form ** Common header in struct form
*/ */
...@@ -55,11 +68,18 @@ typedef struct GCheader { ...@@ -55,11 +68,18 @@ typedef struct GCheader {
CommonHeader; CommonHeader;
} GCheader; } GCheader;
/*
** Word aligned inline access functions for the CommonHeader tt and marked fields.
** Note that these MUST be consistent with the CommonHeader definition above. Arg
** 3 is a word offset (4 bytes in this case) and arg 4 the bit offset in the word.
*/
GET_BYTE_FN(tt,GCheader,4,0)
GET_BYTE_FN(marked,GCheader,4,8)
#if defined(LUA_PACK_VALUE) || defined(ELUA_ENDIAN_BIG) || defined(ELUA_ENDIAN_SMALL) #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" # error "NodeMCU does not support the eLua LUA_PACK_VALUE and ELUA_ENDIAN defines"
#endif #endif
/* /*
** Union of all Lua values ** Union of all Lua values
*/ */
...@@ -214,7 +234,6 @@ typedef struct lua_TValue { ...@@ -214,7 +234,6 @@ typedef struct lua_TValue {
#define iscollectable(o) (ttype(o) >= LUA_TSTRING) #define iscollectable(o) (ttype(o) >= LUA_TSTRING)
typedef TValue *StkId; /* index to stack elements */ typedef TValue *StkId; /* index to stack elements */
...@@ -386,6 +405,7 @@ typedef struct Table { ...@@ -386,6 +405,7 @@ typedef struct Table {
int sizearray; /* size of `array' array */ int sizearray; /* size of `array' array */
} Table; } Table;
typedef const struct luaR_entry ROTable;
/* /*
** `module' operation for hashing (size is always a power of 2) ** `module' operation for hashing (size is always a power of 2)
......
...@@ -38,5 +38,10 @@ ...@@ -38,5 +38,10 @@
return 1 return 1
#endif #endif
#define LROT_TABENTRY(n,t) {LSTRKEY(#n), LRO_ROVAL(t)}
#define LROT_FUNCENTRY(n,f) {LSTRKEY(#n), LRO_FUNCVAL(f)}
#define LROT_NUMENTRY(n,x) {LSTRKEY(#n), LRO_NUMVAL(x)}
#define LROT_END {LNILKEY, LNILVAL}
#endif /* lrodefs_h */ #endif /* lrodefs_h */
...@@ -9,77 +9,139 @@ ...@@ -9,77 +9,139 @@
#include "lobject.h" #include "lobject.h"
#include "lapi.h" #include "lapi.h"
/* Local defines */ #define ALIGNED_STRING (__attribute__((aligned(4))) char *)
#define LUAR_FINDFUNCTION 0 #define LA_LINES 16
#define LUAR_FINDVALUE 1 #define LA_SLOTS 4
//#define COLLECT_STATS
/* Externally defined read-only table array */
extern const luaR_table *lua_rotable; /*
* All keyed ROtable access passes through luaR_findentry(). ROTables
/* Find a global "read only table" in the constant lua_rotable array */ * are simply a list of <key><TValue value> pairs. The existing algo
void* luaR_findglobal(const char *name, unsigned len) { * did a linear scan of this vector of pairs looking for a match.
unsigned i; *
* A N×M lookaside cache has been added, with a simple hash on the key's
if (c_strlen(name) > LUA_MAX_ROTABLE_NAME) * TString addr and the ROTable addr to identify one of N lines. Each
return NULL; * line has M slots which are scanned. This is all done in RAM and is
for (i=0; lua_rotable[i].name; i ++) * perhaps 20x faster than the corresponding random Flash accesses which
if (*lua_rotable[i].name != '\0' && c_strlen(lua_rotable[i].name) == len && !c_strncmp(lua_rotable[i].name, name, len)) { * will cause flash faults.
return (void*)(lua_rotable[i].pentries); *
* If a match is found and the table addresses match, then this entry is
* probed first. In practice the hit-rate here is over 99% so the code
* rarely fails back to doing the linear scan in ROM.
*
* Note that this hash does a couple of prime multiples and a modulus 2^X
* with is all evaluated in H/W, and adequately randomizes the lookup.
*/
#define HASH(a,b) (519*((size_t)(a)>>4) + 17*((size_t)(b)>>4))
static struct {
unsigned hash;
unsigned addr:24;
unsigned ndx:8;
} cache[LA_LINES][LA_SLOTS];
#ifdef COLLECT_STATS
unsigned cache_stats[3];
#define COUNT(i) cache_stats[i]++
#else
#define COUNT(i)
#endif
static int lookup_cache(unsigned hash, ROTable *rotable) {
int i = (hash>>2) & (LA_LINES-1), j;
for (j = 0; j<LA_SLOTS; j++) {
if (cache[i][j].hash == hash &&
((size_t)rotable & 0xffffffu) == cache[i][j].addr) {
COUNT(0);
return cache[i][j].ndx;
} }
return NULL; }
COUNT(1);
return -1;
} }
/* Find an entry in a rotable and return it */ static void update_cache(unsigned hash, ROTable *rotable, unsigned ndx) {
static const TValue* luaR_auxfind(const luaR_entry *pentry, const char *strkey, luaR_numkey numkey, unsigned *ppos) { int i = (hash)>>2 & (LA_LINES-1), j;
const TValue *res = NULL; COUNT(2);
unsigned i = 0; if (ndx>0xffu)
return;
if (pentry == NULL) for (j = LA_SLOTS-1; j>0; j--)
return NULL; cache[i][j] = cache[i][j-1];
while(pentry->key.type != LUA_TNIL) { cache[i][0].hash = hash;
if ((strkey && (pentry->key.type == LUA_TSTRING) && (!c_strcmp(pentry->key.id.strkey, strkey))) || cache[i][0].addr = (size_t) rotable;
(!strkey && (pentry->key.type == LUA_TNUMBER) && ((luaR_numkey)pentry->key.id.numkey == numkey))) { cache[i][0].ndx = ndx;
res = &pentry->value; }
break; /*
* Find a string key entry in a rotable and return it. Note that this internally
* uses a null key to denote a metatable search.
*/
const TValue* luaR_findentry(ROTable *rotable, TString *key, unsigned *ppos) {
const luaR_entry *pentry = rotable;
const char *strkey = key ? getstr(key) : ALIGNED_STRING "__metatable" ;
size_t hash = HASH(rotable, key);
unsigned i = 0;
int j = lookup_cache(hash, rotable);
if (pentry) {
if (j >= 0){
if ((pentry[j].key.type == LUA_TSTRING) &&
!c_strcmp(pentry[j].key.id.strkey, strkey)) {
if (ppos)
*ppos = j;
return &pentry[j].value;
}
}
/*
* The invariants for 1st word comparison are deferred to here since they
* aren't needed if there is a cache hit. Note that the termination null
* is included so a "on\0" has a mask of 0xFFFFFF and "a\0" has 0xFFFF.
*/
unsigned name4 = *(unsigned *)strkey;
unsigned l = key ? key->tsv.len : sizeof("__metatable")-1;
unsigned mask4 = l > 2 ? (~0u) : (~0u)>>((3-l)*8);
for(;pentry->key.type != LUA_TNIL; i++, pentry++) {
if ((pentry->key.type == LUA_TSTRING) &&
((*(unsigned *)pentry->key.id.strkey ^ name4) & mask4) == 0 &&
!c_strcmp(pentry->key.id.strkey, strkey)) {
if (ppos)
*ppos = i;
if (j==-1) {
update_cache(hash, rotable, pentry - rotable);
} else if (j != (pentry - rotable)) {
j = 0;
}
return &pentry->value;
}
} }
i ++; pentry ++;
} }
if (res && ppos) return luaO_nilobject;
*ppos = i;
return res;
} }
int luaR_findfunction(lua_State *L, const luaR_entry *ptable) { const TValue* luaR_findentryN(ROTable *rotable, luaR_numkey numkey, unsigned *ppos) {
const TValue *res = NULL; unsigned i = 0;
const char *key = luaL_checkstring(L, 2); const luaR_entry *pentry = rotable;
if (pentry) {
res = luaR_auxfind(ptable, key, 0, NULL); for ( ;pentry->key.type != LUA_TNIL; i++, pentry++) {
if (res && ttislightfunction(res)) { if (pentry->key.type == LUA_TNUMBER && (luaR_numkey) pentry->key.id.numkey == numkey) {
luaA_pushobject(L, res); if (ppos)
return 1; *ppos = i;
return &pentry->value;
}
}
} }
else return NULL;
return 0;
} }
/* Find an entry in a rotable and return its type
If "strkey" is not NULL, the function will look for a string key,
otherwise it will look for a number key */
const TValue* luaR_findentry(void *data, const char *strkey, luaR_numkey numkey, unsigned *ppos) {
return luaR_auxfind((const luaR_entry*)data, strkey, numkey, ppos);
}
/* Find the metatable of a given table */ /* Find the metatable of a given table */
void* luaR_getmeta(void *data) { void* luaR_getmeta(ROTable *rotable) {
#ifdef LUA_META_ROTABLES const TValue *res = luaR_findentry(rotable, NULL, NULL);
const TValue *res = luaR_auxfind((const luaR_entry*)data, "__metatable", 0, NULL);
return res && ttisrotable(res) ? rvalue(res) : NULL; return res && ttisrotable(res) ? rvalue(res) : NULL;
#else
return NULL;
#endif
} }
static void luaR_next_helper(lua_State *L, const luaR_entry *pentries, int pos, TValue *key, TValue *val) { static void luaR_next_helper(lua_State *L, ROTable *pentries, int pos,
TValue *key, TValue *val) {
setnilvalue(key); setnilvalue(key);
setnilvalue(val); setnilvalue(val);
if (pentries[pos].key.type != LUA_TNIL) { if (pentries[pos].key.type != LUA_TNIL) {
...@@ -91,56 +153,24 @@ static void luaR_next_helper(lua_State *L, const luaR_entry *pentries, int pos, ...@@ -91,56 +153,24 @@ static void luaR_next_helper(lua_State *L, const luaR_entry *pentries, int pos,
setobj2s(L, val, &pentries[pos].value); setobj2s(L, val, &pentries[pos].value);
} }
} }
/* next (used for iteration) */ /* next (used for iteration) */
void luaR_next(lua_State *L, void *data, TValue *key, TValue *val) { void luaR_next(lua_State *L, ROTable *rotable, TValue *key, TValue *val) {
const luaR_entry* pentries = (const luaR_entry*)data;
char strkey[LUA_MAX_ROTABLE_NAME + 1], *pstrkey = NULL;
luaR_numkey numkey = 0;
unsigned keypos; unsigned keypos;
/* Special case: if key is nil, return the first element of the rotable */ /* Special case: if key is nil, return the first element of the rotable */
if (ttisnil(key)) if (ttisnil(key))
luaR_next_helper(L, pentries, 0, key, val); luaR_next_helper(L, rotable, 0, key, val);
else if (ttisstring(key) || ttisnumber(key)) { else if (ttisstring(key) || ttisnumber(key)) {
/* Find the previoud key again */ /* Find the previous key again */
if (ttisstring(key)) { if (ttisstring(key)) {
luaR_getcstr(strkey, rawtsvalue(key), LUA_MAX_ROTABLE_NAME); luaR_findentry(rotable, rawtsvalue(key), &keypos);
pstrkey = strkey; } else {
} else luaR_findentryN(rotable, (luaR_numkey)nvalue(key), &keypos);
numkey = (luaR_numkey)nvalue(key); }
luaR_findentry(data, pstrkey, numkey, &keypos);
/* Advance to next key */ /* Advance to next key */
keypos ++; keypos ++;
luaR_next_helper(L, pentries, keypos, key, val); luaR_next_helper(L, rotable, keypos, key, val);
} }
} }
/* Convert a Lua string to a C string */
void luaR_getcstr(char *dest, const TString *src, size_t maxsize) {
if (src->tsv.len+1 > maxsize)
dest[0] = '\0';
else {
c_memcpy(dest, getstr(src), src->tsv.len);
dest[src->tsv.len] = '\0';
}
}
#ifdef LUA_META_ROTABLES
/* Set in RO check depending on platform */
#if defined(LUA_CROSS_COMPILER) && defined(__CYGWIN__)
extern char __end__[];
#define IN_RO_AREA(p) ((p) < __end__)
#elif defined(LUA_CROSS_COMPILER)
extern char _edata[];
#define IN_RO_AREA(p) ((p) < _edata)
#else /* xtensa tool chain for ESP target */
extern char _irom0_text_start[];
extern char _irom0_text_end[];
#define IN_RO_AREA(p) ((p) >= _irom0_text_start && (p) <= _irom0_text_end)
#endif
/* Return 1 if the given pointer is a rotable */
int luaR_isrotable(void *p) {
return IN_RO_AREA((char *)p);
}
#endif
...@@ -14,7 +14,11 @@ ...@@ -14,7 +14,11 @@
#define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER} #define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
#define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE} #define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE}
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL} #define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
#ifdef LUA_CROSS_COMPILER
#define LRO_STRKEY(k) {LUA_TSTRING, {.strkey = k}} #define LRO_STRKEY(k) {LUA_TSTRING, {.strkey = k}}
#else
#define LRO_STRKEY(k) {LUA_TSTRING, {.strkey = (STORE_ATTR char *) k}}
#endif
#define LRO_NUMKEY(k) {LUA_TNUMBER, {.numkey = k}} #define LRO_NUMKEY(k) {LUA_TNUMBER, {.numkey = k}}
#define LRO_NILKEY {LUA_TNIL, {.strkey=NULL}} #define LRO_NILKEY {LUA_TNIL, {.strkey=NULL}}
...@@ -25,40 +29,58 @@ ...@@ -25,40 +29,58 @@
typedef int luaR_numkey; typedef int luaR_numkey;
/* The next structure defines the type of a key */ /* The next structure defines the type of a key */
typedef struct typedef struct {
{
int type; int type;
union union {
{
const char* strkey; const char* strkey;
luaR_numkey numkey; luaR_numkey numkey;
} id; } id;
} luaR_key; } luaR_key;
/* An entry in the read only table */ /* An entry in the read only table */
typedef struct typedef struct luaR_entry {
{
const luaR_key key; const luaR_key key;
const TValue value; const TValue value;
} luaR_entry; } luaR_entry;
/* A rotable */ /*
typedef struct * The current ROTable implmentation is a vector of luaR_entry terminated by a
{ * nil record. The convention is to use ROtable * to refer to the entire vector
const char *name; * as a logical ROTable.
const luaR_entry *pentries; */
} luaR_table; typedef const struct luaR_entry ROTable;
void* luaR_findglobal(const char *key, unsigned len); const TValue* luaR_findentry(ROTable *tab, TString *key, unsigned *ppos);
int luaR_findfunction(lua_State *L, const luaR_entry *ptable); const TValue* luaR_findentryN(ROTable *tab, luaR_numkey numkey, unsigned *ppos);
const TValue* luaR_findentry(void *data, const char *strkey, luaR_numkey numkey, unsigned *ppos); void luaR_next(lua_State *L, ROTable *tab, TValue *key, TValue *val);
void luaR_getcstr(char *dest, const TString *src, size_t maxsize); void* luaR_getmeta(ROTable *tab);
void luaR_next(lua_State *L, void *data, TValue *key, TValue *val);
void* luaR_getmeta(void *data);
#ifdef LUA_META_ROTABLES
int luaR_isrotable(void *p); int luaR_isrotable(void *p);
/*
* Set inRO check depending on platform. Note that this implementation needs
* to work on both the host (luac.cross) and ESP targets. The luac.cross
* VM is used for the -e option, and is primarily used to be able to debug
* VM changes on the more developer-friendly hot gdb environment.
*/
#if defined(LUA_CROSS_COMPILER)
#if defined(__CYGWIN__)
#define _RODATA_END __end__
#else #else
#define luaR_isrotable(p) (0) #define _RODATA_END _edata
#endif
extern const char _RODATA_END[];
#define IN_RODATA_AREA(p) (((const char *)(p)) < _RODATA_END)
#else /* xtensa tool chain for ESP target */
extern const char _irom0_text_start[];
extern const char _irom0_text_end[];
#define IN_RODATA_AREA(p) (((const char *)(p)) >= _irom0_text_start && ((const char *)(p)) <= _irom0_text_end)
#endif #endif
/* Return 1 if the given pointer is a rotable */
#define luaR_isrotable(p) IN_RODATA_AREA(p)
#endif #endif
...@@ -80,16 +80,12 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, ...@@ -80,16 +80,12 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
return ts; return ts;
} }
#ifdef LUA_CROSS_COMPILER static int lua_is_ptr_in_ro_area(const char *p) {
#define IN_RO_AREA(p) (0) #ifdef LUA_CROSS_COMPILER
#else /* xtensa tool chain for ESP */ return 0; // TStrings are never in RO in luac.cross
extern char _irom0_text_start[]; #else
extern char _irom0_text_end[]; return IN_RODATA_AREA(p);
#define IN_RO_AREA(p) ((p) >= _irom0_text_start && (p) <= _irom0_text_end)
#endif #endif
int lua_is_ptr_in_ro_area(const char *p) {
return IN_RO_AREA(p);
} }
/* /*
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include "lstate.h" #include "lstate.h"
#define sizestring(s) (sizeof(union TString)+(testbit((s)->marked, READONLYBIT) ? sizeof(char **) : ((s)->len+1)*sizeof(char))) #define sizestring(s) (sizeof(union TString)+(testbit(getmarked(s), READONLYBIT) ? sizeof(char **) : ((s)->len+1)*sizeof(char)))
#define sizeudata(u) (sizeof(union Udata)+(u)->len) #define sizeudata(u) (sizeof(union Udata)+(u)->len)
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lrotable.h"
/* macro to `unsign' a character */ /* macro to `unsign' a character */
#define uchar(c) ((unsigned char)(c)) #define uchar(c) ((unsigned char)(c))
......
...@@ -580,7 +580,7 @@ const TValue *luaH_getnum (Table *t, int key) { ...@@ -580,7 +580,7 @@ const TValue *luaH_getnum (Table *t, int key) {
/* same thing for rotables */ /* same thing for rotables */
const TValue *luaH_getnum_ro (void *t, int key) { const TValue *luaH_getnum_ro (void *t, int key) {
const TValue *res = luaR_findentry(t, NULL, key, NULL); const TValue *res = luaR_findentryN(t, key, NULL);
return res ? res : luaO_nilobject; return res ? res : luaO_nilobject;
} }
...@@ -599,14 +599,10 @@ const TValue *luaH_getstr (Table *t, TString *key) { ...@@ -599,14 +599,10 @@ const TValue *luaH_getstr (Table *t, TString *key) {
} }
/* same thing for rotables */ /* same thing for rotables */
const TValue *luaH_getstr_ro (void *t, TString *key) { const TValue *luaH_getstr_ro (void *t, TString *key) {
char keyname[LUA_MAX_ROTABLE_NAME + 1]; if (!t || key->tsv.len>LUA_MAX_ROTABLE_NAME)
const TValue *res;
if (!t)
return luaO_nilobject; return luaO_nilobject;
luaR_getcstr(keyname, key, LUA_MAX_ROTABLE_NAME); return luaR_findentry(t, key, NULL);
res = luaR_findentry(t, keyname, 0, NULL);
return res ? res : luaO_nilobject;
} }
...@@ -745,7 +741,7 @@ int luaH_getn (Table *t) { ...@@ -745,7 +741,7 @@ int luaH_getn (Table *t) {
int luaH_getn_ro (void *t) { int luaH_getn_ro (void *t) {
int i = 1, len=0; int i = 1, len=0;
while(luaR_findentry(t, NULL, i ++, NULL)) while(luaR_findentryN(t, i ++, NULL))
len ++; len ++;
return len; return len;
} }
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lrotable.h"
#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) #define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))
......
...@@ -50,14 +50,22 @@ void luaT_init (lua_State *L) { ...@@ -50,14 +50,22 @@ void luaT_init (lua_State *L) {
** tag methods ** tag methods
*/ */
const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
const TValue *tm = luaR_isrotable(events) ? luaH_getstr_ro(events, ename) : luaH_getstr(events, ename); const TValue *tm;
lua_assert(event <= TM_EQ); lua_assert(event <= TM_EQ);
if (ttisnil(tm)) { /* no tag method? */
if (!luaR_isrotable(events)) if (luaR_isrotable(events)) {
tm = luaH_getstr_ro(events, ename);
if (ttisnil(tm)) { /* no tag method? */
return NULL;
}
} else {
tm = luaH_getstr(events, ename);
if (ttisnil(tm)) { /* no tag method? */
events->flags |= cast_byte(1u<<event); /* cache this fact */ events->flags |= cast_byte(1u<<event); /* cache this fact */
return NULL; return NULL;
} }
else return tm; }
return tm;
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "lobject.h" #include "lobject.h"
#include "lrotable.h"
/* /*
* WARNING: if you change the order of this enumeration, * WARNING: if you change the order of this enumeration,
...@@ -36,12 +36,10 @@ typedef enum { ...@@ -36,12 +36,10 @@ typedef enum {
TM_N /* number of elements in the enum */ TM_N /* number of elements in the enum */
} TMS; } TMS;
#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ #define gfasttm(g,et,e) ((et) == NULL ? NULL : \
!luaR_isrotable(et) && ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) (!luaR_isrotable(et) && ((et)->flags & (1u<<(e)))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
#define fasttm(l,et,e) gfasttm(G(l), et, e) #define fasttm(l,et,e) gfasttm(G(l), et, e)
LUAI_DATA const char *const luaT_typenames[]; LUAI_DATA const char *const luaT_typenames[];
......
# #
# This Make file is called from the core Makefile hierarchy which is a hierarchical # This Make file is called from the core Makefile hierarchy with is a hierarchical
# make which uses parent callbacks to implement inheritance. However if luac_cross # make wwhich uses parent callbacks to implement inheritance. However is luac_cross
# build stands outside this it uses the host toolchain to implement a separate # build stands outside this and uses the host toolchain to implement a separate
# host build of the luac.cross image. # host build of the luac.cross image.
# #
.NOTPARALLEL: .NOTPARALLEL:
CCFLAGS:= -I.. -I../../include -I../../../include -I ../../libc CCFLAGS:= -I.. -I../../include -I../../libc -I../../uzlib
LDFLAGS:= -L$(SDK_DIR)/lib -L$(SDK_DIR)/ld -lm -ldl -Wl,-Map=mapfile LDFLAGS:= -L$(SDK_DIR)/lib -L$(SDK_DIR)/ld -lm -ldl -Wl,-Map=mapfile
CCFLAGS += -Wall CCFLAGS += -Wall
...@@ -18,6 +18,7 @@ TARGET = host ...@@ -18,6 +18,7 @@ TARGET = host
ifeq ($(FLAVOR),debug) ifeq ($(FLAVOR),debug)
CCFLAGS += -O0 -g CCFLAGS += -O0 -g
TARGET_LDFLAGS += -O0 -g TARGET_LDFLAGS += -O0 -g
DEFINES += -DLUA_DEBUG_BUILD
else else
FLAVOR = release FLAVOR = release
CCFLAGS += -O2 CCFLAGS += -O2
...@@ -31,13 +32,13 @@ LUASRC := lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c ldebug.c ...@@ -31,13 +32,13 @@ LUASRC := lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c ldebug.c
lrotable.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c \ lrotable.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c \
ltm.c lundump.c lvm.c lzio.c ltm.c lundump.c lvm.c lzio.c
LIBCSRC := c_stdlib.c LIBCSRC := c_stdlib.c
UZSRC := uzlib_deflate.c crc32.c
# #
# This relies on the files being unique on the vpath # This relies on the files being unique on the vpath
# #
SRC := $(LUACSRC) $(LUASRC) $(LIBCSRC) SRC := $(LUACSRC) $(LUASRC) $(LIBCSRC) $(UZSRC)
vpath %.c .:..:../../libc vpath %.c .:..:../../libc:../../uzlib
ODIR := .output/$(TARGET)/$(FLAVOR)/obj ODIR := .output/$(TARGET)/$(FLAVOR)/obj
...@@ -51,12 +52,7 @@ CC := $(WRAPCC) gcc ...@@ -51,12 +52,7 @@ CC := $(WRAPCC) gcc
ECHO := echo ECHO := echo
BUILD_TYPE := $(shell $(CC) $(EXTRA_CCFLAGS) -E -dM - <../../../app/include/user_config.h | grep LUA_NUMBER_INTEGRAL | wc -l)
ifeq ($(BUILD_TYPE),0)
IMAGE := ../../../luac.cross IMAGE := ../../../luac.cross
else
IMAGE := ../../../luac.cross.int
endif
.PHONY: test clean all .PHONY: test clean all
...@@ -70,7 +66,6 @@ test : ...@@ -70,7 +66,6 @@ test :
@echo SRC: $(SRC) @echo SRC: $(SRC)
@echo OBJS: $(OBJS) @echo OBJS: $(OBJS)
@echo DEPS: $(DEPS) @echo DEPS: $(DEPS)
@echo IMAGE: $(IMAGE)
clean : clean :
$(RM) -r $(ODIR) $(RM) -r $(ODIR)
......
/* /***--
** lflashimg.c ** lflashimg.c
** Dump a compiled Proto hiearchy to a RO (FLash) image file ** Dump a compiled Proto hiearchy to a RO (FLash) image file
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#undef LUA_FLASH_STORE #undef LUA_FLASH_STORE
#define LUA_FLASH_STORE #define LUA_FLASH_STORE
#include "lflash.h" #include "lflash.h"
#include "uzlib.h"
//#define LOCAL_DEBUG //#define LOCAL_DEBUG
...@@ -46,18 +47,18 @@ typedef unsigned int uint; ...@@ -46,18 +47,18 @@ typedef unsigned int uint;
* independent image format, which permits the on-device image loader to load the LFS * independent image format, which permits the on-device image loader to load the LFS
* image at an appropriate base within the flash address space. As all objects in the * image at an appropriate base within the flash address space. As all objects in the
* LFS can be treated as multiples of 4-byte words, also all address fields are both * LFS can be treated as multiples of 4-byte words, also all address fields are both
* word aligned, and any address references within the LFS are also word-aligned, * word aligned, and any address references within the LFS are also word-aligned.
* such addresses are stored in a special format, where each PI address is two
* 16-bit unsigned offsets:
* *
* Bits 0-15 is the offset into the LFS that this address refers to * This version adds gzip compression of the generated LFS image for more efficient
* Bits 16-31 is the offset linking to the PIC next address. * over-the-air (OTA) transfer, so the method of tagging address words has been
* replaced by a scheme which achieves better compression: an additional bitmap
* has been added to the image, with each bit corresponding to a word in the image
* and set if the corresponding work is an address. The addresses are stored as
* signed relative word offsets.
* *
* Hence the LFS can be up to 256Kb in length and the flash loader can use the forward * The unloader is documented in lflash.c Note that his relocation process is
* links to chain down PI address from the mainProto address at offet 3 to all image * skipped for absolute addressed images (which are identified by the
* addresses during load and convert them to the corresponding correct absolute memory * FLASH_SIG_ABSOLUTE bit setting in the flash signature).
* addresses. This reloation process is skipped for absolute addressed images (which
* are identified by the FLASH_SIG_ABSOLUTE bit setting in the flash signature.
* *
* The flash image has a standard header detailed in lflash.h * The flash image has a standard header detailed in lflash.h
* *
...@@ -66,7 +67,7 @@ typedef unsigned int uint; ...@@ -66,7 +67,7 @@ typedef unsigned int uint;
* and int may not have the same size. Hence addresses with the must be declared as * and int may not have the same size. Hence addresses with the must be declared as
* the FlashAddr type rather than typed C pointers and must be accessed through macros. * the FlashAddr type rather than typed C pointers and must be accessed through macros.
* *
* ALso note that image built with a given LUA_PACK_TVALUES / LUA_NUNBER_INTEGRAL * Also note that image built with a given LUA_PACK_TVALUES / LUA_NUNBER_INTEGRAL
* combination must be loaded into a corresponding firmware build. Hence these * combination must be loaded into a corresponding firmware build. Hence these
* configuration options are also included in the FLash Signature. * configuration options are also included in the FLash Signature.
* *
...@@ -96,8 +97,19 @@ typedef struct flashts { /* This is the fixed 32-bit equivalent of TString ...@@ -96,8 +97,19 @@ typedef struct flashts { /* This is the fixed 32-bit equivalent of TString
#endif #endif
static uint curOffset = 0; static uint curOffset = 0;
static uint flashImage[LUA_MAX_FLASH_SIZE];
static unsigned char flashAddrTag[LUA_MAX_FLASH_SIZE/WORDSIZE]; /*
* The flashAddrTag is a bit array, one bit per flashImage word denoting
* whether the corresponding word is a relative address. The defines
* are access methods for this bit array.
*/
static uint flashImage[LUA_MAX_FLASH_SIZE + LUA_MAX_FLASH_SIZE/32];
static uint *flashAddrTag = flashImage + LUA_MAX_FLASH_SIZE;
#define _TW(v) (v)>>5
#define _TB(v) (1<<((v)&0x1F))
#define setFlashAddrTag(v) flashAddrTag[_TW(v)] |= _TB(v)
#define getFlashAddrTag(v) ((flashAddrTag[_TW(v)]&_TB(v)) != 0)
#define fatal luac_fatal #define fatal luac_fatal
extern void __attribute__((noreturn)) luac_fatal(const char* message); extern void __attribute__((noreturn)) luac_fatal(const char* message);
...@@ -115,7 +127,7 @@ static void *flashAlloc(lua_State* L, size_t n) { ...@@ -115,7 +127,7 @@ static void *flashAlloc(lua_State* L, size_t n) {
void *p = (void *)(flashImage + curOffset); void *p = (void *)(flashImage + curOffset);
curOffset += ALIGN(n)>>WORDSHIFT; curOffset += ALIGN(n)>>WORDSHIFT;
if (curOffset > LUA_MAX_FLASH_SIZE) { if (curOffset > LUA_MAX_FLASH_SIZE) {
fatal("Out of Flash memmory"); fatal("Out of Flash memory");
} }
return p; return p;
} }
...@@ -128,8 +140,8 @@ static void *flashAlloc(lua_State* L, size_t n) { ...@@ -128,8 +140,8 @@ static void *flashAlloc(lua_State* L, size_t n) {
#define toFlashAddr(l, pd, s) _toFlashAddr(l, &(pd), s) #define toFlashAddr(l, pd, s) _toFlashAddr(l, &(pd), s)
static void _toFlashAddr(lua_State* L, FlashAddr *a, void *p) { static void _toFlashAddr(lua_State* L, FlashAddr *a, void *p) {
uint doffset = cast(char *, a) - cast(char *,flashImage); uint doffset = cast(char *, a) - cast(char *,flashImage);
lua_assert(!(doffset & (WORDSIZE-1))); lua_assert(!(doffset & (WORDSIZE-1))); // check word aligned
doffset >>= WORDSHIFT; doffset >>= WORDSHIFT; // and convert to a word offset
lua_assert(doffset <= curOffset); lua_assert(doffset <= curOffset);
if (p) { if (p) {
uint poffset = cast(char *, p) - cast(char *,flashImage); uint poffset = cast(char *, p) - cast(char *,flashImage);
...@@ -137,10 +149,8 @@ static void _toFlashAddr(lua_State* L, FlashAddr *a, void *p) { ...@@ -137,10 +149,8 @@ static void _toFlashAddr(lua_State* L, FlashAddr *a, void *p) {
poffset >>= WORDSHIFT; poffset >>= WORDSHIFT;
lua_assert(poffset <= curOffset); lua_assert(poffset <= curOffset);
flashImage[doffset] = poffset; // Set the pointer to the offset flashImage[doffset] = poffset; // Set the pointer to the offset
flashAddrTag[doffset] = 1; // And tag as an address setFlashAddrTag(doffset); // And tag as an address
} else { // Special case for NULL pointer } /* else leave clear */ // Special case for NULL pointer
flashImage[doffset] = 0;
}
} }
/* /*
...@@ -231,7 +241,7 @@ static void createROstrt(lua_State *L, FlashHeader *fh) { ...@@ -231,7 +241,7 @@ static void createROstrt(lua_State *L, FlashHeader *fh) {
fts->marked = bitmask(LFSBIT); // LFS string with no Whitebits set fts->marked = bitmask(LFSBIT); // LFS string with no Whitebits set
fts->hash = hash; // add hash fts->hash = hash; // add hash
fts->len = len; // and length fts->len = len; // and length
memcpy(flashAlloc(L, ALIGN(len+1)), p, ALIGN(len+1)); // copy string memcpy(flashAlloc(L, len+1), p, len+1); // copy string
// include the trailing null char // include the trailing null char
lua_pop(L, 1); // Junk the value lua_pop(L, 1); // Junk the value
lua_pushvalue(L, -1); // Dup the key as rawset dumps its copy lua_pushvalue(L, -1); // Dup the key as rawset dumps its copy
...@@ -308,6 +318,9 @@ static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) { ...@@ -308,6 +318,9 @@ static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) {
case 'I': case 'I':
*d++ = *s++; *d++ = *s++;
break; break;
case 'H':
*d++ = (*s++) & 0;
break;
case 'S': case 'S':
newts = resolveTString(L, *cast(TString **, s)); newts = resolveTString(L, *cast(TString **, s));
toFlashAddr(L, *d, newts); toFlashAddr(L, *d, newts);
...@@ -318,11 +331,15 @@ static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) { ...@@ -318,11 +331,15 @@ static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) {
/* This code has to work for both Integer and Float build variants */ /* This code has to work for both Integer and Float build variants */
memset(d, 0, TARGET_TV_SIZE); memset(d, 0, TARGET_TV_SIZE);
TValue *sv = cast(TValue *, s); TValue *sv = cast(TValue *, s);
/* The value is 0, 4 or 8 bytes depending on type */
if (ttisstring(sv)) { if (ttisstring(sv)) {
toFlashAddr(L, *d, resolveTString(L, rawtsvalue(sv))); toFlashAddr(L, *d, resolveTString(L, rawtsvalue(sv)));
} else { /* non-collectable types all of size lua_Number */ } else if (ttisnumber(sv)) {
lua_assert(!iscollectable(sv));
*cast(lua_Number*,d) = *cast(lua_Number*,s); *cast(lua_Number*,d) = *cast(lua_Number*,s);
} else if (!ttisnil(sv)){
/* all other types are 4 byte */
lua_assert(!iscollectable(sv));
*cast(uint *,d) = *cast(uint *,s);
} }
*cast(int *,cast(lua_Number*,d)+1) = ttype(sv); *cast(int *,cast(lua_Number*,d)+1) = ttype(sv);
s += FLASH_WORDS(TValue); s += FLASH_WORDS(TValue);
...@@ -338,9 +355,9 @@ static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) { ...@@ -338,9 +355,9 @@ static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) {
/* The debug optimised version has a different Proto layout */ /* The debug optimised version has a different Proto layout */
#ifdef LUA_OPTIMIZE_DEBUG #ifdef LUA_OPTIMIZE_DEBUG
#define PROTO_COPY_MASK "AIAAAAAASIIIIIIIAI" #define PROTO_COPY_MASK "AHAAAAAASIIIIIIIAI"
#else #else
#define PROTO_COPY_MASK "AIAAAAAASIIIIIIIIAI" #define PROTO_COPY_MASK "AHAAAAAASIIIIIIIIAI"
#endif #endif
/* /*
...@@ -378,44 +395,52 @@ static void *functionToFlash(lua_State* L, const Proto* orig) { ...@@ -378,44 +395,52 @@ static void *functionToFlash(lua_State* L, const Proto* orig) {
return cast(void *, flashCopy(L, 1, PROTO_COPY_MASK, &f)); return cast(void *, flashCopy(L, 1, PROTO_COPY_MASK, &f));
} }
/*
* Scan through the tagged addresses. This operates in one of two modes.
* - If address is non-zero then the offset is converted back into an absolute
* mapped flash address using the specified address base.
*
* - If the address is zero then form a form linked chain with the upper 16 bits
* the link to the last offset. As the scan is backwards, this 'last' address
* becomes forward reference for the on-chip LFS loader.
*/
void linkAddresses(lu_int32 address){
int i, last = 0;
for (i = curOffset-1 ; i >= 0; i--) {
if (flashAddrTag[i]) {
lua_assert(flashImage[i]<curOffset);
if (address) {
flashImage[i] = 4*flashImage[i] + address;
} else {
flashImage[i] |= last<<16;
last = i;
}
}
}
}
uint dumpToFlashImage (lua_State* L, const Proto *main, lua_Writer w, uint dumpToFlashImage (lua_State* L, const Proto *main, lua_Writer w,
void* data, int strip, lu_int32 address) { void* data, int strip,
lu_int32 address, lu_int32 maxSize) {
// parameter strip is ignored for now // parameter strip is ignored for now
lua_newtable(L);
FlashHeader *fh = cast(FlashHeader *, flashAlloc(L, sizeof(FlashHeader))); FlashHeader *fh = cast(FlashHeader *, flashAlloc(L, sizeof(FlashHeader)));
int i, status;
lua_newtable(L);
scanProtoStrings(L, main); scanProtoStrings(L, main);
createROstrt(L, fh); createROstrt(L, fh);
toFlashAddr(L, fh->mainProto, functionToFlash(L, main)); toFlashAddr(L, fh->mainProto, functionToFlash(L, main));
fh->flash_sig = FLASH_SIG + (address ? FLASH_SIG_ABSOLUTE : 0); fh->flash_sig = FLASH_SIG + (address ? FLASH_SIG_ABSOLUTE : 0);
fh->flash_size = curOffset*WORDSIZE; fh->flash_size = curOffset*WORDSIZE;
linkAddresses(address); if (fh->flash_size>maxSize) {
lua_unlock(L); fatal ("The image is too large for specfied LFS size");
int status = w(L, flashImage, curOffset * sizeof(uint), data); }
if (address) { /* in absolute mode convert addresses to mapped address */
for (i = 0 ; i < curOffset; i++)
if (getFlashAddrTag(i))
flashImage[i] = 4*flashImage[i] + address;
lua_unlock(L);
status = w(L, flashImage, fh->flash_size, data);
} else { /* compressed PI mode */
/*
* In image mode, shift the relocation bitmap down directly above
* the used flashimage. This consolidated array is then gzipped.
*/
uint oLen;
uint8_t *oBuf;
int bmLen = sizeof(uint)*((curOffset+31)/32); /* 32 flags to a word */
memmove(flashImage+curOffset, flashAddrTag, bmLen);
status = uzlib_compress (&oBuf, &oLen,
(const uint8_t *)flashImage, bmLen+fh->flash_size);
if (status != UZLIB_OK) {
luac_fatal("Out of memory during image compression");
}
lua_unlock(L);
#if 0
status = w(L, flashImage, bmLen+fh->flash_size, data);
#else
status = w(L, oBuf, oLen, data);
free(oBuf);
#endif
}
lua_lock(L); lua_lock(L);
return status; return status;
} }
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lrotable.h"
#define IO_INPUT 1 #define IO_INPUT 1
#define IO_OUTPUT 2 #define IO_OUTPUT 2
...@@ -28,7 +27,11 @@ ...@@ -28,7 +27,11 @@
#define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f])) #define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f]))
/* "Pseudo-random" keys for the registry */ /* "Pseudo-random" keys for the registry */
static const size_t liolib_keys[] = {(size_t)&luaL_callmeta, (size_t)&luaL_typerror, (size_t)&luaL_argerror}; static const size_t liolib_keys[] = {
(size_t)&luaL_callmeta,
(size_t)&luaL_typerror,
(size_t)&luaL_argerror
};
static const char *const fnames[] = {"input", "output"}; static const char *const fnames[] = {"input", "output"};
...@@ -452,20 +455,6 @@ const LUA_REG_TYPE iolib_funcs[] = { ...@@ -452,20 +455,6 @@ const LUA_REG_TYPE iolib_funcs[] = {
{LNILKEY, LNILVAL} {LNILKEY, LNILVAL}
}; };
/* Note that IO objects use a RAM metatable created to allow extensibility */
static int io_index(lua_State *L)
{
return luaR_findfunction(L, iolib_funcs);
}
const luaL_Reg iolib[] = {
{"__index", io_index},
{NULL, NULL}
};
#undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 1
#include "lrodefs.h" #include "lrodefs.h"
const LUA_REG_TYPE flib[] = { const LUA_REG_TYPE flib[] = {
{LSTRKEY("close"), LFUNCVAL(io_close)}, {LSTRKEY("close"), LFUNCVAL(io_close)},
...@@ -481,6 +470,7 @@ const LUA_REG_TYPE flib[] = { ...@@ -481,6 +470,7 @@ const LUA_REG_TYPE flib[] = {
{LNILKEY, LNILVAL} {LNILKEY, LNILVAL}
}; };
static const luaL_Reg io_base[] = {{NULL, NULL}};
static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
*newfile(L) = f; *newfile(L) = f;
...@@ -490,14 +480,18 @@ static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { ...@@ -490,14 +480,18 @@ static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
lua_setfield(L, -2, fname); lua_setfield(L, -2, fname);
} }
LUALIB_API int luaopen_io (lua_State *L) { LUALIB_API int luaopen_io(lua_State *L) {
luaL_rometatable(L, LUA_FILEHANDLE, (void*)flib); /* create metatable for file handles */ luaL_rometatable(L, LUA_FILEHANDLE, (void*) flib); /* create metatable for file handles */
luaL_register_light(L, LUA_IOLIBNAME, iolib); luaL_register_light(L, LUA_IOLIBNAME, io_base);
lua_pushvalue(L, -1); lua_pushvalue(L, -1);
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
lua_pushliteral(L, "__index");
lua_pushrotable(L, (void *)iolib_funcs);
lua_rawset(L, -3);
/* create (and set) default files */ /* create (and set) default files */
createstdfile(L, stdin, IO_INPUT, "stdin"); createstdfile(L, stdin, IO_INPUT, "stdin");
createstdfile(L, stdout, IO_OUTPUT, "stdout"); createstdfile(L, stdout, IO_OUTPUT, "stdout");
createstdfile(L, stderr, 0, "stderr"); createstdfile(L, stderr, IO_STDERR, "stderr");
return 1; return 1;
} }
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lualib.h" #include "lualib.h"
#include "lrotable.h"
static int os_pushresult (lua_State *L, int i, const char *filename) { static int os_pushresult (lua_State *L, int i, const char *filename) {
int en = errno; /* calls to Lua API may change this value */ int en = errno; /* calls to Lua API may change this value */
......
...@@ -35,6 +35,7 @@ static int dumping=1; /* dump bytecodes? */ ...@@ -35,6 +35,7 @@ static int dumping=1; /* dump bytecodes? */
static int stripping=0; /* strip debug information? */ static int stripping=0; /* strip debug information? */
static int flash=0; /* output flash image */ static int flash=0; /* output flash image */
static lu_int32 address=0; /* output flash image at absolute location */ static lu_int32 address=0; /* output flash image at absolute location */
static lu_int32 maxSize=0x40000; /* maximuum uncompressed image size */
static int lookup=0; /* output lookup-style master combination header */ static int lookup=0; /* output lookup-style master combination header */
static char Output[]={ OUTPUT }; /* default output file name */ static char Output[]={ OUTPUT }; /* default output file name */
static const char* output=Output; /* actual output file name */ static const char* output=Output; /* actual output file name */
...@@ -72,6 +73,7 @@ static void usage(const char* message) ...@@ -72,6 +73,7 @@ static void usage(const char* message)
" -f output a flash image file\n" " -f output a flash image file\n"
" -a addr generate an absolute, rather than position independent flash image file\n" " -a addr generate an absolute, rather than position independent flash image file\n"
" -i generate lookup combination master (default with option -f)\n" " -i generate lookup combination master (default with option -f)\n"
" -m size maximum LFS image in bytes\n"
" -p parse only\n" " -p parse only\n"
" -s strip debug information\n" " -s strip debug information\n"
" -v show version information\n" " -v show version information\n"
...@@ -123,6 +125,13 @@ static int doargs(int argc, char* argv[]) ...@@ -123,6 +125,13 @@ static int doargs(int argc, char* argv[])
lookup = 1; lookup = 1;
else if (IS("-l")) /* list */ else if (IS("-l")) /* list */
++listing; ++listing;
else if (IS("-m")) /* specify a maximum image size */
{
flash=lookup=1;
maxSize=strtol(argv[++i],NULL,0);
if (maxSize & 0xFFF)
usage(LUA_QL("-e") " maximum size must be a multiple of 4,096");
}
else if (IS("-o")) /* output file */ else if (IS("-o")) /* output file */
{ {
output=argv[++i]; output=argv[++i];
...@@ -264,7 +273,8 @@ struct Smain { ...@@ -264,7 +273,8 @@ struct Smain {
}; };
extern uint dumpToFlashImage (lua_State* L,const Proto *main, lua_Writer w, extern uint dumpToFlashImage (lua_State* L,const Proto *main, lua_Writer w,
void* data, int strip, lu_int32 address); void* data, int strip,
lu_int32 address, lu_int32 maxSize);
static int pmain(lua_State* L) static int pmain(lua_State* L)
{ {
...@@ -302,7 +312,7 @@ static int pmain(lua_State* L) ...@@ -302,7 +312,7 @@ static int pmain(lua_State* L)
lua_lock(L); lua_lock(L);
if (flash) if (flash)
{ {
result=dumpToFlashImage(L,f,writer, D, stripping, address); result=dumpToFlashImage(L,f,writer, D, stripping, address, maxSize);
} else } else
{ {
result=luaU_dump_crosscompile(L,f,writer,D,stripping,target); result=luaU_dump_crosscompile(L,f,writer,D,stripping,target);
......
...@@ -896,13 +896,6 @@ union luai_Cast { double l_d; long l_l; }; ...@@ -896,13 +896,6 @@ union luai_Cast { double l_d; long l_l; };
** without modifying the main part of the file. ** without modifying the main part of the file.
*/ */
/* If you define the next macro you'll get the ability to set rotables as
metatables for tables/userdata/types (but the VM might run slower)
*/
#if (LUA_OPTIMIZE_MEMORY == 2)
#define LUA_META_ROTABLES
#endif
#if LUA_OPTIMIZE_MEMORY == 2 && defined(LUA_USE_POPEN) #if LUA_OPTIMIZE_MEMORY == 2 && defined(LUA_USE_POPEN)
#error "Pipes not supported in aggresive optimization mode (LUA_OPTIMIZE_MEMORY=2)" #error "Pipes not supported in aggresive optimization mode (LUA_OPTIMIZE_MEMORY=2)"
#endif #endif
......
...@@ -130,18 +130,29 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { ...@@ -130,18 +130,29 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
TValue temp; TValue temp;
for (loop = 0; loop < MAXTAGLOOP; loop++) { for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm; const TValue *tm;
if (ttistable(t) || ttisrotable(t)) { /* `t' is a table? */
void *h = ttistable(t) ? hvalue(t) : rvalue(t); if (ttistable(t)) { /* `t' is a table? */
const TValue *res = ttistable(t) ? luaH_get((Table*)h, key) : luaH_get_ro(h, key); /* do a primitive get */ Table *h = hvalue(t);
const TValue *res = luaH_get(h, key); /* do a primitive get */
if (!ttisnil(res) || /* result is no nil? */ if (!ttisnil(res) || /* result is no nil? */
(tm = fasttm(L, ttistable(t) ? ((Table*)h)->metatable : (Table*)luaR_getmeta(h), TM_INDEX)) == NULL) { /* or no TM? */ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
setobj2s(L, val, res); setobj2s(L, val, res);
return; return;
} }
/* else will try the tag method */
} else if (ttisrotable(t)) { /* `t' is a table? */
void *h = rvalue(t);
const TValue *res = luaH_get_ro(h, key); /* do a primitive get */
if (!ttisnil(res) || /* result is no nil? */
(tm = fasttm(L, (Table*)luaR_getmeta(h), TM_INDEX)) == NULL) { /* or no TM? */
setobj2s(L, val, res);
return;
}
/* else will try the tag method */ /* else will try the tag method */
} }
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
luaG_typeerror(L, t, "index"); luaG_typeerror(L, t, "index");
if (ttisfunction(tm) || ttislightfunction(tm)) { if (ttisfunction(tm) || ttislightfunction(tm)) {
callTMres(L, val, tm, t, key); callTMres(L, val, tm, t, key);
return; return;
...@@ -161,25 +172,27 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { ...@@ -161,25 +172,27 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
L->top++; L->top++;
fixedstack(L); fixedstack(L);
for (loop = 0; loop < MAXTAGLOOP; loop++) { for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm; const TValue *tm = NULL;
if (ttistable(t) || ttisrotable(t)) { /* `t' is a table? */ if (ttistable(t)) { /* `t' is a table? */
void *h = ttistable(t) ? hvalue(t) : rvalue(t); Table *h = hvalue(t);
TValue *oldval = ttistable(t) ? luaH_set(L, (Table*)h, key) : NULL; /* do a primitive set */ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
if ((oldval && !ttisnil(oldval)) || /* result is no nil? */ if ((!ttisnil(oldval)) || /* result is no nil? */
(tm = fasttm(L, ttistable(t) ? ((Table*)h)->metatable : (Table*)luaR_getmeta(h), TM_NEWINDEX)) == NULL) { /* or no TM? */ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) {
if(oldval) { L->top--;
L->top--; unfixedstack(L);
unfixedstack(L); setobj2t(L, oldval, val);
setobj2t(L, oldval, val); ((Table *)h)->flags = 0;
((Table *)h)->flags = 0; luaC_barriert(L, (Table*)h, val);
luaC_barriert(L, (Table*)h, val);
}
return; return;
} }
/* else will try the tag method */ /* else will try the tag method */
} }
else if (ttisrotable(t)) {
luaG_runerror(L, "invalid write to ROM variable");
}
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
luaG_typeerror(L, t, "index"); luaG_typeerror(L, t, "index");
if (ttisfunction(tm) || ttislightfunction(tm)) { if (ttisfunction(tm) || ttislightfunction(tm)) {
L->top--; L->top--;
unfixedstack(L); unfixedstack(L);
...@@ -294,7 +307,7 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { ...@@ -294,7 +307,7 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
case LUA_TROTABLE: case LUA_TROTABLE:
return rvalue(t1) == rvalue(t2); return rvalue(t1) == rvalue(t2);
case LUA_TLIGHTUSERDATA: case LUA_TLIGHTUSERDATA:
case LUA_TLIGHTFUNCTION: case LUA_TLIGHTFUNCTION:
return pvalue(t1) == pvalue(t2); return pvalue(t1) == pvalue(t2);
case LUA_TUSERDATA: { case LUA_TUSERDATA: {
...@@ -321,7 +334,7 @@ void luaV_concat (lua_State *L, int total, int last) { ...@@ -321,7 +334,7 @@ void luaV_concat (lua_State *L, int total, int last) {
if (G(L)->memlimit < max_sizet) max_sizet = G(L)->memlimit; if (G(L)->memlimit < max_sizet) max_sizet = G(L)->memlimit;
do { do {
/* Any call which does a memory allocation may trim the stack, /* Any call which does a memory allocation may trim the stack,
invalidating top unless the stack is fixed duri ng the allocation */ invalidating top unless the stack is fixed during the allocation */
StkId top = L->base + last + 1; StkId top = L->base + last + 1;
fixedstack(L); fixedstack(L);
int n = 2; /* number of elements handled in this pass (at least 2) */ int n = 2; /* number of elements handled in this pass (at least 2) */
...@@ -570,7 +583,7 @@ void luaV_execute (lua_State *L, int nexeccalls) { ...@@ -570,7 +583,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
case OP_LEN: { case OP_LEN: {
const TValue *rb = RB(i); const TValue *rb = RB(i);
switch (ttype(rb)) { switch (ttype(rb)) {
case LUA_TTABLE: case LUA_TTABLE:
case LUA_TROTABLE: { case LUA_TROTABLE: {
setnvalue(ra, ttistable(rb) ? cast_num(luaH_getn(hvalue(rb))) : cast_num(luaH_getn_ro(rvalue(rb)))); setnvalue(ra, ttistable(rb) ? cast_num(luaH_getn(hvalue(rb))) : cast_num(luaH_getn_ro(rvalue(rb))));
break; break;
......
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