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; }
void* ponyint_heap_realloc(pony_actor_t* actor, heap_t* heap, void* p, size_t size) { if(p == NULL) return ponyint_heap_alloc(actor, heap, size); chunk_t* chunk = (chunk_t*)ponyint_pagemap_get(p); if(chunk == NULL) { // Get new memory and copy from the old memory. void* q = ponyint_heap_alloc(actor, heap, size); memcpy(q, p, size); return q; } size_t oldsize; if(chunk->size < HEAP_SIZECLASSES) { // Previous allocation was a ponyint_heap_alloc_small. void* ext = EXTERNAL_PTR(p, chunk->size); // If the new allocation is a ponyint_heap_alloc_small and the pointer is // not an internal pointer, we may be able to reuse this memory. If it is // an internal pointer, we know where the old allocation begins but not // where it ends, so we cannot reuse this memory. if((size <= HEAP_MAX) && (p == ext)) { uint32_t sizeclass = ponyint_heap_index(size); // If the new allocation is the same size or smaller, return the old // one. if(sizeclass <= chunk->size) return p; } oldsize = SIZECLASS_SIZE(chunk->size) - ((uintptr_t)p - (uintptr_t)ext); } else { // Previous allocation was a ponyint_heap_alloc_large. if((size <= chunk->size) && (p == chunk->m)) { // If the new allocation is the same size or smaller, and this is not an // internal pointer, return the old one. We can't reuse internal // pointers in large allocs for the same reason as small ones. return p; } oldsize = chunk->size - ((uintptr_t)p - (uintptr_t)chunk->m); } // Determine how much memory to copy. if(oldsize > size) oldsize = size; // Get new memory and copy from the old memory. void* q = ponyint_heap_alloc(actor, heap, size); memcpy(q, p, oldsize); return q; }
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); } } }
void ponyint_gc_markobject(pony_ctx_t* ctx, void* p, pony_trace_fn f, bool immutable) { chunk_t* chunk = (chunk_t*)ponyint_pagemap_get(p); // Don't gc memory that wasn't pony_allocated, but do recurse. if(chunk == NULL) { recurse(ctx, p, f); return; } pony_actor_t* actor = ponyint_heap_owner(chunk); if(actor == ctx->current) mark_local_object(ctx, chunk, p, f); else mark_remote_object(ctx, actor, p, f, immutable, chunk); }
void* ponyint_heap_realloc(pony_actor_t* actor, heap_t* heap, void* p, size_t size) { if(p == NULL) return ponyint_heap_alloc(actor, heap, size); chunk_t* chunk = (chunk_t*)ponyint_pagemap_get(p); if(chunk == NULL) { // Get new memory and copy from the old memory. void* q = ponyint_heap_alloc(actor, heap, size); memcpy(q, p, size); return q; } if(chunk->size < HEAP_SIZECLASSES) { // Previous allocation was a ponyint_heap_alloc_small. if(size <= HEAP_MAX) { uint32_t sizeclass = ponyint_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 = ponyint_heap_alloc(actor, heap, size); memcpy(q, p, SIZECLASS_SIZE(chunk->size)); return q; } // Previous allocation was a ponyint_heap_alloc_large. if(size <= chunk->size) return p; // Get new memory and copy from the old memory. void* q = ponyint_heap_alloc(actor, heap, size); memcpy(q, p, chunk->size); return q; }
void ponyint_gc_acquireobject(pony_ctx_t* ctx, void* p, pony_type_t* t, int mutability) { chunk_t* chunk = (chunk_t*)ponyint_pagemap_get(p); // Don't gc memory that wasn't pony_allocated, but do recurse. if(chunk == NULL) { if(mutability != PONY_TRACE_OPAQUE) recurse(ctx, p, t->trace); return; } pony_actor_t* actor = ponyint_heap_owner(chunk); if(actor == ctx->current) acquire_local_object(ctx, p, t, mutability); else acq_or_rel_remote_object(ctx, actor, p, t, mutability); }