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); }
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); }
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); } } } }