Ejemplo n.º 1
0
/*
** if object 'o' has a finalizer, remove it from 'allgc' list (must
** search the list to find it) and link it in 'finobj' list.
*/
void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
	global_State *g = G(L);
	if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */
		isfinalized(o) ||                           /* ... or is finalized... */
		gfasttm(g, mt, TM_GC) == NULL)                /* or has no finalizer? */
	return;  /* nothing to be done */
	else {  /* move 'o' to 'finobj' list */
	GCObject **p;
	GCheader *ho = gch(o);
	if (g->sweepgc == &ho->next) {  /* avoid removing current sweep object */
		lua_assert(issweepphase(g));
		g->sweepgc = sweeptolive(L, g->sweepgc, NULL);
	}
	/* search for pointer pointing to 'o' */
	for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ }
	*p = ho->next;  /* remove 'o' from root list */
	ho->next = g->finobj;  /* link it in list 'finobj' */
	g->finobj = o;
	l_setbit(ho->marked, SEPARATED);  /* mark it as such */
	if (!keepinvariantout(g))  /* not keeping invariant? */
		makewhite(g, o);  /* "sweep" object */
	else
		resetoldbit(o);  /* see MOVE OLD rule */
	}
}
Ejemplo n.º 2
0
/* move `dead' udata that need finalization to list `tmudata' */
size_t luaC_separateudata (lua_State *L, int all) {
  global_State *g = G(L);
  size_t deadmem = 0;
  GCObject **p = &g->mainthread->next;
  GCObject *curr;
  while ((curr = *p) != NULL) {
    if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
      p = &curr->gch.next;  /* don't bother with them */
    else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
      markfinalized(gco2u(curr));  /* don't need finalization */
      p = &curr->gch.next;
    }
    else {  /* must call its gc method */
      deadmem += sizeudata(gco2u(curr));
      markfinalized(gco2u(curr));
      *p = curr->gch.next;
      /* link `curr' at the end of `tmudata' list */
      if (g->tmudata == NULL)  /* list is empty? */
        g->tmudata = curr->gch.next = curr;  /* creates a circular list */
      else {
        curr->gch.next = g->tmudata->gch.next;
        g->tmudata->gch.next = curr;
        g->tmudata = curr;
      }
    }
  }
  return deadmem;
}
Ejemplo n.º 3
0
/* move `dead' udata that need finalization to list `tmudata' */
size_t luaC_separateudata (lua_State *L) {
    size_t deadmem = 0;
    GCObject **p = &G(L)->rootudata;
    GCObject *curr;
    GCObject *collected = NULL;  /* to collect udata with gc event */
    GCObject **lastcollected = &collected;
    while ((curr = *p) != NULL) {
        lua_assert(curr->gch.tt == LUA_TUSERDATA);
        if (ismarked(curr) || isfinalized(gcotou(curr)))
            p = &curr->gch.next;  /* don't bother with them */

        else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) {
            markfinalized(gcotou(curr));  /* don't need finalization */
            p = &curr->gch.next;
        }
        else {  /* must call its gc method */
            deadmem += sizeudata(gcotou(curr)->uv.len);
            *p = curr->gch.next;
            curr->gch.next = NULL;  /* link `curr' at the end of `collected' list */
            *lastcollected = curr;
            lastcollected = &curr->gch.next;
        }
    }
    /* insert collected udata with gc event into `tmudata' list */
    *lastcollected = G(L)->tmudata;
    G(L)->tmudata = collected;
    return deadmem;
}
Ejemplo n.º 4
0
/*
** The next function tells whether a key or value can be cleared from
** a weak table. Non-collectable objects are never removed from weak
** tables. Strings behave as `values', so are never removed too. for
** other objects: if really collected, cannot keep them; for userdata
** being finalized, keep them in keys, but not in values
*/
static int iscleared (const TValue *o, int iskey) {
  if (!iscollectable(o)) return 0;
  if (ttisstring(o)) {
    stringmark(rawtsvalue(o));  /* strings are `values', so are never weak */
    return 0;
  }
  return iswhite(gcvalue(o)) ||
    (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));
}
Ejemplo n.º 5
0
static GCObject *udata2finalize (global_State *g) {
	GCObject *o = g->tobefnz;  /* get first element */
	lua_assert(isfinalized(o));
	g->tobefnz = gch(o)->next;  /* remove it from 'tobefnz' list */
	gch(o)->next = g->allgc;  /* return it to 'allgc' list */
	g->allgc = o;
	resetbit(gch(o)->marked, SEPARATED);  /* mark that it is not in 'tobefnz' */
	lua_assert(!isold(o));  /* see MOVE OLD rule */
	if (!keepinvariantout(g))  /* not keeping invariant? */
	makewhite(g, o);  /* "sweep" object */
	return o;
}
Ejemplo n.º 6
0
/*
** if object 'o' has a finalizer, remove it from 'allgc' list (must
** search the list to find it) and link it in 'finobj' list.
*/
void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
  global_State *g = G(L);
  if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */
      isfinalized(o) ||                           /* ... or is finalized... */
      gfasttm(g, mt, TM_GC) == NULL)                /* or has no finalizer? */
    return;  /* nothing to be done */
  else {  /* move 'o' to 'finobj' list */
    GCObject **p;
    for (p = &g->allgc; *p != o; p = &gch(*p)->next) ;
    *p = gch(o)->next;  /* remove 'o' from root list */
    gch(o)->next = g->finobj;  /* link it in list 'finobj' */
    g->finobj = o;
    l_setbit(gch(o)->marked, SEPARATED);  /* mark it as such */
    resetoldbit(o);  /* see MOVE OLD rule */
  }
}
Ejemplo n.º 7
0
/*
** move all unreachable objects (or 'all' objects) that need
** finalization from list 'finobj' to list 'tobefnz' (to be finalized)
*/
static void separatetobefnz (lua_State *L, int all) {
	global_State *g = G(L);
	GCObject **p = &g->finobj;
	GCObject *curr;
	GCObject **lastnext = &g->tobefnz;
	/* find last 'next' field in 'tobefnz' list (to add elements in its end) */
	while (*lastnext != NULL)
	lastnext = &gch(*lastnext)->next;
	while ((curr = *p) != NULL) {  /* traverse all finalizable objects */
	lua_assert(!isfinalized(curr));
	lua_assert(testbit(gch(curr)->marked, SEPARATED));
	if (!(iswhite(curr) || all))  /* not being collected? */
		p = &gch(curr)->next;  /* don't bother with it */
	else {
		l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */
		*p = gch(curr)->next;  /* remove 'curr' from 'finobj' list */
		gch(curr)->next = *lastnext;  /* link at the end of 'tobefnz' list */
		*lastnext = curr;
		lastnext = &gch(curr)->next;
	}
	}
}
Ejemplo n.º 8
0
Archivo: lgc.c Proyecto: gitrider/wxsj2
static void marktmu (GCState *st) {
  GCObject *u;
#if LUA_REFCOUNT
  for (u = st->g->tmudata_head.next; u != (GCObject*)&st->g->tmudata_tail; u = u->gch.next) {
#else !LUA_REFCOUNT
  for (u = st->g->tmudata; u; u = u->gch.next) {
#endif LUA_REFCOUNT
    unmark(u);  /* may be marked, if left from previous GC */
    reallymarkobject(st, u);
  }
}


/* move `dead' udata that need finalization to list `tmudata' */
size_t luaC_separateudata (lua_State *L) {
  size_t deadmem = 0;
#if LUA_REFCOUNT
  GCObject **p = &G(L)->rootudata_head.next;
#else !LUA_REFCOUNT
  GCObject **p = &G(L)->rootudata;
#endif LUA_REFCOUNT
  GCObject *curr;
  GCObject *collected = NULL;  /* to collect udata with gc event */
#if !LUA_REFCOUNT
  GCObject **lastcollected = &collected;
  while ((curr = *p) != NULL) {
    lua_assert(curr->gch.tt == LUA_TUSERDATA);
#else LUA_REFCOUNT
  while ((curr = *p) != (GCObject*)&G(L)->rootudata_tail) {
#endif LUA_REFCOUNT
    if (ismarked(curr) || isfinalized(gcotou(curr)))
      p = &curr->gch.next;  /* don't bother with them */

    else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) {
      markfinalized(gcotou(curr));  /* don't need finalization */
      p = &curr->gch.next;
    }
    else {  /* must call its gc method */
      deadmem += sizeudata(gcotou(curr)->uv.len);
      *p = curr->gch.next;
#if LUA_REFCOUNT
	  Unlink(curr);
	  curr->gch.next = (GCObject*)&G(L)->tmudata_tail;  /* link `curr' at the end of `collected' list */
	  curr->gch.prev = G(L)->tmudata_tail.prev;
	  G(L)->tmudata_tail.prev->gch.next = curr;
      G(L)->tmudata_tail.prev = curr;
#else !LUA_REFCOUNT
	  curr->gch.next = NULL;  /* link `curr' at the end of `collected' list */
      *lastcollected = curr;
      lastcollected = &curr->gch.next;
#endif LUA_REFCOUNT
    }
  }
  /* insert collected udata with gc event into `tmudata' list */
#if LUA_REFCOUNT
//  *lastcollected = G(L)->tmudata_head.next;
//  G(L)->tmudata_head.next = collected;
#else !LUA_REFCOUNT
  *lastcollected = G(L)->tmudata;
  G(L)->tmudata = collected;
#endif LUA_REFCOUNT
  return deadmem;
}


static void removekey (lua_State *L, Node *n) {
  (void)L;
  setnilvalue(gval(n));  /* remove corresponding value ... */
  if (iscollectable(gkey(n)))
    setttype(gkey(n), LUA_TNONE);  /* dead key; remove it */
}