예제 #1
0
파일: gc.c 프로젝트: killerswan/ponyc
static void send_remote_object(pony_ctx_t* ctx, pony_actor_t* actor,
  void* p, pony_type_t* t, int mutability)
{
  gc_t* gc = ponyint_actor_gc(ctx->current);
  actorref_t* aref = ponyint_actormap_getorput(&gc->foreign, actor, gc->mark);
  object_t* obj = ponyint_actorref_getorput(aref, p, gc->mark);

  if(obj->mark == gc->mark)
    return;

  // Implicitly send the owner.
  send_remote_actor(ctx, gc, aref);

  // Mark the object.
  obj->mark = gc->mark;

  if((mutability == PONY_TRACE_IMMUTABLE) && !obj->immutable && (obj->rc > 0))
  {
    // If we received the object as not immutable (it's not marked as immutable
    // and it has an RC > 0), but we are now sending it as immutable, we need
    // to acquire it in order to inform the owner it is now immutable. But we
    // also need to continue tracing, to protect the contents until the owner
    // has received the acquire messages.
    obj->rc += (GC_INC_MORE - 1);
    obj->immutable = true;
    acquire_object(ctx, actor, p, true);

    // Set the to PONY_TRACE_MUTABLE to force recursion.
    mutability = PONY_TRACE_MUTABLE;
  } else if(obj->rc <= 1) {
    // If we haven't seen this object, it's an object that is reached from
    // another immutable object we received, or it's a pointer to an embedded
    // field received in an iso. Invent some references to this object and
    // acquire it.
    if(mutability == PONY_TRACE_IMMUTABLE)
      obj->immutable = true;

    // Add to the acquire message and decrement.
    obj->rc += (GC_INC_MORE - 1);
    acquire_object(ctx, actor, p, obj->immutable);
  } else {
    // Decrement.
    obj->rc--;
  }

  if(mutability == PONY_TRACE_MUTABLE)
    recurse(ctx, p, t->trace);
}
예제 #2
0
파일: gc.c 프로젝트: cyisfor/ponyc
static void send_remote_object(pony_ctx_t* ctx, pony_actor_t* actor,
  void* p, pony_trace_fn f, bool immutable)
{
  gc_t* gc = ponyint_actor_gc(ctx->current);
  actorref_t* aref = ponyint_actormap_getorput(&gc->foreign, actor, gc->mark);
  object_t* obj = ponyint_actorref_getorput(aref, p, gc->mark);

  if(obj->mark == gc->mark)
    return;

  // Implicitly send the owner.
  send_remote_actor(ctx, gc, aref);

  // Mark the object.
  obj->mark = gc->mark;

  if(immutable && !obj->immutable && (obj->rc > 0))
  {
    // If we received the object as not immutable (it's not marked as immutable
    // and it has an RC > 0), but we are now sending it as immutable, we need
    // to acquire it in order to inform the owner it is now immutable. But we
    // also need to continue tracing, to protect the contents until the owner
    // has received the acquire messages.
    obj->rc += (GC_INC_MORE - 1);
    obj->immutable = true;
    acquire_object(ctx, actor, p, true);

    immutable = false;
  } else if(obj->rc <= 1) {
    // If we haven't seen this object, it's an object that is reached from
    // another immutable object we received. Invent some references to this
    // object and acquire it. This object should either be immutable or a tag.
    assert((obj->rc > 0) || immutable || (f == NULL));

    // Add to the acquire message and decrement.
    if(immutable)
      obj->immutable = true;

    obj->rc += (GC_INC_MORE - 1);
    acquire_object(ctx, actor, p, obj->immutable);
  } else {
    // Decrement.
    obj->rc--;
  }

  if(!immutable)
    recurse(ctx, p, f);
}
예제 #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);
            }
        }
    }
}