Пример #1
0
Файл: gc.c Проект: ozra/ponyc
void gc_markobject(pony_actor_t* current, heap_t* heap, gc_t* gc,
                   void* p, pony_trace_fn f)
{
    chunk_t* chunk = (chunk_t*)pagemap_get(p);

    // don't gc memory that wasn't pony_allocated
    if(chunk == NULL)
        return;

    pony_actor_t* actor = heap_owner(chunk);
    size_t objsize = heap_base(chunk, &p);

    if(actor == current)
    {
        if(f != NULL)
        {
            // mark in our heap and recurse if it wasn't already marked
            if(!heap_mark(chunk, p))
            {
                stack = gcstack_push(stack, p);
                stack = gcstack_push(stack, f);
            }
        } else {
            // no recurse function, so do a shallow mark. if the same address is
            // later marked with a recurse function, it will recurse.
            heap_mark_shallow(chunk, p);
        }
    } else {
        // mark the owner
        actorref_t* aref = actormap_getactor(&gc->foreign, actor);

        // we've reached this by tracing a tag through a union
        if(aref == NULL)
            return;

        // get the object
        object_t* obj = actorref_getobject(aref, p);

        // we've reached this by tracing a tag through a union
        if(obj == NULL)
            return;

        actorref_mark(aref, gc->mark);

        if(!object_marked(obj, gc->mark))
        {
            // add to heap used size
            heap_used(heap, objsize);

            // mark and recurse
            object_mark(obj, gc->mark);

            if(f != NULL)
            {
                stack = gcstack_push(stack, p);
                stack = gcstack_push(stack, f);
            }
        }
    }
}
Пример #2
0
void* heap_realloc(pony_actor_t* actor, heap_t* heap, void* p, size_t size)
{
  if(p == NULL)
    return heap_alloc(actor, heap, size);

  chunk_t* chunk = (chunk_t*)pagemap_get(p);

  if(chunk == NULL)
  {
    // Get new memory and copy from the old memory.
    void* q = heap_alloc(actor, heap, size);
    memcpy(q, p, size);
    return q;
  }

  if(chunk->size < HEAP_SIZECLASSES)
  {
    // Previous allocation was a heap_alloc_small.
    if(size <= HEAP_MAX)
    {
      uint32_t sizeclass = heap_index(size);

      // If the new allocation is the same size or smaller, return the old one.
      if(sizeclass <= chunk->size)
        return p;
    }

    // Get new memory and copy from the old memory.
    void* q = heap_alloc(actor, heap, size);
    memcpy(q, p, SIZECLASS_SIZE(chunk->size));
    return q;
  }

  // Previous allocation was a heap_alloc_large.
  if(size <= chunk->size)
    return p;

  // Get new memory and copy from the old memory.
  void* q = heap_alloc(actor, heap, size);
  memcpy(q, p, chunk->size);
  return q;
}
Пример #3
0
Файл: gc.c Проект: ozra/ponyc
void gc_sendobject(pony_actor_t* current, heap_t* heap, gc_t* gc,
                   void* p, pony_trace_fn f)
{
    (void)heap;
    chunk_t* chunk = (chunk_t*)pagemap_get(p);

    // don't gc memory that wasn't pony_allocated
    if(chunk == NULL)
        return;

    pony_actor_t* actor = heap_owner(chunk);
    heap_base(chunk, &p);

    if(actor == current)
    {
        current_actor_inc(gc);

        // get the object
        object_t* obj = objectmap_getorput(&gc->local, p, gc->mark);

        if(!object_marked(obj, gc->mark))
        {
            // inc, mark and recurse
            object_inc(obj);
            object_mark(obj, gc->mark);

            if(f != NULL)
            {
                stack = gcstack_push(stack, p);
                stack = gcstack_push(stack, f);
            }
        }
    } else {
        // get the actor
        actorref_t* aref = actormap_getactor(&gc->foreign, actor);

        // we've reached this by tracing a tag through a union
        if(aref == NULL)
            return;

        // get the object
        object_t* obj = actorref_getobject(aref, p);

        // we've reached this by tracing a tag through a union
        if(obj == NULL)
            return;

        if(!actorref_marked(aref, gc->mark))
        {
            // dec. if we can't, we need to build an acquire message
            if(!actorref_dec(aref))
            {
                actorref_inc_more(aref);
                acquire_actor(actor);
            }

            actorref_mark(aref, gc->mark);
            gc->delta = deltamap_update(gc->delta,
                                        actorref_actor(aref), actorref_rc(aref));
        }

        if(!object_marked(obj, gc->mark))
        {
            // dec. if we can't, we need to build an acquire message
            if(!object_dec(obj))
            {
                object_inc_more(obj);
                acquire_object(actor, p);
            }

            object_mark(obj, gc->mark);

            if(f != NULL)
            {
                stack = gcstack_push(stack, p);
                stack = gcstack_push(stack, f);
            }
        }
    }
}
Пример #4
0
Файл: gc.c Проект: ozra/ponyc
void gc_recvobject(pony_actor_t* current, heap_t* heap, gc_t* gc,
                   void* p, pony_trace_fn f)
{
    chunk_t* chunk = (chunk_t*)pagemap_get(p);

    // don't gc memory that wasn't pony_allocated
    if(chunk == NULL)
        return;

    pony_actor_t* actor = heap_owner(chunk);
    size_t objsize = heap_base(chunk, &p);

    if(actor == current)
    {
        current_actor_dec(gc);

        // get the object
        object_t* obj = objectmap_getobject(&gc->local, p);
        assert(obj != NULL);

        if(!object_marked(obj, gc->mark))
        {
            // dec, mark and recurse
            object_dec(obj);
            object_mark(obj, gc->mark);

            if(f != NULL)
            {
                stack = gcstack_push(stack, p);
                stack = gcstack_push(stack, f);
            }
        }
    } else {
        // get the actor
        actorref_t* aref = actormap_getorput(&gc->foreign, actor, gc->mark);

        if(!actorref_marked(aref, gc->mark))
        {
            // inc and mark
            actorref_inc(aref);
            actorref_mark(aref, gc->mark);
            gc->delta = deltamap_update(gc->delta,
                                        actorref_actor(aref), actorref_rc(aref));
        }

        // get the object
        object_t* obj = actorref_getorput(aref, p, gc->mark);

        if(!object_marked(obj, gc->mark))
        {
            // if this is our first reference, add to our heap used size
            if(object_rc(obj) == 0)
                heap_used(heap, objsize);

            // inc, mark and recurse
            object_inc(obj);
            object_mark(obj, gc->mark);

            if(f != NULL)
            {
                stack = gcstack_push(stack, p);
                stack = gcstack_push(stack, f);
            }
        }
    }
}