|
@@ -356,32 +356,30 @@ static void checkMbuffer (lua_State *L) {
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void callgcTM (lua_State *L, Udata *udata) {
|
|
|
+static void do1gcTM (lua_State *L, Udata *udata) {
|
|
|
const TObject *tm = fasttm(L, udata->uv.eventtable, TM_GC);
|
|
|
- if (tm != NULL && ttype(tm) == LUA_TFUNCTION) {
|
|
|
- int oldah = L->allowhooks;
|
|
|
+ if (tm != NULL) {
|
|
|
StkId top = L->top;
|
|
|
- L->allowhooks = 0; /* stop debug hooks during GC tag methods */
|
|
|
setobj(top, tm);
|
|
|
setuvalue(top+1, udata);
|
|
|
L->top += 2;
|
|
|
luaD_call(L, top);
|
|
|
L->top = top; /* restore top */
|
|
|
- L->allowhooks = oldah; /* restore hooks */
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void callgcTMudata (lua_State *L) {
|
|
|
+static void unprotectedcallGCTM (lua_State *L, void *pu) {
|
|
|
luaD_checkstack(L, 3);
|
|
|
L->top++; /* reserve space to keep udata while runs its gc method */
|
|
|
while (G(L)->tmudata != NULL) {
|
|
|
Udata *udata = G(L)->tmudata;
|
|
|
G(L)->tmudata = udata->uv.next; /* remove udata from list */
|
|
|
+ *(Udata **)pu = udata; /* keep a reference to it (in case of errors) */
|
|
|
+ setuvalue(L->top - 1, udata); /* and on stack (in case of recursive GC) */
|
|
|
udata->uv.next = G(L)->rootudata; /* resurect it */
|
|
|
G(L)->rootudata = udata;
|
|
|
- setuvalue(L->top - 1, udata);
|
|
|
- callgcTM(L, udata);
|
|
|
+ do1gcTM(L, udata);
|
|
|
/* mark udata as finalized (default event table) */
|
|
|
uvalue(L->top-1)->uv.eventtable = hvalue(defaultet(L));
|
|
|
}
|
|
@@ -389,11 +387,26 @@ static void callgcTMudata (lua_State *L) {
|
|
|
}
|
|
|
|
|
|
|
|
|
+static void callGCTM (lua_State *L) {
|
|
|
+ int oldah = L->allowhooks;
|
|
|
+ L->allowhooks = 0; /* stop debug hooks during GC tag methods */
|
|
|
+ while (G(L)->tmudata != NULL) {
|
|
|
+ Udata *udata;
|
|
|
+ if (luaD_runprotected(L, unprotectedcallGCTM, &udata) != 0) {
|
|
|
+ /* `udata' generated an error during its gc */
|
|
|
+ /* mark it as finalized (default event table) */
|
|
|
+ udata->uv.eventtable = hvalue(defaultet(L));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ L->allowhooks = oldah; /* restore hooks */
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
void luaC_callallgcTM (lua_State *L) {
|
|
|
lua_assert(G(L)->tmudata == NULL);
|
|
|
G(L)->tmudata = G(L)->rootudata; /* all udata must be collected */
|
|
|
G(L)->rootudata = NULL;
|
|
|
- callgcTMudata(L); /* call their GC tag methods */
|
|
|
+ callGCTM(L); /* call their GC tag methods */
|
|
|
}
|
|
|
|
|
|
|
|
@@ -416,6 +429,6 @@ void luaC_collectgarbage (lua_State *L) {
|
|
|
luaC_collect(L, 0);
|
|
|
checkMbuffer(L);
|
|
|
G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */
|
|
|
- callgcTMudata(L);
|
|
|
+ callGCTM(L);
|
|
|
}
|
|
|
|