diff options
author | RichieSams | 2014-12-30 13:32:44 -0600 |
---|---|---|
committer | RichieSams | 2014-12-30 13:41:24 -0600 |
commit | 2fb116f10eaa1bf682a220c33016fc61492af4fe (patch) | |
tree | 782ae9b63f31f5f7b429e1081fb30e0652d1dd38 /engines/sword25 | |
parent | 2c7a87a4e3181f228c43b92ffb15ae47401f64a7 (diff) | |
download | scummvm-rg350-2fb116f10eaa1bf682a220c33016fc61492af4fe.tar.gz scummvm-rg350-2fb116f10eaa1bf682a220c33016fc61492af4fe.tar.bz2 scummvm-rg350-2fb116f10eaa1bf682a220c33016fc61492af4fe.zip |
SWORD25: Move all lua serialization helper functions to their own file
Diffstat (limited to 'engines/sword25')
-rw-r--r-- | engines/sword25/util/lua_serialization_util.cpp | 269 | ||||
-rw-r--r-- | engines/sword25/util/lua_serialization_util.h | 55 | ||||
-rw-r--r-- | engines/sword25/util/lua_serializer.cpp | 56 | ||||
-rw-r--r-- | engines/sword25/util/lua_unserializer.cpp | 368 |
4 files changed, 376 insertions, 372 deletions
diff --git a/engines/sword25/util/lua_serialization_util.cpp b/engines/sword25/util/lua_serialization_util.cpp index 80c5f86b20..fc3f73eca6 100644 --- a/engines/sword25/util/lua_serialization_util.cpp +++ b/engines/sword25/util/lua_serialization_util.cpp @@ -27,10 +27,20 @@ #include "lua/lobject.h" #include "lua/lstate.h" #include "lua/lgc.h" +#include "lua/lopcodes.h" namespace Lua { +void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize) { + global_State *globalState = G(luaState); + + block = (*globalState->frealloc)(globalState->ud, block, osize, nsize); + globalState->totalbytes = (globalState->totalbytes - osize) + nsize; + + return block; +} + void pushObject(lua_State *luaState, TValue *obj) { setobj2s(luaState, luaState->top, obj); @@ -74,4 +84,263 @@ StkId getObject(lua_State *luaState, int stackpos) { } } +void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type) { + global_State *globalState = G(luaState); + + obj->gch.next = globalState->rootgc; + globalState->rootgc = obj; + obj->gch.marked = luaC_white(globalState); + obj->gch.tt = type; +} + +Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable) { + Closure *c = (Closure *)lua_malloc(luaState, sizeLclosure(numElements)); + lua_linkObjToGC(luaState, obj2gco(c), LUA_TFUNCTION); + + c->l.isC = 0; + c->l.env = elementTable; + c->l.nupvalues = cast_byte(numElements); + + while (numElements--) { + c->l.upvals[numElements] = NULL; + } + + return c; +} + +void pushClosure(lua_State *luaState, Closure *closure) { + TValue obj; + setclvalue(luaState, &obj, closure); + pushObject(luaState, &obj); +} + +Proto *createProto(lua_State *luaState) { + Proto *newProto = (Proto *)lua_malloc(luaState, sizeof(Proto)); + lua_linkObjToGC(luaState, obj2gco(newProto), LUA_TPROTO); + + newProto->k = NULL; + newProto->sizek = 0; + newProto->p = NULL; + newProto->sizep = 0; + newProto->code = NULL; + newProto->sizecode = 0; + newProto->sizelineinfo = 0; + newProto->sizeupvalues = 0; + newProto->nups = 0; + newProto->upvalues = NULL; + newProto->numparams = 0; + newProto->is_vararg = 0; + newProto->maxstacksize = 0; + newProto->lineinfo = NULL; + newProto->sizelocvars = 0; + newProto->locvars = NULL; + newProto->linedefined = 0; + newProto->lastlinedefined = 0; + newProto->source = NULL; + + return newProto; +} + +TString *createString(lua_State *luaState, const char *str, size_t len) { + TString *res; + lua_pushlstring(luaState, str, len); + + res = rawtsvalue(luaState->top - 1); + lua_pop(luaState, 1); + + return res; +} + +Proto *makeFakeProto(lua_State *L, lu_byte nups) { + Proto *p = createProto(L); + + p->sizelineinfo = 1; + p->lineinfo = lua_newVector(L, 1, int); + p->lineinfo[0] = 1; + p->sizecode = 1; + p->code = lua_newVector(L, 1, Instruction); + p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); + p->source = createString(L, "", 0); + p->maxstacksize = 2; + p->nups = nups; + p->sizek = 0; + p->sizep = 0; + + return p; +} + +UpVal *createUpValue(lua_State *luaState, int stackpos) { + UpVal *upValue = (UpVal *)lua_malloc(luaState, sizeof(UpVal)); + lua_linkObjToGC(luaState, (GCObject *)upValue, LUA_TUPVAL); + upValue->tt = LUA_TUPVAL; + upValue->v = &upValue->u.value; + upValue->u.l.prev = NULL; + upValue->u.l.next = NULL; + + const TValue *o2 = (TValue *)getObject(luaState, stackpos); + upValue->v->value = o2->value; + upValue->v->tt = o2->tt; + checkliveness(G(L), upValue->v); + + return upValue; +} + +void unboxUpValue(lua_State *luaState) { + // >>>>> ...... func + LClosure *lcl; + UpVal *uv; + + lcl = (LClosure *)clvalue(getObject(luaState, -1)); + uv = lcl->upvals[0]; + + lua_pop(luaState, 1); + // >>>>> ...... + + pushUpValue(luaState, uv); + // >>>>> ...... upValue +} + +size_t appendStackToStack_reverse(lua_State *from, lua_State *to) { + for (StkId id = from->top - 1; id >= from->stack; --id) { + setobj2s(to, to->top, id); + to->top++; + } + + return from->top - from->stack; +} + +void correctStack(lua_State *L, TValue *oldstack) { + CallInfo *ci; + GCObject *up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->gch.next) + gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; + for (ci = L->base_ci; ci <= L->ci; ci++) { + ci->top = (ci->top - oldstack) + L->stack; + ci->base = (ci->base - oldstack) + L->stack; + ci->func = (ci->func - oldstack) + L->stack; + } + L->base = (L->base - oldstack) + L->stack; +} + +void lua_reallocstack(lua_State *L, int newsize) { + TValue *oldstack = L->stack; + int realsize = newsize + 1 + EXTRA_STACK; + + lua_reallocvector(L, L->stack, L->stacksize, realsize, TValue); + L->stacksize = realsize; + L->stack_last = L->stack + newsize; + correctStack(L, oldstack); +} + +void lua_growstack(lua_State *L, int n) { + // Double size is enough? + if (n <= L->stacksize) { + lua_reallocstack(L, 2 * L->stacksize); + } else { + lua_reallocstack(L, L->stacksize + n); + } +} + +void lua_reallocCallInfo(lua_State *lauState, int newsize) { + CallInfo *oldci = lauState->base_ci; + lua_reallocvector(lauState, lauState->base_ci, lauState->size_ci, newsize, CallInfo); + + lauState->size_ci = newsize; + lauState->ci = (lauState->ci - oldci) + lauState->base_ci; + lauState->end_ci = lauState->base_ci + lauState->size_ci - 1; +} + +void GCUnlink(lua_State *luaState, GCObject *gco) { + GCObject *prevslot; + if (G(luaState)->rootgc == gco) { + G(luaState)->rootgc = G(luaState)->rootgc->gch.next; + return; + } + + prevslot = G(luaState)->rootgc; + while (prevslot->gch.next != gco) { + prevslot = prevslot->gch.next; + } + + prevslot->gch.next = prevslot->gch.next->gch.next; +} + +TString *lua_newlstr(lua_State *luaState, const char *str, size_t len) { + lua_pushlstring(luaState, str, len); + TString *luaStr = &(luaState->top - 1)->value.gc->ts; + + lua_pop(luaState, 1); + + return luaStr; +} + +void lua_link(lua_State *luaState, GCObject *o, lu_byte tt) { + global_State *g = G(luaState); + o->gch.next = g->rootgc; + g->rootgc = o; + o->gch.marked = luaC_white(g); + o->gch.tt = tt; +} + +Proto *lua_newproto(lua_State *luaState) { + Proto *f = (Proto *)lua_malloc(luaState, sizeof(Proto)); + lua_link(luaState, obj2gco(f), LUA_TPROTO); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->sizecode = 0; + f->sizelineinfo = 0; + f->sizeupvalues = 0; + f->nups = 0; + f->upvalues = NULL; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->lineinfo = NULL; + f->sizelocvars = 0; + f->locvars = NULL; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + +UpVal *makeUpValue(lua_State *luaState, int stackPos) { + UpVal *uv = lua_new(luaState, UpVal); + lua_link(luaState, (GCObject *)uv, LUA_TUPVAL); + uv->tt = LUA_TUPVAL; + uv->v = &uv->u.value; + uv->u.l.prev = NULL; + uv->u.l.next = NULL; + + setobj(luaState, uv->v, getObject(luaState, stackPos)); + + return uv; +} + +void boxUpValue_start(lua_State *luaState) { + LClosure *closure; + closure = (LClosure *)lua_newLclosure(luaState, 1, hvalue(&luaState->l_gt)); + pushClosure(luaState, (Closure *)closure); + // >>>>> ...... func + closure->p = makeFakeProto(luaState, 1); + + // Temporarily initialize the upvalue to nil + lua_pushnil(luaState); + closure->upvals[0] = makeUpValue(luaState, -1); + lua_pop(luaState, 1); +} + +void boxUpValue_finish(lua_State *luaState) { + // >>>>> ...... func obj + LClosure *lcl = (LClosure *)clvalue(getObject(luaState, -2)); + + lcl->upvals[0]->u.value = *getObject(luaState, -1); + lua_pop(luaState, 1); + // >>>>> ...... func +} + } // End of namespace Lua diff --git a/engines/sword25/util/lua_serialization_util.h b/engines/sword25/util/lua_serialization_util.h index 6c55d0dd53..345996f606 100644 --- a/engines/sword25/util/lua_serialization_util.h +++ b/engines/sword25/util/lua_serialization_util.h @@ -32,12 +32,67 @@ typedef TValue *StkId; namespace Lua { +#define lua_malloc(luaState, nsize) lua_realloc(luaState, nullptr, 0, nsize) +#define lua_reallocv(luaState, block, on, n, e) lua_realloc(luaState, block, (on) * (e), (n) * (e)) +#define lua_reallocvector(luaState, vec, oldn, n, T) ((vec) = (T *)(lua_reallocv(luaState, vec, oldn, n, sizeof(T)))) +#define lua_newVector(luaState, num, T) ((T *)lua_reallocv(luaState, nullptr, 0, num, sizeof(T))) +#define lua_new(luaState,T) (T *)lua_malloc(luaState, sizeof(T)) + +void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize); + void pushObject(lua_State *luaState, TValue *obj); void pushProto(lua_State *luaState, Proto *proto); void pushUpValue(lua_State *luaState, UpVal *upval); void pushString(lua_State *luaState, TString *str); + StkId getObject(lua_State *luaState, int stackpos); +void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type); + +#define sizeLclosure(n) ((sizeof(LClosure)) + sizeof(TValue *) * ((n) - 1)) + +Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable); +void pushClosure(lua_State *luaState, Closure *closure); + +Proto *createProto(lua_State *luaState); +Proto *makeFakeProto(lua_State *L, lu_byte nups); + +TString *createString(lua_State *luaState, const char *str, size_t len); + +UpVal *createUpValue(lua_State *luaState, int stackpos); +void unboxUpValue(lua_State *luaState); + +/* Appends one stack to another stack, but the stack is reversed in the process */ +size_t appendStackToStack_reverse(lua_State *from, lua_State *to); +void correctStack(lua_State *L, TValue *oldstack); +void lua_reallocstack(lua_State *L, int newsize); +void lua_growstack(lua_State *L, int n); + +void lua_reallocCallInfo(lua_State *lauState, int newsize); + +/* Does basically the opposite of luaC_link(). + * Right now this function is rather inefficient; it requires traversing the + * entire root GC set in order to find one object. If the GC list were doubly + * linked this would be much easier, but there's no reason for Lua to have + * that. */ +void GCUnlink(lua_State *luaState, GCObject *gco); + +TString *lua_newlstr(lua_State *luaState, const char *str, size_t len); +void lua_link(lua_State *luaState, GCObject *o, lu_byte tt); +Proto *lua_newproto(lua_State *luaState) ; + +UpVal *makeUpValue(lua_State *luaState, int stackPos); +/** + * The GC is not fond of finding upvalues in tables. We get around this + * during persistence using a weakly keyed table, so that the GC doesn't + * bother to mark them. This won't work in unpersisting, however, since + * if we make the values weak they'll be collected (since nothing else + * references them). Our solution, during unpersisting, is to represent + * upvalues as dummy functions, each with one upvalue. + */ +void boxUpValue_start(lua_State *luaState); +void boxUpValue_finish(lua_State *luaState); + } // End of namespace Lua #endif diff --git a/engines/sword25/util/lua_serializer.cpp b/engines/sword25/util/lua_serializer.cpp index c6c5f99342..55b6257324 100644 --- a/engines/sword25/util/lua_serializer.cpp +++ b/engines/sword25/util/lua_serializer.cpp @@ -42,7 +42,7 @@ struct SerializationInfo { uint counter; }; -static void serializeObject(SerializationInfo *info); +static void serialize(SerializationInfo *info); static void serializeBoolean(SerializationInfo *info); static void serializeNumber(SerializationInfo *info); @@ -103,14 +103,14 @@ void serializeLua(lua_State *luaState, Common::WriteStream *writeStream) { // >>>>> permTbl indexTbl rootObj // Serialize the root recursively - serializeObject(&info); + serialize(&info); // Return the stack back to the original state lua_remove(luaState, 2); // >>>>> permTbl rootObj } -static void serializeObject(SerializationInfo *info) { +static void serialize(SerializationInfo *info) { // The stack can potentially have many things on it // The object we want to serialize is the item on the top of the stack // >>>>> permTbl indexTbl rootObj ...... obj @@ -188,7 +188,7 @@ static void serializeObject(SerializationInfo *info) { info->writeStream->writeSint32LE(PERMANENT_TYPE); // Serialize the key - serializeObject(info); + serialize(info); // Pop the key off the stack lua_pop(info->luaState, 1); @@ -368,7 +368,7 @@ static bool serializeSpecialObject(SerializationInfo *info, bool defaction) { info->writeStream->writeSint32LE(1); // Serialize the function - serializeObject(info); + serialize(info); lua_pop(info->luaState, 2); // >>>>> permTbl indexTbl ...... obj @@ -395,7 +395,7 @@ static void serializeTable(SerializationInfo *info) { } // >>>>> permTbl indexTbl ...... tbl metaTbl/nil */ - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl @@ -412,13 +412,13 @@ static void serializeTable(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... tbl k v k */ // Serialize the key - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl k v */ // Serialize the value - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl k */ @@ -430,7 +430,7 @@ static void serializeTable(SerializationInfo *info) { lua_pushnil(info->luaState); // >>>>> permTbl indexTbl ...... tbl - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... tbl @@ -457,7 +457,7 @@ static void serializeFunction(SerializationInfo *info) { pushProto(info->luaState, cl->l.p); // >>>>> permTbl indexTbl ...... func proto */ - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... func @@ -468,7 +468,7 @@ static void serializeFunction(SerializationInfo *info) { pushUpValue(info->luaState, cl->l.upvals[i]); // >>>>> permTbl indexTbl ...... func upval - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... func @@ -492,23 +492,13 @@ static void serializeFunction(SerializationInfo *info) { } // >>>>> permTbl indexTbl ...... func fenv/nil - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... func } } -/* Appends one stack to another stack, but the stack is reversed in the process */ -static size_t appendStackToStack_rev(lua_State *from, lua_State *to) { - for (StkId id = from->top - 1; id >= from->stack; --id) { - setobj2s(to, to->top, id); - to->top++; - } - - return from->top - from->stack; -} - static void serializeThread(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... thread lua_State *threadState = lua_tothread(info->luaState, -1); @@ -525,12 +515,12 @@ static void serializeThread(SerializationInfo *info) { // Persist the stack // We *could* have truncation here, but if we have more than 4 billion items on a stack, we have bigger problems - uint32 stackSize = static_cast<uint32>(appendStackToStack_rev(threadState, info->luaState)); + uint32 stackSize = static_cast<uint32>(appendStackToStack_reverse(threadState, info->luaState)); info->writeStream->writeUint32LE(stackSize); // >>>>> permTbl indexTbl ...... thread (reversed contents of thread stack) */ for (; stackSize > 0; --stackSize) { - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); } @@ -592,7 +582,7 @@ static void serializeThread(SerializationInfo *info) { pushUpValue(info->luaState, upVal); // >>>>> permTbl indexTbl ...... thread upVal - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... thread @@ -607,7 +597,7 @@ static void serializeThread(SerializationInfo *info) { // >>>>> permTbl indexTbl ...... thread nil // Use nil as a terminator - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... thread @@ -627,7 +617,7 @@ static void serializeProto(SerializationInfo *info) { pushObject(info->luaState, &proto->k[i]); // >>>>> permTbl indexTbl ...... proto const - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -643,7 +633,7 @@ static void serializeProto(SerializationInfo *info) { pushProto(info->luaState, proto->p[i]); // >>>>> permTbl indexTbl ...... proto subProto */ - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -666,7 +656,7 @@ static void serializeProto(SerializationInfo *info) { pushString(info->luaState, proto->upvalues[i]); // >>>>> permTbl indexTbl ...... proto str - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -680,7 +670,7 @@ static void serializeProto(SerializationInfo *info) { pushString(info->luaState, proto->locvars[i].varname); // >>>>> permTbl indexTbl ...... proto str - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -694,7 +684,7 @@ static void serializeProto(SerializationInfo *info) { pushString(info->luaState, proto->source); // >>>>> permTbl indexTbl ...... proto sourceStr - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); // >>>>> permTbl indexTbl ...... proto @@ -757,7 +747,7 @@ static void serializeUpValue(SerializationInfo *info) { pushObject(info->luaState, upValue->v); // >>>>> permTbl indexTbl ...... obj - serializeObject(info); + serialize(info); // >>>>> permTbl indexTbl ...... obj } @@ -787,7 +777,7 @@ static void serializeUserData(SerializationInfo *info) { } // >>>>> permTbl rootObj ...... udata metaTbl/nil - serializeObject(info); + serialize(info); lua_pop(info->luaState, 1); /* perms reftbl ... udata */ diff --git a/engines/sword25/util/lua_unserializer.cpp b/engines/sword25/util/lua_unserializer.cpp index 69cb764dd2..803c79c8c2 100644 --- a/engines/sword25/util/lua_unserializer.cpp +++ b/engines/sword25/util/lua_unserializer.cpp @@ -40,7 +40,7 @@ struct UnSerializationInfo { Common::ReadStream *readStream; }; -static void unserializeObject(UnSerializationInfo *info); +static void unserialize(UnSerializationInfo *info); static void unserializeBoolean(UnSerializationInfo *info); static void unserializeNumber(UnSerializationInfo *info); @@ -74,7 +74,7 @@ void unserializeLua(lua_State *luaState, Common::ReadStream *readStream) { lua_gc(luaState, LUA_GCSTOP, 0); // Unserialize the root object - unserializeObject(&info); + unserialize(&info); // >>>>> permTbl indexTbl rootObj // Re-start garbage collection @@ -85,7 +85,7 @@ void unserializeLua(lua_State *luaState, Common::ReadStream *readStream) { // >>>>> permTbl rootObj } -/* The object is left on the stack. This is primarily used by unpersist, but +/* The object is left on the stack. This is primarily used by unserialize, but * may be used by GCed objects that may incur cycles in order to preregister * the object. */ static void registerObjectInIndexTable(UnSerializationInfo *info, int index) { @@ -105,7 +105,7 @@ static void registerObjectInIndexTable(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... obj } -static void unserializeObject(UnSerializationInfo *info) { +static void unserialize(UnSerializationInfo *info) { // >>>>> permTbl indexTbl ...... // Make sure there is enough room on the stack @@ -241,7 +241,7 @@ static void unserializeSpecialTable(UnSerializationInfo *info, int index) { // Make sure there is enough room on the stack lua_checkstack(info->luaState, 1); - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... spfunc lua_call(info->luaState, 0, 1); @@ -262,7 +262,7 @@ static void unserializeLiteralTable(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... tbl // Unserialize metatable - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... tbl ?metaTbl/nil? if (lua_istable(info->luaState, -1)) { @@ -279,7 +279,7 @@ static void unserializeLiteralTable(UnSerializationInfo *info, int index) { while (1) { // >>>>> permTbl indexTbl ...... tbl - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... tbl key/nil // The table serialization is nil terminated @@ -292,7 +292,7 @@ static void unserializeLiteralTable(UnSerializationInfo *info, int index) { } // >>>>> permTbl indexTbl ...... tbl key - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... tbl value lua_rawset(info->luaState, -3); @@ -317,142 +317,6 @@ void unserializeTable(UnSerializationInfo *info, int index) { } } - - -void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize) { - global_State *globalState = G(luaState); - - block = (*globalState->frealloc)(globalState->ud, block, osize, nsize); - globalState->totalbytes = (globalState->totalbytes - osize) + nsize; - - return block; -} - -#define lua_malloc(luaState, nsize) lua_realloc(luaState, nullptr, 0, nsize) -#define lua_reallocv(luaState, block, on, n, e) lua_realloc(luaState, block, (on) * (e), (n) * (e)) -#define lua_reallocvector(luaState, vec, oldn, n, T) ((vec) = (T *)(lua_reallocv(luaState, vec, oldn, n, sizeof(T)))) -#define lua_newVector(luaState, num, T) ((T *)lua_reallocv(luaState, nullptr, 0, num, sizeof(T))) -#define lua_new(luaState,T) (T *)lua_malloc(luaState, sizeof(T)) - -void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type) { - global_State *globalState = G(luaState); - - obj->gch.next = globalState->rootgc; - globalState->rootgc = obj; - obj->gch.marked = luaC_white(globalState); - obj->gch.tt = type; -} - -#define sizeLclosure(n) ((sizeof(LClosure)) + sizeof(TValue *) * ((n) - 1)) - -Closure *newLClosure(lua_State *luaState, byte numUpValues, Table *env) { - Closure *newClosure = (Closure *)lua_malloc(luaState, sizeLclosure(numUpValues)); - - lua_linkObjToGC(luaState, obj2gco(newClosure), LUA_TFUNCTION); - - newClosure->l.isC = 0; - newClosure->l.env = env; - newClosure->l.nupvalues = numUpValues; - - while (numUpValues--) { - newClosure->l.upvals[numUpValues] = NULL; - } - - return newClosure; -} - -static void pushClosure(lua_State *luaState, Closure *closure) { - TValue obj; - setclvalue(luaState, &obj, closure); - pushObject(luaState, &obj); -} - -Proto *createProto(lua_State *luaState) { - Proto *newProto = (Proto *)lua_malloc(luaState, sizeof(Proto)); - lua_linkObjToGC(luaState, obj2gco(newProto), LUA_TPROTO); - - newProto->k = NULL; - newProto->sizek = 0; - newProto->p = NULL; - newProto->sizep = 0; - newProto->code = NULL; - newProto->sizecode = 0; - newProto->sizelineinfo = 0; - newProto->sizeupvalues = 0; - newProto->nups = 0; - newProto->upvalues = NULL; - newProto->numparams = 0; - newProto->is_vararg = 0; - newProto->maxstacksize = 0; - newProto->lineinfo = NULL; - newProto->sizelocvars = 0; - newProto->locvars = NULL; - newProto->linedefined = 0; - newProto->lastlinedefined = 0; - newProto->source = NULL; - - return newProto; -} - -TString *createString(lua_State *luaState, const char *str, size_t len) { - TString *res; - lua_pushlstring(luaState, str, len); - - res = rawtsvalue(luaState->top - 1); - lua_pop(luaState, 1); - - return res; -} - -static Proto *makeFakeProto(lua_State *L, lu_byte nups) { - Proto *p = createProto(L); - - p->sizelineinfo = 1; - p->lineinfo = lua_newVector(L, 1, int); - p->lineinfo[0] = 1; - p->sizecode = 1; - p->code = lua_newVector(L, 1, Instruction); - p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); - p->source = createString(L, "", 0); - p->maxstacksize = 2; - p->nups = nups; - p->sizek = 0; - p->sizep = 0; - - return p; -} - -static UpVal *createUpValue(lua_State *luaState, int stackpos) { - UpVal *upValue = (UpVal *)lua_malloc(luaState, sizeof(UpVal)); - lua_linkObjToGC(luaState, (GCObject *)upValue, LUA_TUPVAL); - upValue->tt = LUA_TUPVAL; - upValue->v = &upValue->u.value; - upValue->u.l.prev = NULL; - upValue->u.l.next = NULL; - - const TValue *o2 = (TValue *)getObject(luaState, stackpos); - upValue->v->value = o2->value; - upValue->v->tt = o2->tt; - checkliveness(G(L), upValue->v); - - return upValue; -} - -static void unboxUpValue(lua_State *luaState) { - // >>>>> ...... func - LClosure *lcl; - UpVal *uv; - - lcl = (LClosure *)clvalue(getObject(luaState, -1)); - uv = lcl->upvals[0]; - - lua_pop(luaState, 1); - // >>>>> ...... - - pushUpValue(luaState, uv); - // >>>>> ...... upValue -} - void unserializeFunction(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... @@ -461,7 +325,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { byte numUpValues = info->readStream->readByte(); - LClosure *lclosure = (LClosure *)newLClosure(info->luaState, numUpValues, hvalue(&info->luaState->l_gt)); + LClosure *lclosure = (LClosure *)lua_newLclosure(info->luaState, numUpValues, hvalue(&info->luaState->l_gt)); pushClosure(info->luaState, (Closure *)lclosure); // >>>>> permTbl indexTbl ...... func @@ -484,7 +348,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { registerObjectInIndexTable(info, index); // Now that it's safe, we can get the real proto - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... func proto lclosure->p = gco2p(getObject(info->luaState, -1)->value.gc); @@ -494,7 +358,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { for (byte i = 0; i < numUpValues; ++i) { // >>>>> permTbl indexTbl ...... func - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... func func2 unboxUpValue(info->luaState); @@ -506,7 +370,7 @@ void unserializeFunction(UnSerializationInfo *info, int index) { } // Finally, the fenv - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... func ?fenv/nil? if (!lua_isnil(info->luaState, -1)) { @@ -522,81 +386,6 @@ void unserializeFunction(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... func } -static void correctStack(lua_State *L, TValue *oldstack) { - CallInfo *ci; - GCObject *up; - L->top = (L->top - oldstack) + L->stack; - for (up = L->openupval; up != NULL; up = up->gch.next) - gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; - for (ci = L->base_ci; ci <= L->ci; ci++) { - ci->top = (ci->top - oldstack) + L->stack; - ci->base = (ci->base - oldstack) + L->stack; - ci->func = (ci->func - oldstack) + L->stack; - } - L->base = (L->base - oldstack) + L->stack; -} - -void lua_reallocstack(lua_State *L, int newsize) { - TValue *oldstack = L->stack; - int realsize = newsize + 1 + EXTRA_STACK; - - lua_reallocvector(L, L->stack, L->stacksize, realsize, TValue); - L->stacksize = realsize; - L->stack_last = L->stack + newsize; - correctStack(L, oldstack); -} - -void lua_growstack(lua_State *L, int n) { - // Double size is enough? - if (n <= L->stacksize) { - lua_reallocstack(L, 2 * L->stacksize); - } else { - lua_reallocstack(L, L->stacksize + n); - } -} - -void lua_reallocCallInfo(lua_State *lauState, int newsize) { - CallInfo *oldci = lauState->base_ci; - lua_reallocvector(lauState, lauState->base_ci, lauState->size_ci, newsize, CallInfo); - - lauState->size_ci = newsize; - lauState->ci = (lauState->ci - oldci) + lauState->base_ci; - lauState->end_ci = lauState->base_ci + lauState->size_ci - 1; -} - -void unboxUpVal(lua_State *luaState) { - // >>>>> ... func - LClosure *lcl; - UpVal *uv; - - lcl = (LClosure *)(&getObject(luaState, -1)->value.gc->cl); - uv = lcl->upvals[0]; - lua_pop(luaState, 1); - // >>>>> ... - pushUpValue(luaState, uv); - // >>>>> ... upVal -} - -/* Does basically the opposite of luaC_link(). - * Right now this function is rather inefficient; it requires traversing the - * entire root GC set in order to find one object. If the GC list were doubly - * linked this would be much easier, but there's no reason for Lua to have - * that. */ -static void GCUnlink(lua_State *luaState, GCObject *gco) { - GCObject *prevslot; - if (G(luaState)->rootgc == gco) { - G(luaState)->rootgc = G(luaState)->rootgc->gch.next; - return; - } - - prevslot = G(luaState)->rootgc; - while (prevslot->gch.next != gco) { - prevslot = prevslot->gch.next; - } - - prevslot->gch.next = prevslot->gch.next->gch.next; -} - void unserializeThread(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... @@ -619,7 +408,7 @@ void unserializeThread(UnSerializationInfo *info, int index) { // very bottom of the stack L2->top--; for (uint32 i = 0; i < stackSize; ++i) { - unserializeObject(info); + unserialize(info); // L1: permTbl indexTbl ...... thread obj* } @@ -679,7 +468,7 @@ void unserializeThread(UnSerializationInfo *info, int index) { global_State *g = G(L2); while (true) { - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... thread upVal/nil // The list is terminated by a nil @@ -691,7 +480,7 @@ void unserializeThread(UnSerializationInfo *info, int index) { } // >>>>> permTbl indexTbl ...... thread boxedUpVal - unboxUpVal(info->luaState); + unboxUpValue(info->luaState); // >>>>> permTbl indexTbl ...... thread boxedUpVal uv = &(getObject(info->luaState, -1)->value.gc->uv); @@ -722,48 +511,6 @@ void unserializeThread(UnSerializationInfo *info, int index) { } } -TString *lua_newlstr(lua_State *luaState, const char *str, size_t len) { - lua_pushlstring(luaState, str, len); - TString *luaStr = &(luaState->top - 1)->value.gc->ts; - - lua_pop(luaState, 1); - - return luaStr; -} - -void lua_link(lua_State *luaState, GCObject *o, lu_byte tt) { - global_State *g = G(luaState); - o->gch.next = g->rootgc; - g->rootgc = o; - o->gch.marked = luaC_white(g); - o->gch.tt = tt; -} - -Proto *lua_newproto(lua_State *luaState) { - Proto *f = (Proto *)lua_malloc(luaState, sizeof(Proto)); - lua_link(luaState, obj2gco(f), LUA_TPROTO); - f->k = NULL; - f->sizek = 0; - f->p = NULL; - f->sizep = 0; - f->code = NULL; - f->sizecode = 0; - f->sizelineinfo = 0; - f->sizeupvalues = 0; - f->nups = 0; - f->upvalues = NULL; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->lineinfo = NULL; - f->sizelocvars = 0; - f->locvars = NULL; - f->linedefined = 0; - f->lastlinedefined = 0; - f->source = NULL; - return f; -} - void unserializeProto(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... @@ -793,7 +540,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->k, 0, sizek, TValue); for (int i = 0; i < sizek; ++i) { // >>>>> permTbl indexTbl ...... proto - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... proto k setobj2s(info->luaState, &p->k[i], getObject(info->luaState, -1)); @@ -810,7 +557,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->p, 0, sizep, Proto *); for (int i = 0; i < sizep; ++i) { // >>>>> permTbl indexTbl ...... proto - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... proto subproto p->p[i] = (Proto *)getObject(info->luaState, -1)->value.gc; @@ -834,7 +581,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->upvalues, 0, p->sizeupvalues, TString *); for (int i = 0; i < p->sizeupvalues; ++i) { // >>>>> permTbl indexTbl ...... proto - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... proto str p->upvalues[i] = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); @@ -850,7 +597,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { lua_reallocvector(info->luaState, p->locvars, 0, p->sizelocvars, LocVar); for (int i = 0; i < p->sizelocvars; ++i) { // >>>>> permTbl indexTbl ...... proto - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... proto str p->locvars[i].varname = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); @@ -864,7 +611,7 @@ void unserializeProto(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... proto // Read in source string - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... proto sourceStr p->source = lua_newlstr(info->luaState, lua_tostring(info->luaState, -1), strlen(lua_tostring(info->luaState, -1))); @@ -890,75 +637,18 @@ void unserializeProto(UnSerializationInfo *info, int index) { p->maxstacksize = info->readStream->readByte(); } -Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable) { - Closure *c = (Closure *)lua_malloc(luaState, sizeLclosure(numElements)); - lua_link(luaState, obj2gco(c), LUA_TFUNCTION); - c->l.isC = 0; - c->l.env = elementTable; - c->l.nupvalues = cast_byte(numElements); - - while (numElements--) { - c->l.upvals[numElements] = NULL; - } - - return c; -} - -static UpVal *makeUpVal(lua_State *luaState, int stackPos) { - UpVal *uv = lua_new(luaState, UpVal); - lua_link(luaState, (GCObject *)uv, LUA_TUPVAL); - uv->tt = LUA_TUPVAL; - uv->v = &uv->u.value; - uv->u.l.prev = NULL; - uv->u.l.next = NULL; - - setobj(luaState, uv->v, getObject(luaState, stackPos)); - - return uv; -} - -/** - * The GC is not fond of finding upvalues in tables. We get around this - * during persistence using a weakly keyed table, so that the GC doesn't - * bother to mark them. This won't work in unpersisting, however, since - * if we make the values weak they'll be collected (since nothing else - * references them). Our solution, during unpersisting, is to represent - * upvalues as dummy functions, each with one upvalue. - */ -static void boxupval_start(lua_State *luaState) { - LClosure *closure; - closure = (LClosure *)lua_newLclosure(luaState, 1, hvalue(&luaState->l_gt)); - pushClosure(luaState, (Closure *)closure); - // >>>>> ...... func - closure->p = makeFakeProto(luaState, 1); - - // Temporarily initialize the upvalue to nil - lua_pushnil(luaState); - closure->upvals[0] = makeUpVal(luaState, -1); - lua_pop(luaState, 1); -} - -static void boxupval_finish(lua_State *luaState) { - // >>>>> ...... func obj - LClosure *lcl = (LClosure *)clvalue(getObject(luaState, -2)); - - lcl->upvals[0]->u.value = *getObject(luaState, -1); - lua_pop(luaState, 1); - // >>>>> ...... func -} - void unserializeUpValue(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... - lua_checkstack(upi->L, 2); + lua_checkstack(info->luaState, 2); - boxupval_start(upi->L); + boxUpValue_start(info->luaState); // >>>>> permTbl indexTbl ...... func registerObjectInIndexTable(info, index); - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... func obj - boxupval_finish(upi->L); + boxUpValue_finish(info->luaState); // >>>>> permTbl indexTbl ...... func } @@ -970,7 +660,7 @@ void unserializeUserData(UnSerializationInfo *info, int index) { int isspecial = info->readStream->readSint32LE(); if (isspecial) { - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... specialFunc lua_call(info->luaState, 0, 1); @@ -981,12 +671,12 @@ void unserializeUserData(UnSerializationInfo *info, int index) { // >>>>> permTbl indexTbl ...... udata registerObjectInIndexTable(info, index); - info->readStream->read(lua_touserdata(upi->L, -1), length); + info->readStream->read(lua_touserdata(info->luaState, -1), length); - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... udata metaTable/nil - lua_setmetatable(upi->L, -2); + lua_setmetatable(info->luaState, -2); // >>>>> permTbl indexTbl ...... udata } // >>>>> permTbl indexTbl ...... udata @@ -998,7 +688,7 @@ void unserializePermanent(UnSerializationInfo *info, int index) { // Make sure there is enough room on the stack lua_checkstack(info->luaState, 2); - unserializeObject(info); + unserialize(info); // >>>>> permTbl indexTbl ...... permKey lua_gettable(info->luaState, 1); |