move `dead' udata that need finalization to list `tmudata' */
| 126 | |
| 127 | /* move `dead' udata that need finalization to list `tmudata' */ |
| 128 | size_t luaC_separateudata (lua_State *L, int all) { |
| 129 | global_State *g = G(L); |
| 130 | size_t deadmem = 0; |
| 131 | GCObject **p = &g->mainthread->next; |
| 132 | GCObject *curr; |
| 133 | while ((curr = *p) != NULL) { |
| 134 | if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) |
| 135 | p = &curr->gch.next; /* don't bother with them */ |
| 136 | else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { |
| 137 | markfinalized(gco2u(curr)); /* don't need finalization */ |
| 138 | p = &curr->gch.next; |
| 139 | } |
| 140 | else { /* must call its gc method */ |
| 141 | deadmem += sizeudata(gco2u(curr)); |
| 142 | markfinalized(gco2u(curr)); |
| 143 | *p = curr->gch.next; |
| 144 | /* link `curr' at the end of `tmudata' list */ |
| 145 | if (g->tmudata == NULL) /* list is empty? */ |
| 146 | g->tmudata = curr->gch.next = curr; /* creates a circular list */ |
| 147 | else { |
| 148 | curr->gch.next = g->tmudata->gch.next; |
| 149 | g->tmudata->gch.next = curr; |
| 150 | g->tmudata = curr; |
| 151 | } |
| 152 | } |
| 153 | } |
| 154 | return deadmem; |
| 155 | } |
| 156 | |
| 157 | |
| 158 | static int traversetable (global_State *g, Table *h) { |