LLVMValueRef gencall_allocstruct(compile_t* c, reach_type_t* t) { // We explicitly want a boxed version. // Allocate the object. LLVMValueRef args[3]; args[0] = codegen_ctx(c); LLVMValueRef result; size_t size = t->abi_size; if(size == 0) size = 1; if(size <= HEAP_MAX) { uint32_t index = ponyint_heap_index(size); args[1] = LLVMConstInt(c->i32, index, false); if(t->final_fn == NULL) result = gencall_runtime(c, "pony_alloc_small", args, 2, ""); else result = gencall_runtime(c, "pony_alloc_small_final", args, 2, ""); } else { args[1] = LLVMConstInt(c->intptr, size, false); if(t->final_fn == NULL) result = gencall_runtime(c, "pony_alloc_large", args, 2, ""); else result = gencall_runtime(c, "pony_alloc_large_final", args, 2, ""); } result = LLVMBuildBitCast(c->builder, result, t->structure_ptr, ""); set_descriptor(c, t, result); return result; }
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_heap_alloc(pony_actor_t* actor, heap_t* heap, size_t size) { if(size == 0) { return NULL; } else if(size <= HEAP_MAX) { return ponyint_heap_alloc_small(actor, heap, ponyint_heap_index(size)); } else { return ponyint_heap_alloc_large(actor, heap, size); } }
LLVMValueRef gencall_allocstruct(compile_t* c, gentype_t* g) { // Disable debug anchor dwarf_location(&c->dwarf, NULL); // We explicitly want a boxed version. // Get the size of the structure. size_t size = (size_t)LLVMABISizeOfType(c->target_data, g->structure); // Get the finaliser, if there is one. const char* final = genname_finalise(g->type_name); LLVMValueRef final_fun = LLVMGetNamedFunction(c->module, final); // Allocate the object. LLVMValueRef args[3]; args[0] = codegen_ctx(c); LLVMValueRef result; if(final_fun == NULL) { if(size <= HEAP_MAX) { uint32_t index = ponyint_heap_index(size); args[1] = LLVMConstInt(c->i32, index, false); result = gencall_runtime(c, "pony_alloc_small", args, 2, ""); } else { args[1] = LLVMConstInt(c->intptr, size, false); result = gencall_runtime(c, "pony_alloc_large", args, 2, ""); } } else { args[1] = LLVMConstInt(c->intptr, size, false); args[2] = LLVMConstBitCast(final_fun, c->final_fn); result = gencall_runtime(c, "pony_alloc_final", args, 3, ""); } result = LLVMBuildBitCast(c->builder, result, g->structure_ptr, ""); // Set the descriptor. if(g->underlying != TK_STRUCT) { LLVMValueRef desc_ptr = LLVMBuildStructGEP(c->builder, result, 0, ""); LLVMBuildStore(c->builder, g->desc, desc_ptr); } return result; }
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; }