MemoryPool.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #include "il2cpp-config.h"
  2. #include "utils/MemoryPool.h"
  3. #include "utils/Memory.h"
  4. #include <algorithm>
  5. #include <limits>
  6. namespace il2cpp
  7. {
  8. namespace utils
  9. {
  10. const size_t kPageSize = IL2CPP_PAGE_SIZE;
  11. const size_t kDefaultRegionSize = 64 * 1024;
  12. // by making all allocations a multiple of this value, we ensure the next
  13. // allocation will always be aligned to this value
  14. const size_t kMemoryAlignment = 8;
  15. static inline size_t MakeMultipleOf(size_t size, size_t alignment)
  16. {
  17. return (size + alignment - 1) & ~(alignment - 1);
  18. }
  19. struct MemoryPool::Region
  20. {
  21. char* start;
  22. char* current;
  23. size_t size;
  24. size_t free;
  25. };
  26. MemoryPool::MemoryPool()
  27. {
  28. AddRegion(kDefaultRegionSize);
  29. }
  30. MemoryPool::MemoryPool(size_t initialSize)
  31. {
  32. AddRegion(initialSize);
  33. }
  34. MemoryPool::~MemoryPool()
  35. {
  36. for (RegionList::iterator iter = m_Regions.begin(); iter != m_Regions.end(); ++iter)
  37. {
  38. IL2CPP_FREE((*iter)->start, IL2CPP_MEM_META_POOL);
  39. IL2CPP_FREE(*iter, IL2CPP_MEM_META_POOL);
  40. }
  41. m_Regions.clear();
  42. }
  43. void* MemoryPool::Malloc(size_t size)
  44. {
  45. size = MakeMultipleOf(size, kMemoryAlignment);
  46. Region* region = m_Regions.back();
  47. if (region->free < size)
  48. {
  49. #if IL2CPP_ENABLE_MEM_STATS
  50. il2cpp_mem_stats.meta.meta_wasted += region->free;
  51. #endif //IL2CPP_ENABLE_MEM_STATS
  52. region = AddRegion(size);
  53. }
  54. IL2CPP_ASSERT(region->free >= size);
  55. void* value = region->current;
  56. region->current += size;
  57. region->free -= size;
  58. return value;
  59. }
  60. void* MemoryPool::Calloc(size_t count, size_t size)
  61. {
  62. void* ret = Malloc(count * size);
  63. return ret;
  64. }
  65. MemoryPool::Region* MemoryPool::AddRegion(size_t size)
  66. {
  67. Region* newRegion = (Region*)IL2CPP_MALLOC(sizeof(Region), IL2CPP_MEM_META_POOL);
  68. Region* lastFreeRegion = m_Regions.size() > 0 ? m_Regions.back() : NULL;
  69. size_t allocationSize;
  70. if (lastFreeRegion != NULL && lastFreeRegion->free >= kPageSize)
  71. {
  72. allocationSize = MakeMultipleOf(size, kPageSize);
  73. m_Regions.pop_back();
  74. m_Regions.push_back(newRegion);
  75. m_Regions.push_back(lastFreeRegion);
  76. }
  77. else
  78. {
  79. allocationSize = std::max(kDefaultRegionSize, MakeMultipleOf(size, kPageSize));
  80. m_Regions.push_back(newRegion);
  81. }
  82. newRegion->start = newRegion->current = (char*)IL2CPP_MALLOC_ZERO(allocationSize, IL2CPP_MEM_META_POOL);
  83. newRegion->size = newRegion->free = allocationSize;
  84. #if IL2CPP_ENABLE_MEM_STATS
  85. il2cpp_mem_stats.meta.meta_total += (allocationSize + sizeof(Region));
  86. ++il2cpp_mem_stats.meta.meta_region_count;
  87. #endif //IL2CPP_ENABLE_MEM_STATS
  88. return newRegion;
  89. }
  90. size_t MemoryPool::RegionSize() {
  91. return sizeof(Region);
  92. }
  93. size_t MemoryPool::FreeSize(){
  94. return m_Regions.back()->free;
  95. }
  96. size_t MemoryPool::TotalSize() {
  97. size_t total = 0;
  98. for (RegionList::iterator iter = m_Regions.begin(); iter != m_Regions.end(); ++iter)
  99. {
  100. total += (*iter)->size;
  101. }
  102. return total + sizeof(Region) * m_Regions.size();
  103. }
  104. }
  105. }