| 
 | 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 | + | 
 | 9 | +namespace node {  | 
 | 10 | +namespace mem {  | 
 | 11 | + | 
 | 12 | +template <typename Class, typename AllocatorStruct>  | 
 | 13 | +AllocatorStruct 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 | + | 
 | 23 | +template <typename Class, typename T>  | 
 | 24 | +void* 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 | + | 
 | 74 | +template <typename Class, typename T>  | 
 | 75 | +void* NgLibMemoryManager<Class, T>::MallocImpl(size_t size, void* user_data) {  | 
 | 76 | +  return ReallocImpl(nullptr, size, user_data);  | 
 | 77 | +}  | 
 | 78 | + | 
 | 79 | +template <typename Class, typename T>  | 
 | 80 | +void NgLibMemoryManager<Class, T>::FreeImpl(void* ptr, void* user_data) {  | 
 | 81 | +  if (ptr == nullptr) return;  | 
 | 82 | +  CHECK_NULL(ReallocImpl(ptr, 0, user_data));  | 
 | 83 | +}  | 
 | 84 | + | 
 | 85 | +template <typename Class, typename T>  | 
 | 86 | +void* 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 | + | 
 | 96 | +template <typename Class, typename T>  | 
 | 97 | +void 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_  | 
0 commit comments