Commit dba57fa0 authored by Johny Mattsson's avatar Johny Mattsson
Browse files

Merge branch 'dev-esp32-idf4-lua53' into dev-esp32-idf4

parents 3a6961cc 8e5ce49d
/*
** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
#define lnodemcu_c
#define LUA_CORE
#include "lua.h"
#include <string.h>
#include "lobject.h"
#include "lstate.h"
#include "lauxlib.h"
#include "lgc.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lnodemcu.h"
//== NodeMCU lauxlib.h API extensions ========================================//
#ifdef LUA_USE_ESP
#include "task/task.h"
#include "platform.h"
/*
** Error Reporting Task. We can't pass a string parameter to the error reporter
** directly through the task interface the call is wrapped in a C closure with
** the error string as an Upval and this is posted to call the Lua reporter.
*/
static int errhandler_aux (lua_State *L) {
lua_getfield(L, LUA_REGISTRYINDEX, "onerror");
if (!lua_isfunction(L, -1)) {
lua_pop(L, 1);
lua_getglobal(L, "print");
}
lua_pushvalue(L, lua_upvalueindex(1));
lua_call(L, 1, 0); /* Using an error handler would cause an infinite loop! */
return 0;
}
/*
** Error handler for luaL_pcallx(), called from the lua_pcall() with a single
** argument -- the thrown error. This plus depth=2 is passed to debug.traceback()
** to convert into an error message which it handles in a separate posted task.
*/
static int errhandler (lua_State *L) {
lua_getglobal(L, "debug");
lua_getfield(L, -1, "traceback");
if (lua_isfunction(L, -1)) {
lua_insert(L, 1); /* insert tracback function above error */
lua_pop(L, 1); /* dump the debug table entry */
lua_pushinteger(L, 2); /* skip this function and traceback */
lua_call(L, 2, 1); /* call debug.traceback and return it as a string */
lua_pushcclosure(L, errhandler_aux, 1); /* report with str as upval */
luaL_posttask(L, LUA_TASK_HIGH);
}
return 0;
}
/*
** Use in CBs and other C functions to call a Lua function. This includes
** an error handler which will catch any error and then post this to the
** registered reporter function as a separate follow-on task.
*/
LUALIB_API int luaL_pcallx (lua_State *L, int narg, int nres) { // [-narg, +0, v]
int status;
int base = lua_gettop(L) - narg;
lua_pushcfunction(L, errhandler);
lua_insert(L, base); /* put under args */
status = lua_pcall(L, narg, nres, base);
lua_remove(L, base); /* remove traceback function */
if (status != LUA_OK && status != LUA_ERRRUN) {
lua_gc(L, LUA_GCCOLLECT, 0); /* call onerror directly if handler failed */
lua_pushliteral(L, "out of memory");
lua_pushcclosure(L, errhandler_aux, 1); /* report EOM as upval */
luaL_posttask(L, LUA_TASK_HIGH);
}
return status;
}
static task_handle_t task_handle = 0;
/*
** Task callback handler. Uses luaN_call to do a protected call with full traceback
*/
static void do_task (task_param_t task_fn_ref, task_prio_t prio) {
lua_State* L = lua_getstate();
if (prio < 0|| prio > 2)
luaL_error(L, "invalid posk task");
/* Pop the CB func from the Reg */
//dbg_printf("calling Reg[%u]\n", task_fn_ref);
lua_rawgeti(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
luaL_checkfunction(L, -1);
luaL_unref(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
lua_pushinteger(L, prio);
luaL_pcallx(L, 1, 0);
}
/*
** Schedule a Lua function for task execution
*/
LUALIB_API int luaL_posttask( lua_State* L, int prio ) { // [-1, +0, -]
if (!task_handle)
task_handle = task_get_id(do_task);
if (!lua_isfunction(L, -1) || prio < LUA_TASK_LOW|| prio > LUA_TASK_HIGH)
luaL_error(L, "invalid posk task");
//void *cl = clvalue(L->top-1);
int task_fn_ref = luaL_ref(L, LUA_REGISTRYINDEX);
//dbg_printf("posting Reg[%u]=%p\n",task_fn_ref,cl);
if(!task_post(prio, task_handle, (task_param_t)task_fn_ref)) {
luaL_unref(L, LUA_REGISTRYINDEX, task_fn_ref);
luaL_error(L, "Task queue overflow. Task not posted");
}
return task_fn_ref;
}
#else
LUALIB_API int luaL_posttask( lua_State* L, int prio ) {
(void)L; (void)prio;
return 0;
} /* Dummy stub on host */
#endif
#ifdef LUA_USE_ESP
/*
* Return an LFS function
*/
LUALIB_API int luaL_pushlfsmodule (lua_State *L) {
if (lua_pushlfsindex(L) == LUA_TNIL) {
lua_remove(L,-2); /* dump the name to balance the stack */
return 0; /* return nil if LFS not loaded */
}
lua_insert(L, -2);
lua_call(L, 1, 1);
if (!lua_isfunction(L, -1)) {
lua_pop(L, 1);
lua_pushnil(L); /* replace DTS by nil */
}
return 1;
}
/*
* Return an array of functions in LFS
*/
LUALIB_API int luaL_pushlfsmodules (lua_State *L) {
if (lua_pushlfsindex(L) == LUA_TNIL)
return 0; /* return nil if LFS not loaded */
lua_call(L, 0, 2);
lua_remove(L, -2); /* remove DTS leaving array */
return 1;
}
/*
* Return the Unix timestamp of the LFS image creation
*/
LUALIB_API int luaL_pushlfsdts (lua_State *L) {
if (lua_pushlfsindex(L) == LUA_TNIL)
return 0; /* return nil if LFS not loaded */
lua_call(L, 0, 1);
return 1;
}
#endif
//== NodeMCU lua.h API extensions ============================================//
LUA_API int lua_freeheap (void) {
#ifdef LUA_USE_HOST
return MAX_INT;
#else
return (int)esp_get_free_heap_size();
#endif
}
#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
LUA_API int lua_pushstringsarray(lua_State *L, int opt) {
stringtable *tb = NULL;
int i, j;
lua_lock(L);
if (opt == 0)
tb = &G(L)->strt;
#ifdef LUA_USE_ESP
else if (opt == 1 && G(L)->ROstrt.hash)
tb = &G(L)->ROstrt;
#endif
if (tb == NULL) {
setnilvalue(L->top);
api_incr_top(L);
lua_unlock(L);
return 0;
}
Table *t = luaH_new(L, tb->nuse, 0);
sethvalue(L, L->top, t);
api_incr_top(L);
luaC_checkGC(L);
lua_unlock(L);
for (i = 0, j = 1; i < tb->size; i++) {
GCObject *o;
for(o = tb->hash[i]; o; o = o->gch.next) {
TValue v;
setsvalue(L, &v, o);
setobj2s(L, luaH_setnum(L, hvalue(L->top-1), j++), &v);
}
}
return 1;
}
LUA_API void lua_createrotable (lua_State *L, ROTable *t, const ROTable_entry *e, ROTable *mt) {
int i, j;
lu_byte flags = ~0;
const char *plast = (char *)"_";
for (i = 0; e[i].key; i++) {
if (e[i].key[0] == '_' && strcmp(e[i].key,plast)) {
plast = e[i].key;
lua_pushstring(L,e[i].key);
for (j=0; j<TM_EQ; j++){
if(rawtsvalue(L->top-1)==G(L)->tmname[i]) {
flags |= cast_byte(1u<<i);
break;
}
}
lua_pop(L,1);
}
}
t->next = (GCObject *)1;
t->tt = LUA_TROTABLE;
t->marked = LROT_MARKED;
t->flags = flags;
t->lsizenode = i;
t->metatable = cast(Table *, mt);
t->entry = cast(ROTable_entry *, e);
}
#ifdef LUA_USE_ESP
#include "lfunc.h"
/* Push the LClosure of the LFS index function */
LUA_API int lua_pushlfsindex (lua_State *L) {
lua_lock(L);
Proto *p = G(L)->ROpvmain;
if (p) {
Closure *cl = luaF_newLclosure(L, 0, hvalue(gt(L)));
cl->l.p = p;
setclvalue(L, L->top, cl);
} else {
setnilvalue(L->top);
}
api_incr_top(L);
lua_unlock(L);
return p ? LUA_TFUNCTION : LUA_TNIL;
}
#endif
/*
* NodeMCU extensions to Lua 5.1 for readonly Flash memory support
*/
#ifndef lnodemcu_h
#define lnodemcu_h
#include "lua.h"
#include "lobject.h"
#include "llimits.h"
#include "ltm.h"
#ifdef LUA_USE_HOST
#define LRO_STRKEY(k) k
#define LOCK_IN_SECTION(s)
#else
#define LRO_STRKEY(k) ((__attribute__((aligned(4))) const char *) k)
#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".lua_" #s)))
#endif
/* Macros used to declare rotable entries */
#define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION}
#define LRO_LUDATA(v) {{.p = cast(void*,v)}, LUA_TLIGHTUSERDATA}
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
#define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
#define LRO_INTVAL(v) LRO_NUMVAL(v)
#define LRO_FLOATVAL(v) LRO_NUMVAL(v)
#define LRO_ROVAL(v) {{.gc = cast(GCObject *, &(v ## _ROTable))}, LUA_TROTABLE}
#define LROT_MARKED 0 //<<<<<<<<<< *** TBD *** >>>>>>>>>>>
#define LROT_FUNCENTRY(n,f) {LRO_STRKEY(#n), LRO_FUNCVAL(f)},
#define LROT_LUDENTRY(n,x) {LRO_STRKEY(#n), LRO_LUDATA(x)},
#define LROT_NUMENTRY(n,x) {LRO_STRKEY(#n), LRO_NUMVAL(x)},
#define LROT_INTENTRY(n,x) LROT_NUMENTRY(n,x)
#define LROT_FLOATENTRY(n,x) LROT_NUMENTRY(n,x)
#define LROT_TABENTRY(n,t) {LRO_STRKEY(#n), LRO_ROVAL(t)},
#define LROT_TABLE(rt) const ROTable rt ## _ROTable
#define LROT_ENTRYREF(rt) (rt ##_entries)
#define LROT_TABLEREF(rt) (&rt ##_ROTable)
#define LROT_BEGIN(rt,mt,f) LROT_TABLE(rt); \
static ROTable_entry rt ## _entries[] = {
#define LROT_ENTRIES_IN_SECTION(rt,s) \
static ROTable_entry LOCK_IN_SECTION(s) rt ## _entries[] = {
#define LROT_END(rt,mt,f) {NULL, LRO_NILVAL} }; \
const ROTable rt ## _ROTable = { \
(GCObject *)1, LUA_TROTABLE, LROT_MARKED, \
cast(lu_byte, ~(f)), (sizeof(rt ## _entries)/sizeof(ROTable_entry)) - 1, \
cast(Table *, mt), cast(ROTable_entry *, rt ## _entries) };
#define LROT_BREAK(rt) };
#define LROT_MASK(m) cast(lu_byte, 1<<TM_ ## m)
/*
* These are statically coded can be any combination of the fast index tags
* listed in ltm.h: EQ, GC, INDEX, LEN, MODE, NEWINDEX or combined by anding
* GC+INDEX is the only common combination used, hence the combinaton macro
*/
#define LROT_MASK_EQ LROT_MASK(EQ)
#define LROT_MASK_GC LROT_MASK(GC)
#define LROT_MASK_INDEX LROT_MASK(INDEX)
#define LROT_MASK_LEN LROT_MASK(LEN)
#define LROT_MASK_MODE LROT_MASK(MODE)
#define LROT_MASK_NEWINDEX LROT_MASK(NEWINDEX)
#define LROT_MASK_GC_INDEX (LROT_MASK_GC | LROT_MASK_INDEX)
#define LUA_MAX_ROTABLE_NAME 32 /* Maximum length of a rotable name and of a string key*/
#ifdef LUA_CORE
#endif
#endif
......@@ -11,7 +11,6 @@
#define loadlib_c
#define LUA_LIB
#define LUAC_CROSS_FILE
#include "lua.h"
#include <stdlib.h>
......@@ -24,7 +23,6 @@
#include "lauxlib.h"
#include "lualib.h"
#include "lrotable.h"
/* prefix for open functions in C libraries */
#define LUA_POF "luaopen_"
......@@ -394,11 +392,7 @@ static int loader_Lua (lua_State *L) {
const char *name = luaL_checkstring(L, 1);
filename = findfile(L, name, "path");
if (filename == NULL) return 1; /* library not found in this path */
#ifdef LUA_CROSS_COMPILER
if (luaL_loadfile(L, filename) != 0)
#else
if (luaL_loadfsfile(L, filename) != 0)
#endif
loaderror(L, filename);
return 1; /* library loaded successfully */
}
......@@ -479,7 +473,7 @@ static int ll_require (lua_State *L) {
}
/* Is this a readonly table? */
lua_getfield(L, LUA_GLOBALSINDEX, name);
if(lua_isrotable(L,-1)) {
if(lua_istable(L,-1)) {
return 1;
} else {
lua_pop(L, 1);
......@@ -572,7 +566,7 @@ static int ll_module (lua_State *L) {
const char *modname = luaL_checkstring(L, 1);
/* Is this a readonly table? */
lua_getfield(L, LUA_GLOBALSINDEX, modname);
if(lua_isrotable(L,-1)) {
if(lua_istable(L,-1)) {
return 0;
} else {
lua_pop(L, 1);
......@@ -658,9 +652,9 @@ static const luaL_Reg ll_funcs[] = {
static const lua_CFunction loaders[] =
{loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
LROT_PUBLIC_BEGIN(lmt)
LROT_FUNCENTRY(__gc,gctm)
LROT_END(lmt,lmt, LROT_MASK_GC)
LROT_BEGIN(lmt, NULL, LROT_MASK_GC)
LROT_FUNCENTRY( __gc, gctm )
LROT_END(lmt, NULL, LROT_MASK_GC)
LUALIB_API int luaopen_package (lua_State *L) {
int i;
......
/*
** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $
** Some generic functions over Lua objects
......@@ -7,7 +8,6 @@
#define lobject_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <stdio.h>
......@@ -25,7 +25,6 @@
#else
#include <limits.h>
#endif
const TValue luaO_nilobject_ = {LUA_TVALUE_NIL};
......@@ -54,7 +53,23 @@ int luaO_fb2int (int x) {
int luaO_log2 (unsigned int x) {
#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,
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,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
};
int l = -1;
while (x >= 256) { l += 8; x >>= 8; }
return l + log_2[x];
#else
return 31 - __builtin_clz(x);
#endif
}
......@@ -70,7 +85,7 @@ int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
case LUA_TLIGHTUSERDATA:
return pvalue(t1) == pvalue(t2);
case LUA_TROTABLE:
return rvalue(t1) == rvalue(t2);
return hvalue(t1) == hvalue(t2);
case LUA_TLIGHTFUNCTION:
return fvalue(t1) == fvalue(t2);
default:
......@@ -85,11 +100,11 @@ int luaO_str2d (const char *s, lua_Number *result) {
*result = lua_str2number(s, &endptr);
if (endptr == s) return 0; /* conversion failed */
if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
#if defined(LUA_CROSS_COMPILER)
#if defined(LUA_CROSS_COMPILER)
{
long lres = strtoul(s, &endptr, 16);
#if LONG_MAX != 2147483647L
if (lres & ~0xffffffffL)
#if INT_MAX != 2147483647L
if (lres & ~0xffffffffL)
*result = cast_num(-1);
else if (lres & 0x80000000L)
*result = cast_num(lres | ~0x7fffffffL);
......
......@@ -17,7 +17,7 @@
/* tags for values visible from Lua */
#define LAST_TAG LUA_TTHREAD
#define NUM_TAGS (LAST_TAG+1)
#define LUA_NUMTAGS (LAST_TAG+1)
#define READONLYMASK (1<<7) /* denormalised bitmask for READONLYBIT and */
#define LFSMASK (1<<6) /* LFSBIT to avoid include proliferation */
......@@ -28,15 +28,18 @@
#define LUA_TUPVAL (LAST_TAG+2)
#define LUA_TDEADKEY (LAST_TAG+3)
#ifdef __XTENSA__
#ifdef LUA_USE_ESP8266
/*
** force aligned access to critical fields in Flash-based structures
** wo is the offset of aligned word in bytes 0,4,8,..
** bo is the field within the word in bits 0..31
**
** Note that this returns a lu_int32 as returning a byte can cause the
** gcc code generator to emit an extra extui instruction.
*/
#define GET_BYTE_FN(name,t,wo,bo) \
static inline lu_byte get ## name(void *o) { \
lu_byte res; /* extract named field */ \
static inline lu_int32 get ## name(void *o) { \
lu_int32 res; /* extract named field */ \
asm ("l32i %0, %1, " #wo "; extui %0, %0, " #bo ", 8;" : "=r"(res) : "r"(o) : );\
return res; }
#else
......@@ -49,14 +52,12 @@ static inline lu_byte get ## name(void *o) { return ((t *)o)->name; }
*/
typedef union GCObject GCObject;
/*
** Common Header for all collectable objects (in macro form, to be
** included in other objects)
*/
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
/*
** Common header in struct form
*/
......@@ -93,43 +94,47 @@ typedef union {
#define TValuefields Value value; int tt
#define LUA_TVALUE_NIL {NULL}, LUA_TNIL
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
#pragma pack(4)
#ifdef LUA_USE_ESP
# pragma pack(4)
#endif
typedef struct lua_TValue {
TValuefields;
} TValue;
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
#pragma pack()
#ifdef LUA_USE_ESP
# pragma pack()
#endif
/* Macros to test type */
#define ttisnil(o) (ttype(o) == LUA_TNIL)
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
#define ttisstring(o) (ttype(o) == LUA_TSTRING)
#define ttistable(o) (ttype(o) == LUA_TTABLE)
#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
#define ttisrotable(o) (ttype(o) == LUA_TROTABLE)
#define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION)
#define ttisnil(o) (ttype(o) == LUA_TNIL)
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
#define ttisstring(o) (ttype(o) == LUA_TSTRING)
#define ttistable(o) (ttnov(o) == LUA_TTABLE)
#define ttisrwtable(o) (type(o) == LUA_TTABLE)
#define ttisrotable(o) (ttype(o) & LUA_TISROTABLE)
#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
#define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION)
#define ttisclfunction(o) (ttype(o) == LUA_TFUNCTION)
#define ttisfunction(o) (ttnov(o) == LUA_TFUNCTION)
/* Macros to access values */
#define ttype(o) ((void) (o)->value, (o)->tt)
#define ttnov(o) ((void) (o)->value, ((o)->tt & LUA_TMASK))
#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
#define rvalue(o) check_exp(ttisrotable(o), (o)->value.p)
#define fvalue(o) check_exp(ttislightfunction(o), (o)->value.p)
#define fvalue(o) check_exp(ttislightfunction(o), (o)->value.p)
#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
#define tsvalue(o) (&rawtsvalue(o)->tsv)
#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
#define uvalue(o) (&rawuvalue(o)->uv)
#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl)
#define clvalue(o) check_exp(ttisclfunction(o), &(o)->value.gc->cl)
#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
......@@ -156,9 +161,6 @@ typedef struct lua_TValue {
#define setpvalue(obj,x) \
{ void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TLIGHTUSERDATA; }
#define setrvalue(obj,x) \
{ void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TROTABLE; }
#define setfvalue(obj,x) \
{ void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TLIGHTFUNCTION; }
......@@ -192,7 +194,7 @@ typedef struct lua_TValue {
#define sethvalue(L,obj,x) \
{ GCObject *i_x = cast(GCObject *, (x)); \
TValue *i_o=(obj); \
i_o->value.gc=i_x; i_o->tt=LUA_TTABLE; \
i_o->value.gc=i_x; i_o->tt=gettt(x); \
checkliveness(G(L),i_o); }
#define setptvalue(L,obj,x) \
......@@ -227,7 +229,7 @@ typedef struct lua_TValue {
#define setttype(obj, stt) ((void) (obj)->value, (obj)->tt = (stt))
#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
#define iscollectable(o) (ttype(o) >= LUA_TSTRING && ttype(o) <= LUA_TMASK)
typedef TValue *StkId; /* index to stack elements */
......@@ -245,19 +247,10 @@ typedef union TString {
} tsv;
} TString;
#ifdef LUA_CROSS_COMPILER
#define isreadonly(o) (0)
#else
#define isreadonly(o) ((o).marked & READONLYMASK)
#endif
#define ts_isreadonly(ts) isreadonly((ts)->tsv)
#define getstr(ts) (ts_isreadonly(ts) ? \
cast(const char *, *(const char**)((ts) + 1)) : \
cast(const char *, (ts) + 1))
#define getstr(ts) cast(const char *, (ts) + 1)
#define svalue(o) getstr(rawtsvalue(o))
typedef union Udata {
L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
struct {
......@@ -268,7 +261,12 @@ typedef union Udata {
} uv;
} Udata;
#ifdef LUA_CROSS_COMPILER
#define isreadonly(o) (0)
#else
#define isreadonly(o) (getmarked(o) & READONLYMASK)
#endif
#define islfs(o) (getmarked(o) & LFSMASK)
/*
......@@ -279,20 +277,13 @@ typedef struct Proto {
TValue *k; /* constants used by the function */
Instruction *code;
struct Proto **p; /* functions defined inside the function */
#ifdef LUA_OPTIMIZE_DEBUG
unsigned char *packedlineinfo;
#else
int *lineinfo; /* map from opcodes to source lines */
#endif
struct LocVar *locvars; /* information about local variables */
TString **upvalues; /* upvalue names */
TString *source;
int sizeupvalues;
int sizek; /* size of `k' */
int sizecode;
#ifndef LUA_OPTIMIZE_DEBUG
int sizelineinfo;
#endif
int sizep; /* size of `p' */
int sizelocvars;
int linedefined;
......@@ -303,7 +294,6 @@ typedef struct Proto {
lu_byte is_vararg;
lu_byte maxstacksize;
} Proto;
#define proto_isreadonly(p) isreadonly(*(p))
/* masks for new-style vararg */
......@@ -373,6 +363,18 @@ typedef union Closure {
** Tables
*/
/*
** Common Table fields for both table versions (like CommonHeader in
** macro form, to be included in table structure definitions).
**
** Note that the sethvalue() macro works much like the setsvalue()
** macro and handles the abstracted type. the hvalue(o) macro can be
** used to access CommonTable fields and rw Table fields
*/
#define CommonTable CommonHeader; \
lu_byte flags; lu_byte lsizenode; struct Table *metatable
typedef union TKey {
struct {
TValuefields;
......@@ -390,10 +392,7 @@ typedef struct Node {
typedef struct Table {
CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of `node' array */
struct Table *metatable;
CommonTable;
TValue *array; /* array part */
Node *node;
Node *lastfree; /* any free position is before this position */
......@@ -401,7 +400,23 @@ typedef struct Table {
int sizearray; /* size of `array' array */
} Table;
typedef const struct luaR_entry ROTable;
GET_BYTE_FN(flags,Table,4,16)
GET_BYTE_FN(lsizenode,Table,4,24)
typedef const struct ROTable_entry {
const char *key;
const TValue value;
} ROTable_entry;
typedef struct ROTable {
/* next always has the value (GCObject *)((size_t) 1); */
/* flags & 1<<p means tagmethod(p) is not present */
/* lsizenode is unused */
/* Like TStrings, the ROTable_entry vector follows the ROTable */
CommonTable;
ROTable_entry *entry;
} ROTable;
/*
** `module' operation for hashing (size is always a power of 2)
......
......@@ -6,9 +6,7 @@
#define lopcodes_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include "lopcodes.h"
/* ORDER OP */
......
......@@ -186,8 +186,8 @@ OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
......@@ -197,8 +197,8 @@ OP_FORLOOP,/* A sBx R(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
......@@ -240,7 +240,7 @@ OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
** bits 4-5: B arg mode
** bit 6: instruction set register A
** bit 7: operator is a test
*/
*/
enum OpArgMask {
OpArgN, /* argument is not used */
......
......@@ -7,7 +7,6 @@
#define lparser_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <string.h>
......@@ -344,12 +343,10 @@ static void open_func (LexState *ls, FuncState *fs) {
fs->bl = NULL;
f->source = ls->source;
f->maxstacksize = 2; /* registers 0/1 are always valid */
#ifdef LUA_OPTIMIZE_DEBUG
fs->packedlineinfoSize = 0;
fs->lastline = 0;
fs->lastlineOffset = 0;
fs->lineinfoLastPC = -1;
#endif
fs->h = luaH_new(L, 0, 0);
/* anchor table of constants and prototype (to avoid being collected) */
sethvalue2s(L, L->top, fs->h);
......@@ -367,15 +364,9 @@ static void close_func (LexState *ls) {
luaK_ret(fs, 0, 0); /* final return */
luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
f->sizecode = fs->pc;
#ifdef LUA_OPTIMIZE_DEBUG
f->packedlineinfo[fs->lastlineOffset+1]=0;
luaM_reallocvector(L, f->packedlineinfo, fs->packedlineinfoSize,
fs->lastlineOffset+2, unsigned char);
#else
luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
f->sizelineinfo = fs->pc;
#endif
luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);
f->sizek = fs->nk;
luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
......@@ -392,20 +383,11 @@ static void close_func (LexState *ls) {
L->top -= 2; /* remove table and prototype from the stack */
}
#ifdef LUA_OPTIMIZE_DEBUG
static void compile_stripdebug(lua_State *L, Proto *f) {
int level;
lua_pushlightuserdata(L, &luaG_stripdebug );
lua_gettable(L, LUA_REGISTRYINDEX);
level = lua_isnil(L, -1) ? LUA_OPTIMIZE_DEBUG : lua_tointeger(L, -1);
lua_pop(L, 1);
if (level > 1) {
int len = luaG_stripdebug(L, f, level, 1);
UNUSED(len);
}
int level = G(L)->stripdefault;
if (level > 0)
luaG_stripdebug(L, f, level, 1);
}
#endif
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
......@@ -422,9 +404,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
chunk(&lexstate);
check(&lexstate, TK_EOS);
close_func(&lexstate);
#ifdef LUA_OPTIMIZE_DEBUG
compile_stripdebug(L, funcstate.f);
#endif
L->top--; /* remove 'name' from stack */
lua_assert(funcstate.prev == NULL);
lua_assert(funcstate.f->nups == 0);
......
......@@ -72,12 +72,10 @@ typedef struct FuncState {
lu_byte nactvar; /* number of active local variables */
upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */
unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */
#ifdef LUA_OPTIMIZE_DEBUG
int packedlineinfoSize; /* only used during compilation for line info */
int lastline; /* ditto */
int lastlineOffset; /* ditto */
int lineinfoLastPC; /* ditto */
#endif
} FuncState;
......
......@@ -7,7 +7,6 @@
#define lstate_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
......@@ -35,7 +34,7 @@ typedef struct LG {
lua_State l;
global_State g;
} LG;
static void stack_init (lua_State *L1, lua_State *L) {
......@@ -185,6 +184,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->memlimit = 0;
g->gcpause = LUAI_GCPAUSE;
g->gcstepmul = LUAI_GCMUL;
g->stripdefault = CONFIG_LUA_OPTIMIZE_DEBUG;
g->gcdept = 0;
#ifdef EGC_INITIAL_MODE
g->egcmode = EGC_INITIAL_MODE;
......@@ -197,13 +197,14 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->memlimit = 0;
#endif
#ifndef LUA_CROSS_COMPILER
g->ROstrt.size = 0;
g->ROstrt.nuse = 0;
g->ROstrt.hash = NULL;
g->ROpvmain = NULL;
g->LFSsize = 0;
g->ROstrt.size = 0;
g->ROstrt.nuse = 0;
g->ROstrt.hash = NULL;
g->ROpvmain = NULL;
g->LFSsize = 0;
g->error_reporter = 0;
#endif
for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
for (i=0; i<LUA_NUMTAGS; i++) g->mt[i] = NULL;
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
/* memory allocation error: free partial state */
close_state(L);
......@@ -225,20 +226,17 @@ extern lua_State *luaL_newstate (void);
static lua_State *lua_crtstate;
lua_State *lua_open(void) {
lua_crtstate = luaL_newstate();
lua_crtstate = luaL_newstate();
return lua_crtstate;
}
lua_State *lua_getstate(void) {
return lua_crtstate;
}
LUA_API void lua_close (lua_State *L) {
#ifndef LUA_CROSS_COMPILER
#ifndef LUA_CROSS_COMPILER
lua_sethook( L, NULL, 0, 0 );
lua_crtstate = NULL;
lua_pushnil( L );
// lua_rawseti( L, LUA_REGISTRYINDEX, LUA_INT_HANDLER_KEY );
#endif
#endif
L = G(L)->mainthread; /* only the main thread can be closed */
lua_lock(L);
luaF_close(L, L->stack); /* close all upvalues for this thread */
......
......@@ -56,7 +56,7 @@ typedef struct CallInfo {
#define curr_func(L) (ttisfunction(L->ci->func) ? clvalue(L->ci->func) : NULL)
#define curr_func(L) (ttisclfunction(L->ci->func) ? clvalue(L->ci->func) : NULL)
#define ci_func(ci) (ttisfunction((ci)->func) ? clvalue((ci)->func) : NULL)
#define f_isLua(ci) (!ttislightfunction((ci)->func) && !ci_func(ci)->c.isC)
#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
......@@ -87,17 +87,19 @@ typedef struct global_State {
lu_mem gcdept; /* how much GC is `behind schedule' */
int gcpause; /* size of pause between successive GCs */
int gcstepmul; /* GC `granularity' */
int stripdefault; /* default stripping level for compilation */
int egcmode; /* emergency garbage collection operation mode */
lua_CFunction panic; /* to be called in unprotected errors */
TValue l_registry;
struct lua_State *mainthread;
UpVal uvhead; /* head of double-linked list of all open upvalues */
struct Table *mt[NUM_TAGS]; /* metatables for basic types */
struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
TString *tmname[TM_N]; /* array with tag-method names */
#ifndef LUA_CROSS_COMPILER
stringtable ROstrt; /* Flash-based hash table for RO strings */
Proto *ROpvmain; /* Flash-based Proto main */
int LFSsize; /* Size of Lua Flash Store */
int error_reporter; /* Registry Index of error reporter task */
#endif
} global_State;
......@@ -159,7 +161,7 @@ union GCObject {
#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
#define gco2u(o) (&rawgco2u(o)->uv)
#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
#define gco2h(o) check_exp(((o)->gch.tt & LUA_TMASK) == LUA_TTABLE, &((o)->h))
#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
#define ngcotouv(o) \
......
......@@ -8,7 +8,6 @@
#define lstring_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <string.h>
......@@ -18,8 +17,6 @@
#include "lstate.h"
#include "lstring.h"
#define LUAS_READONLY_STRING 1
#define LUAS_REGULAR_STRING 0
void luaS_resize (lua_State *L, int newsize) {
stringtable *tb;
......@@ -53,26 +50,20 @@ void luaS_resize (lua_State *L, int newsize) {
}
static TString *newlstr (lua_State *L, const char *str, size_t l,
unsigned int h, int readonly) {
unsigned int h) {
TString *ts;
stringtable *tb;
stringtable *tb = &G(L)->strt;
if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
luaM_toobig(L);
tb = &G(L)->strt;
if ((tb->nuse + 1) > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
luaS_resize(L, tb->size*2); /* too crowded */
ts = cast(TString *, luaM_malloc(L, sizeof(TString) + (readonly ? sizeof(char**) : (l+1)*sizeof(char))));
ts = cast(TString *, luaM_malloc(L, sizeof(TString) + (l+1)*sizeof(char)));
ts->tsv.len = l;
ts->tsv.hash = h;
ts->tsv.marked = luaC_white(G(L));
ts->tsv.tt = LUA_TSTRING;
if (!readonly) {
memcpy(ts+1, str, l*sizeof(char));
((char *)(ts+1))[l] = '\0'; /* ending 0 */
} else {
*(char **)(ts+1) = (char *)str;
l_setbit((ts)->tsv.marked, READONLYBIT);
}
memcpy(ts+1, str, l*sizeof(char));
((char *)(ts+1))[l] = '\0'; /* ending 0 */
h = lmod(h, tb->size);
ts->tsv.next = tb->hash[h]; /* chain new entry */
tb->hash[h] = obj2gco(ts);
......@@ -80,15 +71,6 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
return ts;
}
static int lua_is_ptr_in_ro_area(const char *p) {
#ifdef LUA_CROSS_COMPILER
(void)p;
return 0; // TStrings are never in RO in luac.cross
#else
return IN_RODATA_AREA(p);
#endif
}
/*
* The string algorithm has been modified to be LFS-friendly. The previous eLua
* algo used the address of the string was in flash and the string was >4 bytes
......@@ -129,11 +111,7 @@ LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
}
}
#endif
/* New additions to the RAM strt are tagged as readonly if the string address
* is in the CTEXT segment (target only, not luac.cross) */
int readonly = (lua_is_ptr_in_ro_area(str) && l+1 > sizeof(char**) &&
l == strlen(str) ? LUAS_READONLY_STRING : LUAS_REGULAR_STRING);
return newlstr(L, str, l, h, readonly); /* not found */
return newlstr(L, str, l, h); /* not found */
}
......
......@@ -13,8 +13,7 @@
#include "lstate.h"
#define sizestring(s) (sizeof(union TString)+(testbit(getmarked(s), READONLYBIT) ? sizeof(char **) : ((s)->len+1)*sizeof(char)))
#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char))
#define sizeudata(u) (sizeof(union Udata)+(u)->len)
#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
......
......@@ -7,7 +7,6 @@
#define lstrlib_c
#define LUA_LIB
#define LUAC_CROSS_FILE
#include "lua.h"
#include <stdio.h>
......@@ -15,13 +14,11 @@
#include "lauxlib.h"
#include "lualib.h"
#include "lrotable.h"
/* macro to `unsign' a character */
#define uchar(c) ((unsigned char)(c))
static int str_len (lua_State *L) {
size_t l;
luaL_checklstring(L, 1, &l);
......@@ -143,17 +140,25 @@ static int writer (lua_State *L, const void* b, size_t size, void* B) {
static int str_dump (lua_State *L) {
luaL_Buffer b;
int strip, tstrip = lua_type(L, 2);
if (tstrip == LUA_TBOOLEAN) {
strip = lua_toboolean(L, 2) ? 2 : 0;
} else if (tstrip == LUA_TNONE || tstrip == LUA_TNIL) {
strip = -1; /* This tells lua_dump to use the global strip default */
} else {
strip = lua_tointeger(L, 2);
luaL_argcheck(L, (unsigned)(strip) < 3, 2, "strip out of range");
}
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_settop(L, 1);
luaL_buffinit(L,&b);
if (lua_dump(L, writer, &b) != 0)
luaL_error(L, "unable to dump given function");
if (lua_dump(L, writer, &b, strip) != 0)
return luaL_error(L, "unable to dump given function");
luaL_pushresult(&b);
return 1;
}
/*
** {======================================================
** PATTERN MATCHING
......@@ -634,7 +639,7 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
lua_pushlstring(L, s, e - s); /* keep original text */
}
else if (!lua_isstring(L, -1))
luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
luaL_addvalue(b); /* add result to accumulator */
}
......@@ -787,7 +792,7 @@ static int str_format (lua_State *L) {
sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
break;
}
#if !defined LUA_NUMBER_INTEGRAL
#if !defined LUA_NUMBER_INTEGRAL
case 'e': case 'E': case 'f':
case 'g': case 'G': {
sprintf(buff, form, (double)luaL_checknumber(L, arg));
......@@ -825,7 +830,21 @@ static int str_format (lua_State *L) {
return 1;
}
LROT_PUBLIC_BEGIN(strlib)
static int str_format2 (lua_State *L) {
if (lua_type(L, 2) == LUA_TTABLE) {
int i,n=lua_objlen(L,2);
lua_settop(L,2);
for (i = 1; i <= n; i++)
lua_rawgeti(L, 2, i);
lua_remove(L, 2);
}
return str_format(L);
}
LROT_BEGIN(strlib, NULL, LROT_MASK_INDEX)
LROT_TABENTRY( __index, strlib )
LROT_FUNCENTRY( __mod, str_format2 )
LROT_FUNCENTRY( byte, str_byte )
LROT_FUNCENTRY( char, str_char )
LROT_FUNCENTRY( dump, str_dump )
......@@ -845,8 +864,7 @@ LROT_PUBLIC_BEGIN(strlib)
LROT_FUNCENTRY( reverse, str_reverse )
LROT_FUNCENTRY( sub, str_sub )
LROT_FUNCENTRY( upper, str_upper )
LROT_TABENTRY( __index, strlib )
LROT_END(strlib, NULL, 0) // OR DO WE NEED LRTO_MASK_INDEX **TODO**
LROT_END(strlib, NULL, LROT_MASK_INDEX)
/*
** Open string library
......
......@@ -20,7 +20,6 @@
#define ltable_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <math.h>
......@@ -33,7 +32,8 @@
#include "lobject.h"
#include "lstate.h"
#include "ltable.h"
#include "lrotable.h"
#include "lstring.h"
/*
** max size of array part is 2^MAXBITS
......@@ -48,7 +48,7 @@
#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
#define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
#define hashboolean(t,p) hashpow2(t, p)
......@@ -68,6 +68,10 @@
*/
#define numints cast_int(sizeof(lua_Number)/sizeof(int))
static const TValue* rotable_findentry(ROTable *rotable, TString *key, unsigned *ppos);
static void rotable_next_helper(lua_State *L, ROTable *pentries, int pos,
TValue *key, TValue *val);
static void rotable_next(lua_State *L, ROTable *rotable, TValue *key, TValue *val);
#define dummynode (&dummynode_)
......@@ -105,11 +109,11 @@ static Node *mainposition (const Table *t, const TValue *key) {
return hashstr(t, rawtsvalue(key));
case LUA_TBOOLEAN:
return hashboolean(t, bvalue(key));
case LUA_TROTABLE:
return hashpointer(t, rvalue(key));
case LUA_TLIGHTUSERDATA:
case LUA_TLIGHTFUNCTION:
return hashpointer(t, pvalue(key));
case LUA_TROTABLE:
return hashpointer(t, hvalue(key));
default:
return hashpointer(t, gcvalue(key));
}
......@@ -163,7 +167,12 @@ static int findindex (lua_State *L, Table *t, StkId key) {
int luaH_next (lua_State *L, Table *t, StkId key) {
int i = findindex(L, t, key); /* find original element */
int i;
if (isrotable(t)) {
rotable_next(L, (ROTable *) t, key, key+1);
return ttisnil(key) ? 0 : 1;
}
i = findindex(L, t, key); /* find original element */
for (i++; i < t->sizearray; i++) { /* try first array part */
if (!ttisnil(&t->array[i])) { /* a non-nil value? */
setnvalue(key, cast_num(i+1));
......@@ -182,12 +191,6 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
}
int luaH_next_ro (lua_State *L, void *t, StkId key) {
luaR_next(L, t, key, key+1);
return ttisnil(key) ? 0 : 1;
}
/*
** {=============================================================
** Rehash
......@@ -330,7 +333,7 @@ static Node *find_prev_node(Node *mp, Node *next) {
** first, check whether the moving node's main position is free. If not, check whether
** colliding node is in its main position or not: if it is not, move colliding
** node to an empty place and put moving node in its main position; otherwise
** (colliding node is in its main position), moving node goes to an empty position.
** (colliding node is in its main position), moving node goes to an empty position.
*/
static int move_node (lua_State *L, Table *t, Node *node) {
(void)L;
......@@ -372,7 +375,7 @@ static int move_node (lua_State *L, Table *t, Node *node) {
static int move_number (lua_State *L, Table *t, Node *node) {
(void)L; (void)t;
(void)L;
int key;
lua_Number n = nvalue(key2tval(node));
lua_number2int(key, n);
......@@ -565,6 +568,8 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
** search function for integers
*/
const TValue *luaH_getnum (Table *t, int key) {
if (isrotable(t))
return luaO_nilobject;
/* (1 <= key && key <= t->sizearray) */
if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
return &t->array[key-1];
......@@ -580,18 +585,16 @@ const TValue *luaH_getnum (Table *t, int key) {
}
}
/* same thing for rotables */
const TValue *luaH_getnum_ro (void *t, int key) {
(void)t; (void)key;
const TValue *res = NULL; // integer values not supported: luaR_findentryN(t, key, NULL);
return res ? res : luaO_nilobject;
}
/*
** search function for strings
*/
const TValue *luaH_getstr (Table *t, TString *key) {
if (isrotable(t)) {
if (key->tsv.len>LUA_MAX_ROTABLE_NAME)
return luaO_nilobject;
return rotable_findentry((ROTable*) t, key, NULL);
}
Node *n = hashstr(t, key);
do { /* check whether `key' is somewhere in the chain */
if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)
......@@ -601,65 +604,41 @@ const TValue *luaH_getstr (Table *t, TString *key) {
return luaO_nilobject;
}
/* same thing for rotables */
const TValue *luaH_getstr_ro (void *t, TString *key) {
if (!t || key->tsv.len>LUA_MAX_ROTABLE_NAME)
return luaO_nilobject;
return luaR_findentry(t, key, NULL);
}
/*
** main search function
*/
const TValue *luaH_get (Table *t, const TValue *key) {
switch (ttype(key)) {
case LUA_TNIL: return luaO_nilobject;
case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
case LUA_TNUMBER: {
int k;
lua_Number n = nvalue(key);
lua_number2int(k, n);
if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
return luaH_getnum(t, k); /* use specialized version */
/* else go through */
}
/* fall-through */
default: {
Node *n = mainposition(t, key);
do { /* check whether `key' is somewhere in the chain */
if (luaO_rawequalObj(key2tval(n), key))
return gval(n); /* that's it */
else n = gnext(n);
} while (n);
return luaO_nilobject;
}
}
}
/* same thing for rotables */
const TValue *luaH_get_ro (void *t, const TValue *key) {
switch (ttype(key)) {
case LUA_TNIL: return luaO_nilobject;
case LUA_TSTRING: return luaH_getstr_ro(t, rawtsvalue(key));
case LUA_TNUMBER: {
int k;
lua_Number n = nvalue(key);
lua_number2int(k, n);
if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
return luaH_getnum_ro(t, k); /* use specialized version */
/* else go through */
}
/* fall-through */
default: {
return luaO_nilobject;
}
int type = ttype(key);
if (type == LUA_TNIL)
return luaO_nilobject;
if (type == LUA_TSTRING)
return luaH_getstr(t, rawtsvalue(key));
if (isrotable(t))
return luaO_nilobject;
if (type == LUA_TNUMBER) {
int k;
lua_Number n = nvalue(key);
lua_number2int(k, n);
if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
return luaH_getnum(t, k); /* use specialized version */
}
/* default */
Node *n = mainposition(t, key);
do { /* check whether `key' is somewhere in the chain */
if (luaO_rawequalObj(key2tval(n), key))
return gval(n); /* that's it */
else n = gnext(n);
} while (n);
return luaO_nilobject;
}
TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
const TValue *p = luaH_get(t, key);
const TValue *p;
if (isrotable(t))
luaG_runerror(L, "table is readonly");
p = luaH_get(t, key);
t->flags = 0;
if (p != luaO_nilobject)
return cast(TValue *, p);
......@@ -673,7 +652,10 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
TValue *luaH_setnum (lua_State *L, Table *t, int key) {
const TValue *p = luaH_getnum(t, key);
const TValue *p;
if (isrotable(t))
luaG_runerror(L, "table is readonly");
p = luaH_getnum(t, key);
if (p != luaO_nilobject)
return cast(TValue *, p);
else {
......@@ -685,7 +667,10 @@ TValue *luaH_setnum (lua_State *L, Table *t, int key) {
TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
const TValue *p = luaH_getstr(t, key);
const TValue *p;
if (isrotable(t))
luaG_runerror(L, "table is readonly");
p = luaH_getstr(t, key);
if (p != luaO_nilobject)
return cast(TValue *, p);
else {
......@@ -725,7 +710,10 @@ static int unbound_search (Table *t, unsigned int j) {
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
*/
int luaH_getn (Table *t) {
unsigned int j = t->sizearray;
unsigned int j;
if(isrotable(t))
return 0;
j = t->sizearray;
if (j > 0 && ttisnil(&t->array[j - 1])) {
/* there is a boundary in the array part: (binary) search for it */
unsigned int i = 0;
......@@ -742,14 +730,138 @@ int luaH_getn (Table *t) {
else return unbound_search(t, j);
}
/* same thing for rotables */
int luaH_getn_ro (void *t) {
(void)t;
return 0; // Integer Keys are not currently supported for ROTables
}
int luaH_isdummy (Node *n) { return n == dummynode; }
/*
** All keyed ROTable access passes through rotable_findentry(). ROTables
** are simply a list of <key><TValue value> pairs.
**
** The global KeyCache is used to avoid a relatively expensive Flash memory
** vector scan. A simple hash on the key's TString addr and the ROTable
** addr selects the cache line. The line's slots are then scanned for a
** hit.
**
** Unlike the standard hast which uses a prime line count therefore requires
** the use of modulus operation which is expensive on an IoT processor
** without H/W divide. This hash is power of 2 based which might not be
** quite so uniform but can be calcuated without using H/W-based instructions.
**
** 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 LA_LINES 32
#define LA_SLOTS 4
static size_t cache [LA_LINES][LA_SLOTS];
#define HASH(a,b) ((((29*(size_t)(a)) ^ (37*((b)->tsv.hash)))>>4) % LA_LINES)
#define NDX_SHFT 24
#define ADDR_MASK (((size_t) 1<<24)-1)
/*
* Find a string key entry in a rotable and return it. Note that this internally
* uses a null key to denote a metatable search.
*/
static const TValue* rotable_findentry(ROTable *t, TString *key, unsigned *ppos) {
const ROTable_entry *e = cast(const ROTable_entry *, t->entry);
const int tl = getlsizenode(t);
const char *strkey = getstr(key);
size_t *cl = cache[HASH(t, key)];
int i, j = 1, l;
if (!e || gettt(key) != LUA_TSTRING)
return luaO_nilobject;
l = key->tsv.len;
/* scan the ROTable lookaside cache and return if hit found */
for (i=0; i<LA_SLOTS; i++) {
int cl_ndx = cl[i] >> NDX_SHFT;
if ((((size_t)t - cl[i]) & ADDR_MASK) == 0 && cl_ndx < tl &&
strcmp(e[cl_ndx].key, strkey) == 0) {
if (ppos)
*ppos = cl_ndx;
return &e[cl_ndx].value;
}
}
/*
* A lot of search misses are metavalues, but tables typically only have at
* most a couple of them, so these are always put at the front of the table
* in ascending order and the metavalue scan short circuits using a straight
* strcmp()
*/
lu_int32 name4 = *(lu_int32 *) strkey;
if (*(char*)&name4 == '_') {
for(i = 0; i < tl; i++) {
j = strcmp(e[i].key, strkey);
if (j>=0)
break;
}
} else {
/*
* Ordinary (non-meta) keys can be unsorted. This is for legacy compatiblity,
* plus misses are pretty rare in this case. The masked name4 comparison is
* safe 4-byte comparison that nearly always avoids the more costly strcmp()
* for an actual hit validation.
*/
lu_int32 mask4 = l > 2 ? (~0u) : (~0u)>>((3-l)*8);
for(i = 0; i < tl; i++) {
if (((*(lu_int32 *)e[i].key ^ name4) & mask4) != 0)
continue;
j = strcmp(e[i].key, strkey);
if (j==0)
break;
}
}
if (j)
return luaO_nilobject;
if (ppos)
*ppos = i;
/* In the case of a hit, update the lookaside cache */
for (j = LA_SLOTS-1; j>0; j--)
cl[j] = cl[j-1];
cl[0] = ((size_t)t & ADDR_MASK) + (i << NDX_SHFT);
return &e[i].value;
}
static void rotable_next_helper(lua_State *L, ROTable *t, int pos,
TValue *key, TValue *val) {
const ROTable_entry *e = cast(const ROTable_entry *, t->entry);
if (pos < getlsizenode(t)) {
/* Found an entry */
setsvalue(L, key, luaS_new(L, e[pos].key));
setobj2s(L, val, &e[pos].value);
} else {
setnilvalue(key);
setnilvalue(val);
}
}
/* next (used for iteration) */
static void rotable_next(lua_State *L, ROTable *t, TValue *key, TValue *val) {
unsigned keypos = getlsizenode(t);
/* Special case: if key is nil, return the first element of the rotable */
if (ttisnil(key))
rotable_next_helper(L, t, 0, key, val);
else if (ttisstring(key)) {
/* Find the previous key again */
if (ttisstring(key)) {
rotable_findentry(t, rawtsvalue(key), &keypos);
}
/* Advance to next key */
rotable_next_helper(L, t, ++keypos, key, val);
}
}
#if defined(LUA_DEBUG)
Node *luaH_mainposition (const Table *t, const TValue *key) {
return mainposition(t, key);
......
......@@ -16,26 +16,24 @@
#define gnext(n) ((n)->i_key.nk.next)
#define key2tval(n) (&(n)->i_key.tvk)
#define isrotable(t) (gettt(t)==LUA_TROTABLE)
#define isrwtable(t) (gettt(t)==LUA_TTABLE)
LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
LUAI_FUNC const TValue *luaH_getnum_ro (void *t, int key);
LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
LUAI_FUNC const TValue *luaH_getstr_ro (void *t, TString *key);
LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
LUAI_FUNC const TValue *luaH_get_ro (void *t, const TValue *key);
LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);
LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
LUAI_FUNC void luaH_free (lua_State *L, Table *t);
LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
LUAI_FUNC int luaH_next_ro (lua_State *L, void *t, StkId key);
LUAI_FUNC int luaH_getn (Table *t);
LUAI_FUNC int luaH_getn_ro (void *t);
LUAI_FUNC int luaH_isdummy (Node *n);
#define LUA_MAX_ROTABLE_NAME 32
#if defined(LUA_DEBUG)
LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
#endif
......
......@@ -7,13 +7,11 @@
#define ltablib_c
#define LUA_LIB
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "lrotable.h"
#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))
......@@ -22,7 +20,7 @@
static int foreachi (lua_State *L) {
int i;
int n = aux_getn(L, 1);
luaL_checkanyfunction(L, 2);
luaL_checkfunction(L, 2);
for (i=1; i <= n; i++) {
lua_pushvalue(L, 2); /* function */
lua_pushinteger(L, i); /* 1st argument */
......@@ -38,7 +36,7 @@ static int foreachi (lua_State *L) {
static int foreach (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkanyfunction(L, 2);
luaL_checkfunction(L, 2);
lua_pushnil(L); /* first key */
while (lua_next(L, 1)) {
lua_pushvalue(L, 2); /* function */
......@@ -266,7 +264,7 @@ static int sort (lua_State *L) {
/* }====================================================== */
LROT_PUBLIC_BEGIN(tab_funcs)
LROT_BEGIN(tab_funcs, NULL, 0)
LROT_FUNCENTRY( concat, tconcat )
LROT_FUNCENTRY( foreach, foreach )
LROT_FUNCENTRY( foreachi, foreachi )
......
......@@ -5,37 +5,35 @@
*/
#include <string.h>
#define ltm_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include <string.h>
#include "lobject.h"
#include "lstate.h"
#include "lgc.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lrotable.h"
/* These must be correspond to the LUA_T* defines in lua.h */
const char *const luaT_typenames[] = {
"nil", "boolean", "romtable", "lightfunction", "userdata", "number",
"string", "table", "function", "userdata", "thread",
"nil", "boolean", "lightfunction","number", // base type = 0, 1, 2, 3
"string", "table", "function", "userdata", "thread", // base type = 4, 5, 6, 7, 8
"proto", "upval"
};
void luaT_init (lua_State *L) {
static const char *const luaT_eventname[] = { /* ORDER TM */
"__index", "__newindex",
"__gc", "__mode", "__eq",
"__add", "__sub", "__mul", "__div", "__mod",
"__pow", "__unm", "__len", "__lt", "__le",
"__concat", "__call"
"__concat", "__call",
"__metatable"
};
int i;
for (i=0; i<TM_N; i++) {
......@@ -50,22 +48,14 @@ void luaT_init (lua_State *L) {
** tag methods
*/
const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
const TValue *tm;
const TValue *tm = luaH_getstr(events, ename);
lua_assert(event <= TM_EQ);
if (luaR_isrotable(events)) {
tm = luaH_getstr_ro(events, ename);
if (ttisnil(tm)) { /* no tag method? */
if (isrwtable(events)) /* if this a (RW) Table */
events->flags |= cast_byte(1u<<event); /* then cache this fact */
return NULL;
}
} else {
tm = luaH_getstr(events, ename);
if (ttisnil(tm)) { /* no tag method? */
events->flags |= cast_byte(1u<<event); /* cache this fact */
return NULL;
}
}
return tm;
else return tm;
}
......@@ -73,21 +63,14 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
Table *mt;
switch (ttype(o)) {
case LUA_TTABLE:
mt = hvalue(o)->metatable;
break;
case LUA_TROTABLE:
mt = (Table*)luaR_getmeta(rvalue(o));
mt = hvalue(o)->metatable;
break;
case LUA_TUSERDATA:
mt = uvalue(o)->metatable;
break;
default:
mt = G(L)->mt[ttype(o)];
mt = G(L)->mt[ttnov(o)];
}
if (!mt)
return luaO_nilobject;
else if (luaR_isrotable(mt))
return luaH_getstr_ro(mt, G(L)->tmname[event]);
else
return luaH_getstr(mt, G(L)->tmname[event]);
return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
}
......@@ -7,10 +7,6 @@
#ifndef ltm_h
#define ltm_h
#include "lobject.h"
#include "lrotable.h"
/*
* WARNING: if you change the order of this enumeration,
* grep "ORDER TM"
......@@ -33,13 +29,16 @@ typedef enum {
TM_LE,
TM_CONCAT,
TM_CALL,
TM_METATABLE,
TM_N /* number of elements in the enum */
} TMS;
//#include "lobject.h"
#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
(!luaR_isrotable(et) && ((et)->flags & (1u<<(e)))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
(getflags(et) & (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[];
......
#include "llimits.h"
#include "lauxlib.h"
#include "lualib.h"
#define LUA_VERSION_51
#include "../lua-5.3/lua.c"
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