aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sword25/util/lua_serialization_util.cpp269
-rw-r--r--engines/sword25/util/lua_serialization_util.h55
-rw-r--r--engines/sword25/util/lua_serializer.cpp56
-rw-r--r--engines/sword25/util/lua_unserializer.cpp368
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);