move `dead' udata that need finalization to list `tmudata' */
| 6128 | |
| 6129 | /* move `dead' udata that need finalization to list `tmudata' */ |
| 6130 | size_t luaC_separateudata (lua_State *L, int all) { |
| 6131 | global_State *g = G(L); |
| 6132 | size_t deadmem = 0; |
| 6133 | GCObject **p = &g->mainthread->next; |
| 6134 | GCObject *curr; |
| 6135 | while ((curr = *p) != NULL) { |
| 6136 | if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) |
| 6137 | p = &curr->gch.next; /* don't bother with them */ |
| 6138 | else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { |
| 6139 | markfinalized(gco2u(curr)); /* don't need finalization */ |
| 6140 | p = &curr->gch.next; |
| 6141 | } |
| 6142 | else { /* must call its gc method */ |
| 6143 | deadmem += sizeudata(gco2u(curr)); |
| 6144 | markfinalized(gco2u(curr)); |
| 6145 | *p = curr->gch.next; |
| 6146 | /* link `curr' at the end of `tmudata' list */ |
| 6147 | if (g->tmudata == NULL) /* list is empty? */ |
| 6148 | g->tmudata = curr->gch.next = curr; /* creates a circular list */ |
| 6149 | else { |
| 6150 | curr->gch.next = g->tmudata->gch.next; |
| 6151 | g->tmudata->gch.next = curr; |
| 6152 | g->tmudata = curr; |
| 6153 | } |
| 6154 | } |
| 6155 | } |
| 6156 | return deadmem; |
| 6157 | } |
| 6158 | |
| 6159 | |
| 6160 | static int traversetable (global_State *g, Table *h) { |