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