Memory.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #pragma once
  2. #include "il2cpp-config.h"
  3. #include "il2cpp-runtime-stats.h"
  4. namespace il2cpp
  5. {
  6. namespace utils
  7. {
  8. struct LIBIL2CPP_CODEGEN_API Memory
  9. {
  10. static void SetMemoryCallbacks(Il2CppMemoryCallbacks* callbacks);
  11. // for Allocator only
  12. static void* Malloc(size_t size);
  13. static void Free(void* memory);
  14. static void* Malloc(size_t size, Il2CppMemLabel label);
  15. static void* AlignedMalloc(size_t size, size_t alignment, Il2CppMemLabel label);
  16. static void Free(void* memory, Il2CppMemLabel label);
  17. static void AlignedFree(void* memory, Il2CppMemLabel label);
  18. static void* Calloc(size_t count, size_t size, Il2CppMemLabel label);
  19. static void* Realloc(void* memory, size_t newSize, Il2CppMemLabel label);
  20. static void* AlignedRealloc(void* memory, size_t newSize, size_t alignment, Il2CppMemLabel label);
  21. };
  22. } /* namespace utils */
  23. } /* namespace il2cpp */
  24. #define IL2CPP_MALLOC(size,lable) il2cpp::utils::Memory::Malloc(size,lable)
  25. #define IL2CPP_MALLOC_ALIGNED(size, alignment,lable) il2cpp::utils::Memory::AlignedMalloc(size, alignment,lable)
  26. #define IL2CPP_MALLOC_ZERO(size,lable) il2cpp::utils::Memory::Calloc(1,size,lable)
  27. #define IL2CPP_FREE(memory,lable) il2cpp::utils::Memory::Free(memory,lable)
  28. #define IL2CPP_FREE_ALIGNED(memory,lable) il2cpp::utils::Memory::AlignedFree(memory,lable)
  29. #define IL2CPP_CALLOC(count, size,lable) il2cpp::utils::Memory::Calloc(count,size,lable)
  30. #define IL2CPP_REALLOC(memory, newSize,lable) il2cpp::utils::Memory::Realloc(memory,newSize,lable)
  31. #define IL2CPP_REALLOC_ALIGNED(memory, newSize, alignment,lable) il2cpp::utils::Memory::AlignedRealloc(memory, newSize, alignment,lable)
  32. #if IL2CPP_TARGET_JAVASCRIPT
  33. #define HASH_MALLOC(size,lable) IL2CPP_MALLOC(size,lable)
  34. #define HASH_FREE(memory,lable) IL2CPP_FREE(memory,lable)
  35. #define HASH_REALLOC(memory, newSize,lable) IL2CPP_REALLOC(memory, newSize,lable)
  36. #else
  37. #define HASH_MALLOC(size,lable) malloc(size)
  38. #define HASH_FREE(memory,lable) free(memory)
  39. #define HASH_REALLOC(memory, newSize,lable) realloc(memory, newSize)
  40. #endif
  41. // allocator for il2cppHashSet/map
  42. // IL2CPP_MALLOC can only be used on webgl platform, because globel hashset/map objects will be constructed before unity engine MemoryAllocator initializing.
  43. template<class T>
  44. class libc_allocator_with_realloc_il2cpp {
  45. public:
  46. typedef T value_type;
  47. typedef size_t size_type;
  48. typedef ptrdiff_t difference_type;
  49. typedef T* pointer;
  50. typedef const T* const_pointer;
  51. typedef T& reference;
  52. typedef const T& const_reference;
  53. libc_allocator_with_realloc_il2cpp() {}
  54. libc_allocator_with_realloc_il2cpp(const libc_allocator_with_realloc_il2cpp&) {}
  55. ~libc_allocator_with_realloc_il2cpp() {}
  56. pointer address(reference r) const { return &r; }
  57. const_pointer address(const_reference r) const { return &r; }
  58. pointer allocate(size_type n, const_pointer = 0) {
  59. il2cpp_runtime_stats.hashtable_mem += n * sizeof(value_type);
  60. #if IL2CPP_ENABLE_MEM_STATS
  61. auto size = n * sizeof(value_type);
  62. void* ret = HASH_MALLOC(size, IL2CPP_MEM_HASH_TABLE);
  63. if (ret) {
  64. il2cpp_mem_stats.hash_table += size;
  65. auto& hashAllocMap = GetHashAllocMap();
  66. hashAllocMap[ret] = size;
  67. }
  68. return static_cast<pointer>(ret);
  69. #else
  70. return static_cast<pointer>(HASH_MALLOC(n * sizeof(value_type), IL2CPP_MEM_HASH_TABLE));
  71. #endif
  72. }
  73. void deallocate(pointer p, size_type n) {
  74. il2cpp_runtime_stats.hashtable_mem -= n * sizeof(value_type);
  75. #if IL2CPP_ENABLE_MEM_STATS
  76. void* ptr = static_cast<void*>(p);
  77. if (ptr) {
  78. auto& hashAllocMap = GetHashAllocMap();
  79. auto it = hashAllocMap.find(ptr);
  80. if (it != hashAllocMap.end()) {
  81. il2cpp_mem_stats.hash_table -= it->second;
  82. hashAllocMap.erase(it);
  83. }
  84. }
  85. #endif
  86. HASH_FREE(p, IL2CPP_MEM_HASH_TABLE);
  87. }
  88. pointer reallocate(pointer p, size_type n) {
  89. IL2CPP_NOT_IMPLEMENTED(libc_allocator_with_realloc_il2cpp::reallocate);
  90. #if IL2CPP_ENABLE_MEM_STATS
  91. auto newSize = n * sizeof(value_type);
  92. void* ret = HASH_REALLOC(static_cast<void*>(p), newSize, IL2CPP_MEM_HASH_TABLE);
  93. void* ptr = static_cast<void*>(p);
  94. auto& hashAllocMap = GetHashAllocMap();
  95. if (ptr) {
  96. auto it = hashAllocMap.find(ptr);
  97. if (it != hashAllocMap.end()) {
  98. il2cpp_mem_stats.hash_table -= it->second;
  99. hashAllocMap.erase(it);
  100. }
  101. }
  102. if (ret) {
  103. il2cpp_mem_stats.hash_table += newSize;
  104. hashAllocMap[ret] = newSize;
  105. }
  106. return static_cast<pointer>(ret);
  107. #else
  108. // p points to a storage array whose objects have already been destroyed
  109. // cast to void* to prevent compiler warnings about calling realloc() on
  110. // an object which cannot be relocated in memory
  111. return static_cast<pointer>(HASH_REALLOC(static_cast<void*>(p), n * sizeof(value_type) , IL2CPP_MEM_HASH_TABLE));
  112. #endif
  113. }
  114. size_type max_size() const {
  115. return static_cast<size_type>(-1) / sizeof(value_type);
  116. }
  117. void construct(pointer p, const value_type& val) {
  118. new(p) value_type(val);
  119. }
  120. void destroy(pointer p) { p->~value_type(); }
  121. template <class U>
  122. libc_allocator_with_realloc_il2cpp(const libc_allocator_with_realloc_il2cpp<U>&) {}
  123. template<class U>
  124. struct rebind {
  125. typedef libc_allocator_with_realloc_il2cpp<U> other;
  126. };
  127. };
  128. // libc_allocator_with_realloc_il2cpp<void> specialization.
  129. template<>
  130. class libc_allocator_with_realloc_il2cpp<void> {
  131. public:
  132. typedef void value_type;
  133. typedef size_t size_type;
  134. typedef ptrdiff_t difference_type;
  135. typedef void* pointer;
  136. typedef const void* const_pointer;
  137. template<class U>
  138. struct rebind {
  139. typedef libc_allocator_with_realloc_il2cpp<U> other;
  140. };
  141. };
  142. template<class T>
  143. inline bool operator==(const libc_allocator_with_realloc_il2cpp<T>&,
  144. const libc_allocator_with_realloc_il2cpp<T>&) {
  145. return true;
  146. }
  147. template<class T>
  148. inline bool operator!=(const libc_allocator_with_realloc_il2cpp<T>&,
  149. const libc_allocator_with_realloc_il2cpp<T>&) {
  150. return false;
  151. }
  152. #undef HASH_MALLOC
  153. #undef HASH_FREE
  154. #undef HASH_REALLOC