diff --git a/include/lstate.h b/include/lstate.h index 93029b4..8aacb74 100644 --- a/include/lstate.h +++ b/include/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.128 2015/11/13 12:16:51 roberto Exp $ +** $Id: lstate.h,v 2.130 2015/12/16 16:39:38 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -33,6 +33,15 @@ struct lua_longjmp; /* defined in ldo.c */ +/* +** Atomic type (relative to signals) to better ensure that 'lua_sethook' +** is thread safe +*/ +#if !defined(l_signalT) +#include +#define l_signalT sig_atomic_t +#endif + /* extra stack space to handle TM calls and some other extras */ #define EXTRA_STACK 5 @@ -171,7 +180,7 @@ struct lua_State { struct lua_State *twups; /* list of threads with open upvalues */ struct lua_longjmp *errorJmp; /* current error recover point */ CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ - lua_Hook hook; + volatile lua_Hook hook; ptrdiff_t errfunc; /* current error handling function (stack index) */ int stacksize; int basehookcount; diff --git a/include/ltests.h b/include/ltests.h index 6aceb16..760dc73 100644 --- a/include/ltests.h +++ b/include/ltests.h @@ -1,5 +1,5 @@ /* -** $Id: ltests.h,v 2.47 2014/12/26 14:44:44 roberto Exp $ +** $Id: ltests.h,v 2.49 2015/09/22 14:18:24 roberto Exp $ ** Internal Header for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ diff --git a/include/lua.h b/include/lua.h index 4937f94..e02ff9f 100644 --- a/include/lua.h +++ b/include/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.329 2015/11/13 17:18:42 roberto Exp $ +** $Id: lua.h,v 1.331 2016/05/30 15:53:28 roberto Exp $ ** Lua - A Scripting Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -19,11 +19,11 @@ #define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MINOR "3" #define LUA_VERSION_NUM 503 -#define LUA_VERSION_RELEASE "2" +#define LUA_VERSION_RELEASE "3" #define LUA_VERSION "Ravi " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE -#define LUA_COPYRIGHT LUA_RELEASE "\nCopyright (C) 1994-2015 Lua.org, PUC-Rio\nPortions Copyright (C) 2015 Dibyendu Majumdar" +#define LUA_COPYRIGHT LUA_RELEASE "\nCopyright (C) 1994-2016 Lua.org, PUC-Rio\nPortions Copyright (C) 2015-2016 Dibyendu Majumdar" #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes, Dibyendu Majumdar" @@ -544,7 +544,7 @@ LUA_API void ravi_set_debuglevel(int level); /****************************************************************************** -* Copyright (C) 1994-2015 Lua.org, PUC-Rio. +* Copyright (C) 1994-2016 Lua.org, PUC-Rio. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/include/lvm.h b/include/lvm.h index d74b1d4..2f898a4 100644 --- a/include/lvm.h +++ b/include/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.39 2015/09/09 13:44:07 roberto Exp $ +** $Id: lvm.h,v 2.40 2016/01/05 16:07:21 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -49,25 +49,24 @@ /* -** fast track for 'gettable': 1 means 'aux' points to resulted value; -** 0 means 'aux' is metamethod (if 't' is a table) or NULL. 'f' is -** the raw get function to use. +** fast track for 'gettable': if 't' is a table and 't[k]' is not nil, +** return 1 with 'slot' pointing to 't[k]' (final result). Otherwise, +** return 0 (meaning it will have to check metamethod) with 'slot' +** pointing to a nil 't[k]' (if 't' is a table) or NULL (otherwise). +** 'f' is the raw get function to use. */ -#define luaV_fastget(L,t,k,aux,f) \ +#define luaV_fastget(L,t,k,slot,f) \ (!ttistable(t) \ - ? (aux = NULL, 0) /* not a table; 'aux' is NULL and result is 0 */ \ - : (aux = f(hvalue(t), k), /* else, do raw access */ \ - !ttisnil(aux) ? 1 /* result not nil? 'aux' has it */ \ - : (aux = fasttm(L, hvalue(t)->metatable, TM_INDEX), /* get metamethod */\ - aux != NULL ? 0 /* has metamethod? must call it */ \ - : (aux = luaO_nilobject, 1)))) /* else, final result is nil */ + ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ + : (slot = f(hvalue(t), k), /* else, do raw access */ \ + !ttisnil(slot))) /* result not nil? */ /* ** standard implementation for 'gettable' */ -#define luaV_fastgettable(L,t,k,v) { const TValue *aux; \ - if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \ - else luaV_finishget(L,t,k,v,aux); } +#define luaV_fastgettable(L,t,k,v) { const TValue *slot; \ + if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \ + else luaV_finishget(L,t,k,v,slot); } /* @@ -105,10 +104,11 @@ LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val); LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, - StkId val, const TValue *tm); + StkId val, const TValue *slot); LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, - StkId val, const TValue *oldval); + StkId val, const TValue *slot); LUAI_FUNC void luaV_finishOp (lua_State *L); +/* The int return value is a Ravi extension */ LUAI_FUNC int luaV_execute (lua_State *L); LUAI_FUNC void luaV_concat (lua_State *L, int total); LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); @@ -116,7 +116,7 @@ LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); -// RAVI changes +/* RAVI changes for JIT */ LUAI_FUNC int luaV_forlimit(const TValue *obj, lua_Integer *p, lua_Integer step, int *stopnow); diff --git a/src/lapi.c b/src/lapi.c index c2b05c8..943176c 100644 --- a/src/lapi.c +++ b/src/lapi.c @@ -1,11 +1,11 @@ /* -** $Id: lapi.c,v 2.257 2015/11/02 18:48:07 roberto Exp $ +** $Id: lapi.c,v 2.259 2016/02/29 14:27:14 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ /* -** Portions Copyright (C) 2015 Dibyendu Majumdar +** Portions Copyright (C) 2015-2016 Dibyendu Majumdar */ @@ -412,9 +412,9 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { return NULL; } lua_lock(L); /* 'luaO_tostring' may create a new string */ + luaO_tostring(L, o); luaC_checkGC(L); o = index2addr(L, idx); /* previous call may reallocate the stack */ - luaO_tostring(L, o); lua_unlock(L); } if (len != NULL) @@ -517,10 +517,10 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { TString *ts; lua_lock(L); - luaC_checkGC(L); ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); setsvalue2s(L, L->top, ts); api_incr_top(L); + luaC_checkGC(L); lua_unlock(L); return getstr(ts); } @@ -532,12 +532,12 @@ LUA_API const char *lua_pushstring (lua_State *L, const char *s) { setnilvalue(L->top); else { TString *ts; - luaC_checkGC(L); ts = luaS_new(L, s); setsvalue2s(L, L->top, ts); s = getstr(ts); /* internal copy's address */ } api_incr_top(L); + luaC_checkGC(L); lua_unlock(L); return s; } @@ -547,8 +547,8 @@ LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, va_list argp) { const char *ret; lua_lock(L); - luaC_checkGC(L); ret = luaO_pushvfstring(L, fmt, argp); + luaC_checkGC(L); lua_unlock(L); return ret; } @@ -558,10 +558,10 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { const char *ret; va_list argp; lua_lock(L); - luaC_checkGC(L); va_start(argp, fmt); ret = luaO_pushvfstring(L, fmt, argp); va_end(argp); + luaC_checkGC(L); lua_unlock(L); return ret; } @@ -578,7 +578,6 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { if (n > MAXUPVAL) luaG_runerror(L, "upvalue index too large"); api_check(L, n <= MAXUPVAL, "upvalue index too large"); - luaC_checkGC(L); cl = luaF_newCclosure(L, n); cl->f = fn; L->top -= n; @@ -589,6 +588,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { setclCvalue(L, L->top, cl); } api_incr_top(L); + luaC_checkGC(L); lua_unlock(L); } @@ -625,16 +625,16 @@ LUA_API int lua_pushthread (lua_State *L) { static int auxgetstr (lua_State *L, const TValue *t, const char *k) { - const TValue *aux; + const TValue *slot; TString *str = luaS_new(L, k); - if (luaV_fastget(L, t, str, aux, luaH_getstr)) { - setobj2s(L, L->top, aux); + if (luaV_fastget(L, t, str, slot, luaH_getstr)) { + setobj2s(L, L->top, slot); api_incr_top(L); } else { setsvalue2s(L, L->top, str); api_incr_top(L); - luaV_finishget(L, t, L->top - 1, L->top - 1, aux); + luaV_finishget(L, t, L->top - 1, L->top - 1, slot); } lua_unlock(L); return ttnov(L->top - 1); @@ -663,20 +663,21 @@ LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { return auxgetstr(L, index2addr(L, idx), k); } -LUA_API int lua_geti(lua_State *L, int idx, lua_Integer n) { + +LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { StkId t; - const TValue *aux; + const TValue *slot; lua_lock(L); t = index2addr(L, idx); if (!ttistable(t) || hvalue(t)->ravi_array.array_type == RAVI_TTABLE) { - if (luaV_fastget(L, t, n, aux, luaH_getint)) { - setobj2s(L, L->top, aux); + if (luaV_fastget(L, t, n, slot, luaH_getint)) { + setobj2s(L, L->top, slot); api_incr_top(L); } else { setivalue(L->top, n); api_incr_top(L); - luaV_finishget(L, t, L->top - 1, L->top - 1, aux); + luaV_finishget(L, t, L->top - 1, L->top - 1, slot); } } else { @@ -741,7 +742,8 @@ LUA_API int lua_rawget(lua_State *L, int idx) { return ttnov(L->top - 1); } -LUA_API int lua_rawgeti(lua_State *L, int idx, lua_Integer n) { + +LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { StkId t; Table *h; lua_lock(L); @@ -768,6 +770,7 @@ LUA_API int lua_rawgeti(lua_State *L, int idx, lua_Integer n) { return ttnov(L->top - 1); } + LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { StkId t; TValue k; @@ -788,12 +791,12 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { Table *t; lua_lock(L); - luaC_checkGC(L); t = luaH_new(L); sethvalue(L, L->top, t); api_incr_top(L); if (narray > 0 || nrec > 0) luaH_resize(L, t, narray, nrec); + luaC_checkGC(L); lua_unlock(L); } @@ -804,10 +807,10 @@ LUA_API void ravi_create_integer_array(lua_State *L, int narray, lua_Integer initial_value) { Table *t; lua_lock(L); - luaC_checkGC(L); t = raviH_new_integer_array(L, (unsigned int)narray, initial_value); sethvalue(L, L->top, t); api_incr_top(L); + luaC_checkGC(L); lua_unlock(L); } @@ -818,10 +821,10 @@ LUA_API void ravi_create_number_array(lua_State *L, int narray, lua_Number initial_value) { Table *t; lua_lock(L); - luaC_checkGC(L); t = raviH_new_number_array(L, (unsigned int)narray, initial_value); sethvalue(L, L->top, t); api_incr_top(L); + luaC_checkGC(L); lua_unlock(L); } @@ -872,7 +875,6 @@ LUA_API void ravi_create_slice(lua_State *L, int idx, unsigned int start, Table *slice; const char *errmsg = NULL; lua_lock(L); - luaC_checkGC(L); /* The do-while loop here is just for error handling */ parent = index2addr(L, idx); if (!ttistable(parent)) { @@ -891,6 +893,7 @@ LUA_API void ravi_create_slice(lua_State *L, int idx, unsigned int start, slice = raviH_new_slice(L, parent, start, len); sethvalue(L, L->top, slice); api_incr_top(L); + luaC_checkGC(L); done: lua_unlock(L); if (errmsg) @@ -944,15 +947,15 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) { ** t[k] = value at the top of the stack (where 'k' is a string) */ static void auxsetstr (lua_State *L, const TValue *t, const char *k) { - const TValue *aux; + const TValue *slot; TString *str = luaS_new(L, k); api_checknelems(L, 1); - if (luaV_fastset(L, t, str, aux, luaH_getstr, L->top - 1)) + if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1)) L->top--; /* pop value */ else { setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ api_incr_top(L); - luaV_finishset(L, t, L->top - 1, L->top - 2, aux); + luaV_finishset(L, t, L->top - 1, L->top - 2, slot); L->top -= 2; /* pop value and key */ } lua_unlock(L); /* lock done by caller */ @@ -984,17 +987,17 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { LUA_API void lua_seti(lua_State *L, int idx, lua_Integer n) { StkId t; - const TValue *aux; + const TValue *slot; lua_lock(L); api_checknelems(L, 1); t = index2addr(L, idx); if (!ttistable(t) || hvalue(t)->ravi_array.array_type == RAVI_TTABLE) { - if (luaV_fastset(L, t, n, aux, luaH_getint, L->top - 1)) + if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1)) L->top--; /* pop value */ else { setivalue(L->top, n); api_incr_top(L); - luaV_finishset(L, t, L->top - 1, L->top - 2, aux); + luaV_finishset(L, t, L->top - 1, L->top - 2, slot); L->top -= 2; /* pop value and key */ } } @@ -1030,6 +1033,7 @@ LUA_API void lua_seti(lua_State *L, int idx, lua_Integer n) { LUA_API void lua_rawset(lua_State *L, int idx) { StkId o; + TValue *slot; Table *t; lua_lock(L); api_checknelems(L, 2); @@ -1037,7 +1041,8 @@ LUA_API void lua_rawset(lua_State *L, int idx) { api_check(L, ttistable(o), "table expected"); t = hvalue(o); if (t->ravi_array.array_type == RAVI_TTABLE) { - setobj2t(L, luaH_set(L, t, L->top - 2), L->top - 1); + slot = luaH_set(L, t, L->top - 2); + setobj2t(L, slot, L->top - 1); invalidateTMcache(t); luaC_barrierback(L, t, L->top - 1); } @@ -1122,7 +1127,7 @@ LUA_API void lua_rawseti(lua_State *L, int idx, lua_Integer n) { LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { StkId o; Table *t; - TValue k; + TValue k, *slot; lua_lock(L); api_checknelems(L, 1); o = index2addr(L, idx); @@ -1130,7 +1135,8 @@ LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { t = hvalue(o); api_check(L, t->ravi_array.array_type == RAVI_TTABLE, "Lua table expected"); setpvalue(&k, cast(void *, p)); - setobj2t(L, luaH_set(L, t, &k), L->top - 1); + slot = luaH_set(L, t, &k); + setobj2t(L, slot, L->top - 1); luaC_barrierback(L, t, L->top - 1); L->top--; lua_unlock(L); @@ -1437,7 +1443,6 @@ LUA_API void lua_concat (lua_State *L, int n) { lua_lock(L); api_checknelems(L, n); if (n >= 2) { - luaC_checkGC(L); luaV_concat(L, n); } else if (n == 0) { /* push empty string */ @@ -1445,6 +1450,7 @@ LUA_API void lua_concat (lua_State *L, int n) { api_incr_top(L); } /* else n == 1; nothing to do */ + luaC_checkGC(L); lua_unlock(L); } @@ -1480,10 +1486,10 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { LUA_API void *lua_newuserdata (lua_State *L, size_t size) { Udata *u; lua_lock(L); - luaC_checkGC(L); u = luaS_newudata(L, size); setuvalue(L, L->top, u); api_incr_top(L); + luaC_checkGC(L); lua_unlock(L); return getudatamem(u); } diff --git a/src/lauxlib.c b/src/lauxlib.c index b1de175..b9427f5 100644 --- a/src/lauxlib.c +++ b/src/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.284 2015/11/19 19:16:22 roberto Exp $ +** $Id: lauxlib.c,v 1.286 2016/01/08 15:33:09 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -17,7 +17,8 @@ #include -/* This file uses only the official API of Lua. +/* +** This file uses only the official API of Lua. ** Any function declared here could be written as an application function. */ @@ -198,6 +199,10 @@ static void tag_error (lua_State *L, int arg, int tag) { } +/* +** The use of 'lua_pushfstring' ensures this function does not +** need reserved stack space when called. +*/ LUALIB_API void luaL_where (lua_State *L, int level) { lua_Debug ar; if (lua_getstack(L, level, &ar)) { /* check function at level */ @@ -207,10 +212,15 @@ LUALIB_API void luaL_where (lua_State *L, int level) { return; } } - lua_pushliteral(L, ""); /* else, no information available... */ + lua_pushfstring(L, ""); /* else, no information available... */ } +/* +** Again, the use of 'lua_pushvfstring' ensures this function does +** not need reserved stack space when called. (At worst, it generates +** an error with "stack overflow" instead of the given message.) +*/ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); @@ -349,10 +359,15 @@ LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def, } +/* +** Ensures the stack has at least 'space' extra slots, raising an error +** if it cannot fulfill the request. (The error handling needs a few +** extra slots to format the error message. In case of an error without +** this extra space, Lua will generate the same 'stack overflow' error, +** but without 'msg'.) +*/ LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { - /* keep some extra space to run error routines, if needed */ - const int extra = LUA_MINSTACK; - if (!lua_checkstack(L, space + extra)) { + if (!lua_checkstack(L, space)) { if (msg) luaL_error(L, "stack overflow (%s)", msg); else @@ -678,7 +693,7 @@ static int skipcomment (LoadF *lf, int *cp) { if (c == '#') { /* first line is a comment (Unix exec. file)? */ do { /* skip first line */ c = getc(lf->f); - } while (c != EOF && c != '\n') ; + } while (c != EOF && c != '\n'); *cp = getc(lf->f); /* skip end-of-line, if present */ return 1; /* there was a comment */ } diff --git a/src/lbaselib.c b/src/lbaselib.c index 93450bf..4f59788 100644 --- a/src/lbaselib.c +++ b/src/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.312 2015/10/29 15:21:04 roberto Exp $ +** $Id: lbaselib.c,v 1.313 2016/04/11 19:18:40 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ @@ -102,8 +102,8 @@ static int luaB_tonumber (lua_State *L) { static int luaB_error (lua_State *L) { int level = (int)luaL_optinteger(L, 2, 1); lua_settop(L, 1); - if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ - luaL_where(L, level); + if (lua_type(L, 1) == LUA_TSTRING && level > 0) { + luaL_where(L, level); /* add extra information */ lua_pushvalue(L, 1); lua_concat(L, 2); } diff --git a/src/lcorolib.c b/src/lcorolib.c index 0c0b7fa..2303429 100644 --- a/src/lcorolib.c +++ b/src/lcorolib.c @@ -1,5 +1,5 @@ /* -** $Id: lcorolib.c,v 1.9 2014/11/02 19:19:04 roberto Exp $ +** $Id: lcorolib.c,v 1.10 2016/04/11 19:19:55 roberto Exp $ ** Coroutine Library ** See Copyright Notice in lua.h */ @@ -75,7 +75,7 @@ static int luaB_auxwrap (lua_State *L) { lua_State *co = lua_tothread(L, lua_upvalueindex(1)); int r = auxresume(L, co, lua_gettop(L)); if (r < 0) { - if (lua_isstring(L, -1)) { /* error object is a string? */ + if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */ luaL_where(L, 1); /* add extra info */ lua_insert(L, -2); lua_concat(L, 2); diff --git a/src/ldebug.c b/src/ldebug.c index c751712..18ea101 100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.117 2015/11/02 18:48:07 roberto Exp $ +** $Id: ldebug.c,v 2.120 2016/03/31 19:01:21 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ diff --git a/src/ldo.c b/src/ldo.c index b6e91f8..169b6ba 100644 --- a/src/ldo.c +++ b/src/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.150 2015/11/19 19:16:22 roberto Exp $ +** $Id: ldo.c,v 2.151 2015/12/16 16:40:07 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ diff --git a/src/lvm.c b/src/lvm.c index c620f37..10b6d05 100644 --- a/src/lvm.c +++ b/src/lvm.c @@ -1,11 +1,11 @@ /* -** $Id: lvm.c,v 2.265 2015/11/23 11:30:45 roberto Exp $ +** $Id: lvm.c,v 2.268 2016/02/05 19:59:14 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ /* -** Portions Copyright (C) 2015 Dibyendu Majumdar +** Portions Copyright (C) 2015-2016 Dibyendu Majumdar */ @@ -166,55 +166,67 @@ int luaV_forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, /* -** Complete a table access: if 't' is a table, 'tm' has its metamethod; -** otherwise, 'tm' is NULL. +** Finish the table access 'val = t[key]'. +** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to +** t[k] entry (which must be nil). */ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, - const TValue *tm) { + const TValue *slot) { int loop; /* counter to avoid infinite loops */ - lua_assert(tm != NULL || !ttistable(t)); + const TValue *tm; /* metamethod */ for (loop = 0; loop < MAXTAGLOOP; loop++) { - if (tm == NULL) { /* no metamethod (from a table)? */ - if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) + if (slot == NULL) { /* 't' is not a table? */ + lua_assert(!ttistable(t)); + tm = luaT_gettmbyobj(L, t, TM_INDEX); + if (ttisnil(tm)) luaG_typeerror(L, t, "index"); /* no metamethod */ + /* else will try the metamethod */ + } + else { /* 't' is a table */ + lua_assert(ttisnil(slot)); + tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ + if (tm == NULL) { /* no metamethod? */ + setnilvalue(val); /* result is nil */ + return; + } + /* else will try the metamethod */ } - if (ttisfunction(tm)) { /* metamethod is a function */ + if (ttisfunction(tm)) { /* is metamethod a function? */ luaT_callTM(L, tm, t, key, val, 1); /* call it */ return; } - t = tm; /* else repeat access over 'tm' */ - if (luaV_fastget(L,t,key,tm,luaH_get)) { /* try fast track */ - setobj2s(L, val, tm); /* done */ + t = tm; /* else try to access 'tm[key]' */ + if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */ + setobj2s(L, val, slot); /* done */ return; } - /* else repeat */ + /* else repeat (tail call 'luaV_finishget') */ } - luaG_runerror(L, "gettable chain too long; possible loop"); + luaG_runerror(L, "'__index' chain too long; possible loop"); } /* -** Main function for table assignment (invoking metamethods if needed). -** Compute 't[key] = val' +** Finish a table assignment 't[key] = val'. +** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points +** to the entry 't[key]', or to 'luaO_nilobject' if there is no such +** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastset' +** would have done the job.) */ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, - StkId val, const TValue *oldval) { + StkId val, const TValue *slot) { int loop; /* counter to avoid infinite loops */ for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (oldval != NULL) { - lua_assert(ttistable(t) && ttisnil(oldval)); + const TValue *tm; /* '__newindex' metamethod */ + if (slot != NULL) { /* is 't' a table? */ Table *h = hvalue(t); /* save 't' table */ - lua_assert(ttisnil(oldval)); - /* must check the metamethod */ - if ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && - /* no metamethod; is there a previous entry in the table? */ - (oldval != luaO_nilobject || - /* no previous entry; must create one. (The next test is - always true; we only need the assignment.) */ - (oldval = luaH_newkey(L, h, key), 1))) { + lua_assert(ttisnil(slot)); /* old value must be nil */ + tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ + if (tm == NULL) { /* no metamethod? */ + if (slot == luaO_nilobject) /* no previous entry? */ + slot = luaH_newkey(L, h, key); /* create one */ /* no metamethod and (now) there is an entry with given key */ - setobj2t(L, cast(TValue *, oldval), val); + setobj2t(L, cast(TValue *, slot), val); /* set its new value */ invalidateTMcache(h); luaC_barrierback(L, h, val); return; @@ -231,7 +243,7 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, return; } t = tm; /* else repeat assignment over 'tm' */ - if (luaV_fastset(L, t, key, oldval, luaH_get, val)) + if (luaV_fastset(L, t, key, slot, luaH_get, val)) return; /* done */ /* else loop */ } @@ -854,12 +866,12 @@ void luaV_finishOp (lua_State *L) { /* -** copy of 'luaV_gettable', but protecting call to potential metamethod -** (which can reallocate the stack) +** copy of 'luaV_gettable', but protecting the call to potential +** metamethod (which can reallocate the stack) */ -#define gettableProtected(L,t,k,v) { const TValue *aux; \ - if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \ - else Protect(luaV_finishget(L,t,k,v,aux)); } +#define gettableProtected(L,t,k,v) { const TValue *slot; \ + if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \ + else Protect(luaV_finishget(L,t,k,v,slot)); } /* same for 'luaV_settable' */