LUA_API void LUA_rawgetp (LUA_State *L, int idx, const void *p) { StkId t; TValue k; LUA_lock(L); t = index2addr(L, idx); api_check(L, ttistable(t), "table expected"); setpvalue(&k, cast(void *, p)); setobj2s(L, L->top, LUAH_get(hvalue(t), &k)); api_incr_top(L); LUA_unlock(L); }
LUA_API void LUA_callk (LUA_State *L, int nargs, int nresults, int ctx, LUA_CFunction k) { StkId func; LUA_lock(L); api_check(L, k == NULL || !isLUA(L->ci), "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); func = L->top - (nargs+1); if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ L->ci->u.c.k = k; /* save continuation */ L->ci->u.c.ctx = ctx; /* save context */ LUAD_call(L, func, nresults, 1); /* do the call */ } else /* no continuation or no yieldable */ LUAD_call(L, func, nresults, 0); /* just do the call */ adjustresults(L, nresults); LUA_unlock(L); }
LUA_API void LUA_rawseti (LUA_State *L, int idx, int n) { StkId t; LUA_lock(L); api_checknelems(L, 1); t = index2addr(L, idx); api_check(L, ttistable(t), "table expected"); LUAH_setint(L, hvalue(t), n, L->top - 1); LUAC_barrierback(L, gcvalue(t), L->top-1); L->top--; LUA_unlock(L); }
LUA_API void lua_rawset (lua_State *L, int idx) { StkId t; lua_lock(L); api_checknelems(L, 2); t = index2addr(L, idx); api_check(L, ttistable(t), "table expected"); setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); invalidateTMcache(hvalue(t)); luaC_barrierback(L, gcvalue(t), L->top-1); L->top -= 2; lua_unlock(L); }
LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { StkId t; TValue k; lua_lock(L); t = index2addr(L, idx); api_check(ttistable(t), "table expected"); setpvalue(&k, cast(void *, p)); setobj2s(L, L->top, luaH_get(hvalue(t), &k)); api_incr_top(L); lua_unlock(L); return ttnov(L->top - 1); }
LUA_API void lua_getuservalue (lua_State *L, int idx) { StkId o; lua_lock(L); o = index2addr(L, idx); api_check(L, ttisuserdata(o), "userdata expected"); if (uvalue(o)->env) { sethvalue(L, L->top, uvalue(o)->env); } else setnilvalue(L->top); api_incr_top(L); lua_unlock(L); }
LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { StkId t; TValue k; lua_lock(L); api_checknelems(L, 1); t = index2addr(L, idx); api_check(L, ttistable(t), "table expected"); setpvalue(&k, cast(void *, p)); setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1); luaC_barrierback(L, gcvalue(t), L->top - 1); L->top--; lua_unlock(L); }
LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { StkId o; Table *t; lua_lock(L); api_checknelems(L, 1); o = index2addr(L, idx); api_check(ttistable(o), "table expected"); t = hvalue(o); luaH_setint(L, t, n, L->top - 1); luaC_barrierback(L, t, L->top-1); L->top--; lua_unlock(L); }
/* ** Let x = AB, where A is a prefix of length 'n'. Then, ** rotate x n == BA. But BA == (A^r . B^r)^r. */ LUA_API void lua_rotate (lua_State *L, int idx, int n) { StkId p, t, m; lua_lock(L); t = L->top - 1; /* end of stack segment being rotated */ p = index2addr(L, idx); /* start of segment */ api_checkstackindex(idx, p); api_check((n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ reverse(L, p, m); /* reverse the prefix with length 'n' */ reverse(L, m + 1, t); /* reverse the suffix */ reverse(L, p, t); /* reverse the entire segment */ lua_unlock(L); }
LUA_API void lua_rawseti (lua_State *L, int idx, int n) { StkId o; lua_lock(L); api_checknelems(L, 1); o = luaA_index(L, idx); api_check(L, ttistable(o)); setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1); /* write barrier */ #if LUA_REFCOUNT setnilvalue(--L->top); #else !LUA_REFCOUNT L->top--; #endif LUA_REFCOUNT lua_unlock(L); }
LUA_API int lua_setfenv (lua_State *L, int idx) { StkId o; int res = 0; lua_lock(L); api_checknelems(L, 1); o = luaA_index(L, idx); L->top--; api_check(L, ttistable(L->top)); if (isLfunction(o)) { res = 1; clvalue(o)->l.g = *(L->top); } lua_unlock(L); return res; }
LUA_API void lua_settop (lua_State *L, int idx) { lua_lock(L); if (idx >= 0) { api_check(L, idx <= L->stack_last - L->base); while (L->top < L->base + idx) setnilvalue(L->top++); L->top = L->base + idx; } else { #if LUA_REFCOUNT StkId origTop = L->top; int origIdx = idx; api_check(L, -(idx+1) <= (L->top - L->base)); while (++idx < 0) setnilvalue(--L->top); lua_assert(L->top == origTop + (origIdx + 1)); #else !LUA_REFCOUNT api_check(L, -(idx+1) <= (L->top - L->base)); L->top += idx+1; /* `subtract' index (index is negative) */ #endif LUA_REFCOUNT } lua_unlock(L); }
LUA_API void lua_rawset (lua_State *L, int idx) { StkId t; lua_lock(L); api_checknelems(L, 2); t = luaA_index(L, idx); api_check(L, ttistable(t)); setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1); /* write barrier */ #if LUA_REFCOUNT setnilvalue(--L->top); setnilvalue(--L->top); #else !LUA_REFCOUNT L->top -= 2; #endif LUA_REFCOUNT lua_unlock(L); }
LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { StkId o1, o2; int i = 0; lua_lock(L); /* may call tag method */ o1 = index2addr(L, index1); o2 = index2addr(L, index2); if (isvalid(o1) && isvalid(o2)) { switch (op) { case LUA_OPEQ: i = equalobj(L, o1, o2); break; case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; default: api_check(L, 0, "invalid option"); } } lua_unlock(L); return i; }
/* weet: * 1. 用负值索引找栈中的对象 * 2. 可以看出一些栈的设计思路 * */ static TObject *negindex (lua_State *L, int idx) { if (idx > LUA_REGISTRYINDEX) { api_check(L, idx != 0 && -idx <= L->top - L->base); return L->top+idx; } else switch (idx) { /* pseudo-indices */ case LUA_REGISTRYINDEX: return registry(L); case LUA_GLOBALSINDEX: return gt(L); default: { TObject *func = (L->base - 1); idx = LUA_GLOBALSINDEX - idx; lua_assert(iscfunction(func)); return (idx <= clvalue(func)->c.nupvalues) /* (weet: 哈哈, 原来lua把闭包变量放在这个地方!! */ ? &clvalue(func)->c.upvalue[idx-1] : NULL; } } }
LUA_API int lua_checkstack (lua_State *L, int n) { int res; CallInfo *ci = L->ci; lua_lock(L); api_check(n >= 0, "negative 'n'"); if (L->stack_last - L->top > n) /* stack large enough? */ res = 1; /* yes; check is OK */ else { /* no; need to grow stack */ int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ res = 0; /* no */ else /* try to grow stack */ res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); } if (res && ci->top < L->top + n) ci->top = L->top + n; /* adjust frame top */ lua_unlock(L); return res; }
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { lua_lock(L); if (n == 0) { setfvalue(L->top, fn); } else { Closure *cl; api_checknelems(L, n); api_check(L, n <= MAXUPVAL, "upvalue index too large"); luaC_checkGC(L); cl = luaF_newCclosure(L, n); cl->c.f = fn; L->top -= n; while (n--) setobj2n(L, &cl->c.upvalue[n], L->top + n); setclCvalue(L, L->top, cl); } api_incr_top(L); lua_unlock(L); }
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { const char *name; lua_lock(L); if (ar == NULL) { /* information about non-active function? */ if (!isLfunction(L->top - 1)) /* not a Lua function? */ name = NULL; else /* consider live variables at function start (parameters) */ name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); } else { /* active function; get information through 'ar' */ StkId pos = 0; /* to avoid warnings */ name = findlocal(L, ar->i_ci, n, &pos); if (name) { setobj2s(L, L->top, pos); api_incr_top(L); api_check(L, L->top <= L->ci->top); } } lua_unlock(L); return name; }
/* ** generic allocation routine. */ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { void *newblock; global_State *g = G(L); size_t realosize = (block) ? osize : 0; lua_assert((realosize == 0) == (block == NULL)); #if defined(HARDMEMTESTS) if (nsize > realosize && g->gcrunning) luaC_fullgc(L, 1); /* force a GC whenever possible */ #endif newblock = (*g->frealloc)(g->ud, block, osize, nsize); if (newblock == NULL && nsize > 0) { api_check(L, nsize > realosize, "realloc cannot fail when shrinking a block"); if (g->gcrunning) { luaC_fullgc(L, 1); /* try to free some memory... */ newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ } if (newblock == NULL) luaD_throw(L, LUA_ERRMEM); } lua_assert((nsize == 0) == (newblock == NULL)); g->GCdebt = (g->GCdebt + nsize) - realosize; #if defined(TRACEMEM) { /* auxiliary patch to monitor garbage collection. ** To plot, gnuplot with following command: ** plot TRACEMEM using 1:2 with lines, TRACEMEM using 1:3 with lines */ static unsigned long total = 0; /* our "time" */ static FILE *f = NULL; /* output file */ total++; /* "time" always grows */ if ((total % 200) == 0) { if (f == NULL) f = fopen(TRACEMEM, "w"); fprintf(f, "%lu %u %d %d\n", total, gettotalbytes(g), g->GCdebt, g->gcstate * 10000); } } #endif return newblock; }
TObject *negindex (lua_State *L, int idx) { if (idx > LUA_REGISTRYINDEX) { api_check(L, idx != 0 && -idx <= L->top - L->base); return L->top+idx; } else if (idx < -40000) { return (TObject*)luaH_getnum(hvalue(registry(L)), -idx - 40000); } else switch (idx) { /* pseudo-indices */ case LUA_REGISTRYINDEX: return registry(L); case LUA_GLOBALSINDEX: return gt(L); default: { TObject *func = (L->base - 1); idx = LUA_GLOBALSINDEX - idx; lua_assert(iscfunction(func)); return (idx <= clvalue(func)->c.nupvalues) ? &clvalue(func)->c.upvalue[idx-1] : NULL; } } }
/** * 调用此函数前,参数都经过检查, 保证了分配的内存块不会过大; * * 创建对象的函数 luaM_newobject 也调用此函数(lmem.h): * #define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) * * nsize 为 0 表示释放内存 * #define luaM_freearray(L, b, n) luaM_realloc_(L, (b), (n)*sizeof(*(b)), 0) * * 内部调用 g->frealloc 来重新分配内存 */ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { void *newblock; global_State *g = G(L); size_t realosize = (block) ? osize : 0; lua_assert((realosize == 0) == (block == NULL)); #if defined(HARDMEMTESTS) if (nsize > realosize && g->gcrunning) luaC_fullgc(L, 1); /* force a GC whenever possible */ #endif newblock = (*g->frealloc)(g->ud, block, osize, nsize); if (newblock == NULL && nsize > 0) { api_check( nsize > realosize, "realloc cannot fail when shrinking a block"); luaC_fullgc(L, 1); /* try to free some memory... */ newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ if (newblock == NULL) luaD_throw(L, LUA_ERRMEM); } lua_assert((nsize == 0) == (newblock == NULL)); g->GCdebt = (g->GCdebt + nsize) - realosize; return newblock; }
LUA_API int lua_setmetatable (lua_State *L, int objindex) { TObject *obj, *mt; int res = 1; lua_lock(L); api_checknelems(L, 1); obj = luaA_index(L, objindex); mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L); api_check(L, ttistable(mt)); switch (ttype(obj)) { case LUA_TTABLE: { #if LUA_REFCOUNT __AddRefDirect(hvalue(mt)); __ReleaseDirect(L, hvalue(obj)->metatable); #endif LUA_REFCOUNT hvalue(obj)->metatable = hvalue(mt); /* write barrier */ break; } case LUA_TUSERDATA: { #if LUA_REFCOUNT __AddRefDirect(hvalue(mt)); __ReleaseDirect(L, &uvalue(obj)->uv.metatable); #endif LUA_REFCOUNT uvalue(obj)->uv.metatable = hvalue(mt); /* write barrier */ break; } default: { res = 0; /* cannot set */ break; } } #if LUA_REFCOUNT setnilvalue(--L->top); #else !LUA_REFCOUNT L->top--; #endif LUA_REFCOUNT lua_unlock(L); return res; }
LUA_API int lua_setmetatable (lua_State *L, int objindex) { TValue *obj; Table *mt; lua_lock(L); api_checknelems(L, 1); obj = index2addr(L, objindex); api_checkvalidindex(L, obj); if (ttisnil(L->top - 1)) mt = NULL; else { api_check(L, ttistable(L->top - 1), "table expected"); mt = hvalue(L->top - 1); } switch (ttypenv(obj)) { case LUA_TTABLE: { hvalue(obj)->metatable = mt; if (mt) luaC_objbarrierback(L, gcvalue(obj), mt); luaC_checkfinalizer(L, gcvalue(obj), mt); break; } case LUA_TUSERDATA: { uvalue(obj)->metatable = mt; if (mt) { luaC_objbarrier(L, rawuvalue(obj), mt); luaC_checkfinalizer(L, gcvalue(obj), mt); } break; } default: { G(L)->mt[ttypenv(obj)] = mt; break; } } L->top--; lua_unlock(L); return 1; }
int lua_getinfo (LuaThread *L, const char *what, LuaDebug *ar) { THREAD_CHECK(L); int status; LuaClosure *cl; LuaStackFrame *ci; StkId func; if (*what == '>') { ci = NULL; func = L->stack_.top_ - 1; api_check(func->isFunction(), "function expected"); what++; /* skip the '>' */ L->stack_.pop(); /* pop function */ } else { ci = ar->i_ci; func = ci->getFunc(); assert(ci->getFunc()->isFunction()); } cl = NULL; if(func->isCClosure()) cl = func->getCClosure(); if(func->isLClosure()) cl = func->getLClosure(); status = auxgetinfo(L, what, ar, cl, ci); LuaResult result = LUA_OK; if (strchr(what, 'f')) { result = L->stack_.push_reserve2(*func); } handleResult(result); if (strchr(what, 'L')) { collectvalidlines(L, cl); } return status; }
void pushObject(lua_State *luaState, TValue *obj) { setobj2s(luaState, luaState->top, obj); api_check(luaState, luaState->top < luaState->ci->top); luaState->top++; }
static TValue *index2adr (lua_State *L, int idx) { if (idx > 0) { TValue *o = L->base + (idx - 1); api_check(L, idx <= L->ci->top - L->base); if (o >= L->top) return cast(TValue *, luaO_nilobject); else return o;
LUA_API const char *lua_typename (lua_State *L, int t) { UNUSED(L); api_check(LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); return ttypename(t); }