1#ifndef SRC_NODE_MEM_INL_H_ 2#define SRC_NODE_MEM_INL_H_ 3 4#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6#include "node_mem.h" 7#include "node_internals.h" 8 9namespace node { 10namespace mem { 11 12template <typename Class, typename AllocatorStruct> 13AllocatorStruct NgLibMemoryManager<Class, AllocatorStruct>::MakeAllocator() { 14 return AllocatorStruct { 15 static_cast<void*>(static_cast<Class*>(this)), 16 MallocImpl, 17 FreeImpl, 18 CallocImpl, 19 ReallocImpl 20 }; 21} 22 23template <typename Class, typename T> 24void* NgLibMemoryManager<Class, T>::ReallocImpl(void* ptr, 25 size_t size, 26 void* user_data) { 27 Class* manager = static_cast<Class*>(user_data); 28 29 size_t previous_size = 0; 30 char* original_ptr = nullptr; 31 32 // We prepend each allocated buffer with a size_t containing the full 33 // size of the allocation. 34 if (size > 0) size += sizeof(size_t); 35 36 if (ptr != nullptr) { 37 // We are free()ing or re-allocating. 38 original_ptr = static_cast<char*>(ptr) - sizeof(size_t); 39 previous_size = *reinterpret_cast<size_t*>(original_ptr); 40 // This means we called StopTracking() on this pointer before. 41 if (previous_size == 0) { 42 // Fall back to the standard Realloc() function. 43 char* ret = UncheckedRealloc(original_ptr, size); 44 if (ret != nullptr) 45 ret += sizeof(size_t); 46 return ret; 47 } 48 } 49 50 manager->CheckAllocatedSize(previous_size); 51 52 char* mem = UncheckedRealloc(original_ptr, size); 53 54 if (mem != nullptr) { 55 // Adjust the memory info counter. 56 // TODO(addaleax): Avoid the double bookkeeping we do with 57 // current_nghttp2_memory_ + AdjustAmountOfExternalAllocatedMemory 58 // and provide versions of our memory allocation utilities that take an 59 // Environment*/Isolate* parameter and call the V8 method transparently. 60 const int64_t new_size = size - previous_size; 61 manager->IncreaseAllocatedSize(new_size); 62 manager->env()->isolate()->AdjustAmountOfExternalAllocatedMemory( 63 new_size); 64 *reinterpret_cast<size_t*>(mem) = size; 65 mem += sizeof(size_t); 66 } else if (size == 0) { 67 manager->DecreaseAllocatedSize(previous_size); 68 manager->env()->isolate()->AdjustAmountOfExternalAllocatedMemory( 69 -static_cast<int64_t>(previous_size)); 70 } 71 return mem; 72} 73 74template <typename Class, typename T> 75void* NgLibMemoryManager<Class, T>::MallocImpl(size_t size, void* user_data) { 76 return ReallocImpl(nullptr, size, user_data); 77} 78 79template <typename Class, typename T> 80void NgLibMemoryManager<Class, T>::FreeImpl(void* ptr, void* user_data) { 81 if (ptr == nullptr) return; 82 CHECK_NULL(ReallocImpl(ptr, 0, user_data)); 83} 84 85template <typename Class, typename T> 86void* NgLibMemoryManager<Class, T>::CallocImpl(size_t nmemb, 87 size_t size, 88 void* user_data) { 89 size_t real_size = MultiplyWithOverflowCheck(nmemb, size); 90 void* mem = MallocImpl(real_size, user_data); 91 if (mem != nullptr) 92 memset(mem, 0, real_size); 93 return mem; 94} 95 96template <typename Class, typename T> 97void NgLibMemoryManager<Class, T>::StopTrackingMemory(void* ptr) { 98 size_t* original_ptr = reinterpret_cast<size_t*>( 99 static_cast<char*>(ptr) - sizeof(size_t)); 100 Class* manager = static_cast<Class*>(this); 101 manager->DecreaseAllocatedSize(*original_ptr); 102 manager->env()->isolate()->AdjustAmountOfExternalAllocatedMemory( 103 -static_cast<int64_t>(*original_ptr)); 104 *original_ptr = 0; 105} 106 107} // namespace mem 108} // namespace node 109 110#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 111 112#endif // SRC_NODE_MEM_INL_H_ 113