void ponyint_mark_done(pony_ctx_t* ctx) { ponyint_gc_markimmutable(ctx, ponyint_actor_gc(ctx->current)); ponyint_gc_handlestack(ctx); ponyint_gc_sendacquire(ctx); ponyint_gc_sweep(ctx, ponyint_actor_gc(ctx->current)); ponyint_gc_done(ponyint_actor_gc(ctx->current)); }
static void release_local_object(pony_ctx_t* ctx, void* p, pony_type_t* t, int mutability) { size_t index = HASHMAP_UNKNOWN; gc_t* gc = ponyint_actor_gc(ctx->current); object_t* obj = ponyint_objectmap_getobject(&gc->local, p, &index); pony_assert(obj != NULL); if(obj->mark == gc->mark) return; // Implicitly release the owner. release_local_actor(gc); obj->rc--; obj->mark = gc->mark; if(mutability == PONY_TRACE_OPAQUE) return; if(mutability == PONY_TRACE_IMMUTABLE) obj->immutable = true; if(!obj->immutable) recurse(ctx, p, t->trace); }
static void send_local_object(pony_ctx_t* ctx, void* p, pony_type_t* t, int mutability) { gc_t* gc = ponyint_actor_gc(ctx->current); object_t* obj = ponyint_objectmap_getorput(&gc->local, p, gc->mark); if(obj->mark == gc->mark) return; // Implicitly send the owner. send_local_actor(gc); // Inc, mark, and recurse if not immutable. obj->rc++; obj->mark = gc->mark; if(mutability == PONY_TRACE_OPAQUE) return; if(mutability == PONY_TRACE_IMMUTABLE) obj->immutable = true; if(!obj->immutable) recurse(ctx, p, t->trace); }
static void acq_or_rel_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(&ctx->acquire, actor, 0); object_t* obj = ponyint_actorref_getorput(aref, p, gc->mark); if(obj->mark == gc->mark) return; // Implicitly acquire/release the owner. acq_or_rel_remote_actor(ctx, actor); obj->rc++; obj->mark = gc->mark; if(mutability == PONY_TRACE_OPAQUE) return; if(mutability == PONY_TRACE_IMMUTABLE) obj->immutable = true; if(!obj->immutable) recurse(ctx, p, t->trace); }
void ponyint_gc_releaseactor(pony_ctx_t* ctx, pony_actor_t* actor) { if(actor == ctx->current) release_local_actor(ponyint_actor_gc(ctx->current)); else acq_or_rel_remote_actor(ctx, actor); }
static void recv_local_object(pony_ctx_t* ctx, void* p, pony_trace_fn f, bool immutable) { // get the object gc_t* gc = ponyint_actor_gc(ctx->current); object_t* obj = ponyint_objectmap_getobject(&gc->local, p); assert(obj != NULL); if(obj->mark == gc->mark) return; // Implicitly receive the owner. recv_local_actor(gc); // Dec, mark and recurse. Mark as reachable from the actor, since a // release message for this object could arrive before a gc pass. obj->rc--; obj->mark = gc->mark; obj->reachable = true; if(immutable) obj->immutable = true; if(!obj->immutable) recurse(ctx, p, f); }
static void recv_remote_object(pony_ctx_t* ctx, pony_actor_t* actor, void* p, pony_trace_fn f, bool immutable, chunk_t* chunk) { 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 receive the owner. recv_remote_actor(ctx, gc, aref); // If this is our first reference, add to our heap used size. if(obj->rc == 0) ponyint_heap_used(ponyint_actor_heap(ctx->current), ponyint_heap_size(chunk)); // Inc, mark and recurse. obj->rc++; obj->mark = gc->mark; if(immutable) obj->immutable = true; if(!obj->immutable) recurse(ctx, p, f); }
void pony_recv_done(pony_ctx_t* ctx) { ponyint_gc_handlestack(ctx); ponyint_gc_done(ponyint_actor_gc(ctx->current)); DTRACE1(GC_RECV_END, (uintptr_t)ctx->scheduler); }
void ponyint_gc_createactor(pony_actor_t* current, pony_actor_t* actor) { gc_t* gc = ponyint_actor_gc(current); actorref_t* aref = ponyint_actormap_getorput(&gc->foreign, actor, gc->mark); aref->rc = GC_INC_MORE; gc->delta = ponyint_deltamap_update(gc->delta, actor, aref->rc); ponyint_heap_used(ponyint_actor_heap(current), GC_ACTOR_HEAP_EQUIV); }
void pony_send_done(pony_ctx_t* ctx) { ponyint_gc_handlestack(ctx); ponyint_gc_sendacquire(ctx); ponyint_gc_done(ponyint_actor_gc(ctx->current)); DTRACE1(GC_SEND_END, (uintptr_t)ctx->scheduler); }
void ponyint_gc_markactor(pony_ctx_t* ctx, pony_actor_t* actor) { if(actor == ctx->current) return; gc_t* gc = ponyint_actor_gc(ctx->current); actorref_t* aref = ponyint_actormap_getactor(&gc->foreign, actor); mark_remote_actor(ctx, gc, aref); }
void pony_recv_done(pony_ctx_t* ctx) { ponyint_gc_handlestack(ctx); ponyint_gc_done(ponyint_actor_gc(ctx->current)); #ifdef USE_TELEMETRY ctx->time_in_recv_scan += (ponyint_cpu_tick() - ctx->tsc); #endif }
void ponyint_gc_recvactor(pony_ctx_t* ctx, pony_actor_t* actor) { gc_t* gc = ponyint_actor_gc(ctx->current); if(actor == ctx->current) { recv_local_actor(gc); } else { actorref_t* aref = ponyint_actormap_getorput(&gc->foreign, actor, gc->mark); recv_remote_actor(ctx, gc, aref); } }
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); }
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_local_object(pony_ctx_t* ctx, void* p, pony_trace_fn f, bool immutable) { gc_t* gc = ponyint_actor_gc(ctx->current); object_t* obj = ponyint_objectmap_getorput(&gc->local, p, gc->mark); if(obj->mark == gc->mark) return; // Implicitly send the owner. send_local_actor(gc); // Inc, mark, and recurse if not immutable. obj->rc++; obj->mark = gc->mark; if(immutable) obj->immutable = true; if(!obj->immutable) recurse(ctx, p, f); }
static void recv_remote_object(pony_ctx_t* ctx, pony_actor_t* actor, void* p, pony_type_t* t, int mutability, chunk_t* chunk) { 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 receive the owner. recv_remote_actor(ctx, gc, aref); if(obj->rc == 0) { // Increase apparent used memory to provoke GC. ponyint_heap_used(ponyint_actor_heap(ctx->current), ponyint_heap_size(chunk)); // Increase apparent used memory further if the object is immutable, to // account for memory that is reachable but not traced by this actor. if(mutability == PONY_TRACE_IMMUTABLE) ponyint_heap_used(ponyint_actor_heap(ctx->current), GC_IMMUT_HEAP_EQUIV); } // Inc, mark and recurse. obj->rc++; obj->mark = gc->mark; if(mutability == PONY_TRACE_OPAQUE) return; if(mutability == PONY_TRACE_IMMUTABLE) obj->immutable = true; if(!obj->immutable) recurse(ctx, p, t->trace); }
void pony_send_next(pony_ctx_t* ctx) { ponyint_gc_handlestack(ctx); ponyint_gc_done(ponyint_actor_gc(ctx->current)); }
ponyint_actormap_destroy(&ctx->acquire); memset(&ctx->acquire, 0, sizeof(actormap_t)); } void ponyint_gc_sendrelease(pony_ctx_t* ctx, gc_t* gc) { gc->delta = ponyint_actormap_sweep(ctx, &gc->foreign, gc->mark, gc->delta); } void ponyint_gc_register_final(pony_ctx_t* ctx, void* p, pony_final_fn final) { if(!ctx->finalising) { // If we aren't finalising an actor, register the finaliser. gc_t* gc = ponyint_actor_gc(ctx->current); ponyint_objectmap_register_final(&gc->local, p, final, gc->mark); gc->finalisers++; } else { // Otherwise, put the finaliser on the gc stack. recurse(ctx, p, final); } } void ponyint_gc_final(pony_ctx_t* ctx, gc_t* gc) { if(gc->finalisers == 0) return; // Set the finalising flag. ctx->finalising = true;
void pony_acquire_done(pony_ctx_t* ctx) { ponyint_gc_handlestack(ctx); ponyint_gc_sendacquire(ctx); ponyint_gc_done(ponyint_actor_gc(ctx->current)); }
void pony_release_done(pony_ctx_t* ctx) { ponyint_gc_handlestack(ctx); ponyint_gc_sendrelease_manual(ctx); ponyint_gc_done(ponyint_actor_gc(ctx->current)); }