static actorref_t* move_unmarked_objects(actorref_t* from, uint32_t mark) { size_t size = ponyint_objectmap_size(&from->map); if(size == 0) return NULL; actorref_t* to = NULL; size_t i = HASHMAP_BEGIN; object_t* obj; bool needs_optimize = false; while((obj = ponyint_objectmap_next(&from->map, &i)) != NULL) { if(obj->mark == mark) continue; ponyint_objectmap_clearindex(&from->map, i); needs_optimize = true; if(to == NULL) { // Guarantee we don't resize during insertion. to = actorref_alloc(from->actor, mark); ponyint_objectmap_init(&to->map, size); } ponyint_objectmap_put(&to->map, obj); } if(needs_optimize) ponyint_objectmap_optimize(&from->map); return to; }
bool ponyint_gc_release(gc_t* gc, actorref_t* aref) { size_t rc = aref->rc; assert(gc->rc >= rc); gc->rc -= rc; objectmap_t* map = &aref->map; size_t i = HASHMAP_BEGIN; object_t* obj; while((obj = ponyint_objectmap_next(map, &i)) != NULL) { void* p = obj->address; object_t* obj_local = ponyint_objectmap_getobject(&gc->local, p); assert(obj_local->rc >= obj->rc); obj_local->rc -= obj->rc; if(obj_local->rc == 0) { // The local rc for this object has dropped to zero. We keep track of // whether or not the object was reachable. If we go to 0 rc and it // wasn't reachable, we free it. If we receive the object in a message, // mark it as reachable again. if(!obj_local->reachable) { chunk_t* chunk = (chunk_t*)ponyint_pagemap_get(p); ponyint_heap_free(chunk, p); } } } ponyint_actorref_free(aref); return rc > 0; }
bool ponyint_gc_acquire(gc_t* gc, actorref_t* aref) { size_t rc = aref->rc; gc->rc += rc; objectmap_t* map = &aref->map; size_t i = HASHMAP_BEGIN; object_t* obj; while((obj = ponyint_objectmap_next(map, &i)) != NULL) { // Add to our RC. The object may not be in our object map, if it was // reached through another immutable reference. object_t* obj_local = ponyint_objectmap_getorput(&gc->local, obj->address, gc->mark); obj_local->rc += obj->rc; // Mark as immutable if necessary. if(obj->immutable) obj_local->immutable = true; } ponyint_actorref_free(aref); return rc > 0; }
void ponyint_gc_markimmutable(pony_ctx_t* ctx, gc_t* gc) { objectmap_t* map = &gc->local; size_t i = HASHMAP_BEGIN; object_t* obj; while((obj = ponyint_objectmap_next(map, &i)) != NULL) { if(obj->immutable && (obj->rc > 0)) { // Mark in our heap and recurse if it wasn't already marked. void* p = obj->address; chunk_t* chunk = (chunk_t*)ponyint_pagemap_get(p); pony_type_t* type = *(pony_type_t**)p; mark_local_object(ctx, chunk, p, type->trace); } } }
bool ponyint_gc_release(gc_t* gc, actorref_t* aref) { size_t rc = aref->rc; pony_assert(gc->rc >= rc); gc->rc -= rc; objectmap_t* map = &aref->map; size_t i = HASHMAP_BEGIN; object_t* obj; size_t index = HASHMAP_UNKNOWN; while((obj = ponyint_objectmap_next(map, &i)) != NULL) { void* p = obj->address; object_t* obj_local = ponyint_objectmap_getobject(&gc->local, p, &index); pony_assert(obj_local->rc >= obj->rc); obj_local->rc -= obj->rc; } ponyint_actorref_free(aref); return rc > 0; }