@@ -83,6 +83,11 @@ namespace Lua
8383 struct LuaMetaEntry {
8484 unsigned char iType = UCHAR_MAX;
8585 GCRef metatable; // Direct reference allowing for faster setting.
86+
87+ LuaMetaEntry ()
88+ {
89+ setgcrefnull (metatable);
90+ }
8691 };
8792
8893 /*
@@ -141,9 +146,31 @@ namespace Lua
141146 std::unordered_map<void *, LuaUserData*> pPushedUserData; // Would love to get rid of this
142147 GarrysMod::Lua::ILuaInterface* pLua = NULL ;
143148 CLuaInterfaceProxy* pProxy;
149+ GCRef nErrorFunc;
150+
151+ StateData ()
152+ {
153+ setgcrefnull (nErrorFunc);
154+ }
144155
145156 ~StateData ();
146157
158+ // When called we expect the error function to be pushed onto the stack. We'll pop it.
159+ inline void SetErrorFunc ()
160+ {
161+ lua_State* L = pLua->GetState ();
162+ TValue* pVal = RawLua::index2adr (L, -1 );
163+ if (!tvistab (pVal))
164+ {
165+ Warning (PROJECT_NAME " - RegisterMetaTable: MetaTable is NOT a table?!? What the heck!\n " );
166+ pLua->Pop (1 );
167+ return ;
168+ }
169+
170+ setgcref (nErrorFunc, obj2gco (tabV (pVal)));
171+ pLua->Pop (1 ); // it's stored in the registry so everything will be fine :3
172+ }
173+
147174 inline void RegisterMetaTable (LuaTypes type, int metaID)
148175 {
149176 pLuaTypes[type].iType = (unsigned char )metaID;
@@ -222,6 +249,28 @@ namespace Lua
222249 {
223250 return pPushedUserData;
224251 }
252+
253+ inline bool FastPCall (int nArgs, int nRets, bool bShowError)
254+ {
255+ lua_State* L = pLua->GetState ();
256+ int nRet = Util::func_lua_pcall (L, nArgs, nRets, 0 );
257+ if (nRet > 0 )
258+ {
259+ // We use the ILuaInterface here since on errors we really don't expect speed.
260+ if (bShowError)
261+ {
262+ const char * pError = pLua->GetString (-1 );
263+ pLua->Pop (1 );
264+ pLua->ErrorFromLua (pError);
265+ } else {
266+ pLua->Pop (1 );
267+ }
268+
269+ return false ;
270+ }
271+
272+ return true ;
273+ }
225274 };
226275
227276 /*
@@ -464,7 +513,7 @@ struct LuaUserData : GCudata_holylib { // No constructor/deconstructor since its
464513 {
465514 setgcrefnull (nextgc);
466515 gct = 0x0 ;
467- marked = 0x0 ;
516+ marked = 0x3 ; // mark white
468517 }
469518
470519 inline void Init (GarrysMod::Lua::ILuaInterface* LUA, const Lua::LuaMetaEntry& pMetaEntry, void * pData, bool bNoGC = false , bool bNoUserTable = false )
@@ -491,7 +540,7 @@ struct LuaUserData : GCudata_holylib { // No constructor/deconstructor since its
491540 flags |= UDATA_NO_USERTABLE;
492541 // setgcrefnull(usertable); // Verify: Do we need to always have a valid usertable? iirc the gc is missing a null check
493542 } else {
494- ClearLuaTable (LUA);
543+ ClearLuaTable (LUA, true );
495544 }
496545
497546 /* global_StateGMOD *g = (global_StateGMOD*)G(LUA->GetState());
@@ -505,7 +554,7 @@ struct LuaUserData : GCudata_holylib { // No constructor/deconstructor since its
505554#if HOLYLIB_UTIL_DEBUG_LUAUSERDATA
506555 g_pLuaUserData.insert (this );
507556#if HOLYLIB_UTIL_DEBUG_LUAUSERDATA == 2
508- Msg (" holylib - util: LuaUserdata got initialized %p - %p - %i\n " , this , LUA, type );
557+ Msg (" holylib - util: LuaUserdata got initialized %p - %p - %i\n " , this , LUA, pMetaEntry. iType );
509558#endif
510559#endif
511560 }
@@ -571,13 +620,13 @@ struct LuaUserData : GCudata_holylib { // No constructor/deconstructor since its
571620 }
572621 }
573622
574- inline void ClearLuaTable (GarrysMod::Lua::ILuaInterface* pLua)
623+ inline void ClearLuaTable (GarrysMod::Lua::ILuaInterface* pLua, bool bFresh = false ) // bFresh = if we got freshly created / are in a white state
575624 {
576625 if (flags & UDATA_NO_USERTABLE)
577626 return ;
578627
579628 lua_State* L = pLua->GetState ();
580- if (Util::func_lj_tab_new)
629+ if (Util::func_lj_tab_new && (bFresh || Util::func_lj_gc_barrierf) )
581630 {
582631 // We cannot free it since the GC would kill itself... We also SHOULDN'T since the gc handles it already, so NO touching >:(
583632 // Why does the GC kill itself? Because inside the GCHeader of the usertable, the next GC object is stored.
@@ -586,9 +635,30 @@ struct LuaUserData : GCudata_holylib { // No constructor/deconstructor since its
586635 // And lj_tab_free also doesn't take care of this, it just frees the memory, so this caused crashes, memory corruption and infinite loops.
587636 // Util::func_lj_tab_free(G(L), gco2tab(gcref(usertable)));
588637 setgcref (usertable, obj2gco (Util::func_lj_tab_new (L, 0 , 0 )));
638+
639+ if (!bFresh)
640+ { // lj_gc_objbarrier unwrapped since we need to ensure this.
641+ if (((((GCobj*)(gcref (usertable))))->gch .marked & (0x01 | 0x02 )) && ((((GCobj*)(this )))->gch .marked & 0x04 ))
642+ Util::func_lj_gc_barrierf (G (L), ((GCobj*)(this )), ((GCobj*)(gcref (usertable))));
643+ }
589644 } else {
590645 pLua->CreateTable ();
591- setgcref (usertable, obj2gco (tabV (L->top -1 )));
646+ if (!bFresh)
647+ {
648+ if (Util::func_lj_gc_barrierf)
649+ {
650+ setgcref (usertable, obj2gco (tabV (L->top -1 )));
651+
652+ { // lj_gc_objbarrier unwrapped since we need to ensure this.
653+ if (((((GCobj*)(gcref (usertable))))->gch .marked & (0x01 | 0x02 )) && ((((GCobj*)(this )))->gch .marked & 0x04 ))
654+ Util::func_lj_gc_barrierf (G (L), ((GCobj*)(this )), ((GCobj*)(gcref (usertable))));
655+ }
656+ } else {
657+ Util::func_lua_setfenv (L, -2 ); // Internally has the gc barrier
658+ }
659+ } else {
660+ setgcref (usertable, obj2gco (tabV (L->top -1 )));
661+ }
592662 pLua->Pop (1 );
593663 }
594664 }
0 commit comments