void* MemoryHeap::realloc(void *ptr, size_t size) { if (mMspace == NULL) return 0; auto itr = mPages.find(ptr); if (itr != mPages.end()) { alloc_info info = (*itr).second; if (info.largeAlloc) { if (size < mPageSize / 2) { lassert(size < info.size); //the new array is no longer a 'large alloc' and should be placed back in the main //pool void* newPtr = malloc(size); lassert(newPtr); memcpy(newPtr, ptr, size); free(ptr); return newPtr; } else { void* newPtr = mMRemapFun(ptr, info.size, size, MREMAP_MAYMOVE); if (newPtr == MAP_FAILED) return 0; mark_unallocated(ptr, info.size); mark_allocated(newPtr, size, info.largeAlloc); mBytesUsed += (size - info.size); return newPtr; } } } size_t oldSize = mspace_usable_size(ptr); //the new array will be large enough that we should mmap it. if (size >= mPageSize) { void* newPtr = malloc(size); lassert(newPtr); memcpy(newPtr, ptr, std::min<size_t>(oldSize, size)); free(ptr); return newPtr; } void* newPtr = mspace_realloc(mMspace, ptr, size); if (newPtr != NULL) mBytesUsed += mspace_usable_size(newPtr) - oldSize; return newPtr; }
void palHeapAllocator::Deallocate(void* ptr) { if (ptr) { uint32_t reported_size = mspace_usable_size(ptr); mspace_free(internal_, ptr); ReportMemoryDeallocation(ptr, reported_size); } }
void* palHeapAllocator::Allocate(uint64_t size, uint32_t alignment) { void* ptr = mspace_memalign(internal_, alignment, (size_t)size); if (ptr) { uint32_t reported_size = mspace_usable_size(ptr); ReportMemoryAllocation(ptr, reported_size); } return ptr; }
/* * Returns the number of usable bytes in an allocated chunk; the size * may be larger than the size passed to dvmHeapSourceAlloc(). */ size_t dvmHeapSourceChunkSize(const void *ptr) { HS_BOILERPLATE(); Heap* heap = ptr2heap(gHs, ptr); if (heap != NULL) { return mspace_usable_size(ptr); } return 0; }
/* * Functions to update heapSource->bytesAllocated when an object * is allocated or freed. mspace_usable_size() will give * us a much more accurate picture of heap utilization than * the requested byte sizes would. * * These aren't exact, and should not be treated as such. */ static void countAllocation(Heap *heap, const void *ptr) { assert(heap->bytesAllocated < mspace_footprint(heap->msp)); heap->bytesAllocated += mspace_usable_size(ptr) + HEAP_SOURCE_CHUNK_OVERHEAD; heap->objectsAllocated++; HeapSource* hs = gDvm.gcHeap->heapSource; dvmHeapBitmapSetObjectBit(&hs->liveBits, ptr); assert(heap->bytesAllocated < mspace_footprint(heap->msp)); }
size_t MemoryHeap::msize(void* ptr) { if (mMspace == NULL) return 0; auto itr = mPages.find(ptr); if (itr != mPages.end()) { alloc_info info = (*itr).second; if (info.largeAlloc) { return info.size; } } return mspace_usable_size(ptr); }
void MemoryHeap::free(void *ptr) { if (mMspace == NULL) return; auto itr = mPages.find(ptr); if (itr != mPages.end()) { alloc_info info = (*itr).second; if (info.largeAlloc) { mMUnmapFun(ptr, info.size); mark_unallocated(ptr, info.size); mBytesUsed -= info.size; return; } } mBytesUsed -= mspace_usable_size(ptr); lassert(mspace_usable_size(ptr)); mspace_free(mMspace, ptr); }
static void countFree(Heap *heap, const void *ptr, size_t *numBytes) { size_t delta = mspace_usable_size(ptr) + HEAP_SOURCE_CHUNK_OVERHEAD; assert(delta > 0); if (delta < heap->bytesAllocated) { heap->bytesAllocated -= delta; } else { heap->bytesAllocated = 0; } HeapSource* hs = gDvm.gcHeap->heapSource; dvmHeapBitmapClearObjectBit(&hs->liveBits, ptr); if (heap->objectsAllocated > 0) { heap->objectsAllocated--; } *numBytes += delta; }
void* OOBase::ArenaAllocator::reallocate(void* ptr, size_t bytes, size_t align) { if (align <= 8) return mspace_realloc(m_mspace,ptr,bytes); if (mspace_realloc_in_place(m_mspace,ptr,bytes)) return ptr; void* new_ptr = mspace_memalign(m_mspace,align,bytes); if (new_ptr) { memcpy(new_ptr,ptr,mspace_usable_size(ptr)); mspace_free(m_mspace,ptr); } return new_ptr; }
void* MemoryHeap::malloc(size_t size) { if (mMspace == NULL) initialize(); if (size >= mPageSize) { void* newAddr = mMMapFun(size); if (newAddr != MAP_FAILED) { mBytesUsed += size; mark_allocated(newAddr, size, true); return newAddr; } return 0; } void* newAddr = mspace_malloc(mMspace, size); if (newAddr != NULL) mBytesUsed += mspace_usable_size(newAddr); return newAddr; }
uint64_t palHeapAllocator::GetSize(void* ptr) const { return mspace_usable_size(ptr); }
int main(int argc, char *argv[]) { size_t size1 = 255; void *addr1 = NULL; size_t size2 = 256; void *addr2 = NULL; size_t size3 = kMaxCodeCacheCapacity - 512; void *addr3 = NULL; gExecutableStore = malloc(kMaxCodeCacheCapacity); if (gExecutableStore == NULL) { printf("error malloc\n"); return -1; } gMspace = create_mspace_with_base(gExecutableStore, kMaxCodeCacheCapacity, /*locked=*/ true); printf("-> create mspace\n"); mspace_malloc_stats(gMspace); addr1 = mspace_malloc(gMspace, size1); if (addr1 != NULL) { printf("-> malloc addr1 = %p, 0x%x\n", addr1, (uint32_t)size1); mspace_malloc_stats(gMspace); printf("addr1 size = 0x%x\n", (uint32_t)mspace_usable_size(addr1)); } addr2 = mspace_malloc(gMspace, size2); if (addr2 != NULL) { printf("-> malloc addr2 = %p, 0x%x\n", addr2, (uint32_t)size2); mspace_malloc_stats(gMspace); printf("addr2 size = 0x%x\n", (uint32_t)mspace_usable_size(addr2)); } addr3 = mspace_malloc(gMspace, size3); if (addr3 != NULL) { printf("-> malloc addr3 = %p, 0x%x\n", addr3, (uint32_t)size3); mspace_malloc_stats(gMspace); printf("addr3 size = 0x%x\n", (uint32_t)mspace_usable_size(addr3)); } else { printf("malloc addr3 error!\n"); } if (addr1 != NULL) { mspace_free(gMspace, addr1); } if (addr2 != NULL) { mspace_free(gMspace, addr2); } if (addr3 != NULL) { mspace_free(gMspace, addr3); } printf("-> all free\n"); mspace_malloc_stats(gMspace); _exit: if (gMspace != NULL) { destroy_mspace(gMspace); gMspace = NULL; } if (gExecutableStore != NULL) { free(gExecutableStore); gExecutableStore = NULL; } return 0; }
size_t mm_mspace_getallocsize(const void *ptr) { return mspace_usable_size(ptr); }