• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
MakeAllocator()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>
ReallocImpl(void * ptr,size_t size,void * user_data)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>
MallocImpl(size_t size,void * user_data)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>
FreeImpl(void * ptr,void * user_data)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>
CallocImpl(size_t nmemb,size_t size,void * user_data)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>
StopTrackingMemory(void * ptr)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_
113