11cb0ef41Sopenharmony_ci#ifndef SRC_NODE_MEM_INL_H_
21cb0ef41Sopenharmony_ci#define SRC_NODE_MEM_INL_H_
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ci#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci#include "node_mem.h"
71cb0ef41Sopenharmony_ci#include "node_internals.h"
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_cinamespace node {
101cb0ef41Sopenharmony_cinamespace mem {
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_citemplate <typename Class, typename AllocatorStruct>
131cb0ef41Sopenharmony_ciAllocatorStruct NgLibMemoryManager<Class, AllocatorStruct>::MakeAllocator() {
141cb0ef41Sopenharmony_ci  return AllocatorStruct {
151cb0ef41Sopenharmony_ci    static_cast<void*>(static_cast<Class*>(this)),
161cb0ef41Sopenharmony_ci    MallocImpl,
171cb0ef41Sopenharmony_ci    FreeImpl,
181cb0ef41Sopenharmony_ci    CallocImpl,
191cb0ef41Sopenharmony_ci    ReallocImpl
201cb0ef41Sopenharmony_ci  };
211cb0ef41Sopenharmony_ci}
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_citemplate <typename Class, typename T>
241cb0ef41Sopenharmony_civoid* NgLibMemoryManager<Class, T>::ReallocImpl(void* ptr,
251cb0ef41Sopenharmony_ci                                             size_t size,
261cb0ef41Sopenharmony_ci                                             void* user_data) {
271cb0ef41Sopenharmony_ci  Class* manager = static_cast<Class*>(user_data);
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  size_t previous_size = 0;
301cb0ef41Sopenharmony_ci  char* original_ptr = nullptr;
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci  // We prepend each allocated buffer with a size_t containing the full
331cb0ef41Sopenharmony_ci  // size of the allocation.
341cb0ef41Sopenharmony_ci  if (size > 0) size += sizeof(size_t);
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci  if (ptr != nullptr) {
371cb0ef41Sopenharmony_ci    // We are free()ing or re-allocating.
381cb0ef41Sopenharmony_ci    original_ptr = static_cast<char*>(ptr) - sizeof(size_t);
391cb0ef41Sopenharmony_ci    previous_size = *reinterpret_cast<size_t*>(original_ptr);
401cb0ef41Sopenharmony_ci    // This means we called StopTracking() on this pointer before.
411cb0ef41Sopenharmony_ci    if (previous_size == 0) {
421cb0ef41Sopenharmony_ci      // Fall back to the standard Realloc() function.
431cb0ef41Sopenharmony_ci      char* ret = UncheckedRealloc(original_ptr, size);
441cb0ef41Sopenharmony_ci      if (ret != nullptr)
451cb0ef41Sopenharmony_ci        ret += sizeof(size_t);
461cb0ef41Sopenharmony_ci      return ret;
471cb0ef41Sopenharmony_ci    }
481cb0ef41Sopenharmony_ci  }
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  manager->CheckAllocatedSize(previous_size);
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  char* mem = UncheckedRealloc(original_ptr, size);
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  if (mem != nullptr) {
551cb0ef41Sopenharmony_ci    // Adjust the memory info counter.
561cb0ef41Sopenharmony_ci    // TODO(addaleax): Avoid the double bookkeeping we do with
571cb0ef41Sopenharmony_ci    // current_nghttp2_memory_ + AdjustAmountOfExternalAllocatedMemory
581cb0ef41Sopenharmony_ci    // and provide versions of our memory allocation utilities that take an
591cb0ef41Sopenharmony_ci    // Environment*/Isolate* parameter and call the V8 method transparently.
601cb0ef41Sopenharmony_ci    const int64_t new_size = size - previous_size;
611cb0ef41Sopenharmony_ci    manager->IncreaseAllocatedSize(new_size);
621cb0ef41Sopenharmony_ci    manager->env()->isolate()->AdjustAmountOfExternalAllocatedMemory(
631cb0ef41Sopenharmony_ci        new_size);
641cb0ef41Sopenharmony_ci    *reinterpret_cast<size_t*>(mem) = size;
651cb0ef41Sopenharmony_ci    mem += sizeof(size_t);
661cb0ef41Sopenharmony_ci  } else if (size == 0) {
671cb0ef41Sopenharmony_ci    manager->DecreaseAllocatedSize(previous_size);
681cb0ef41Sopenharmony_ci    manager->env()->isolate()->AdjustAmountOfExternalAllocatedMemory(
691cb0ef41Sopenharmony_ci        -static_cast<int64_t>(previous_size));
701cb0ef41Sopenharmony_ci  }
711cb0ef41Sopenharmony_ci  return mem;
721cb0ef41Sopenharmony_ci}
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_citemplate <typename Class, typename T>
751cb0ef41Sopenharmony_civoid* NgLibMemoryManager<Class, T>::MallocImpl(size_t size, void* user_data) {
761cb0ef41Sopenharmony_ci  return ReallocImpl(nullptr, size, user_data);
771cb0ef41Sopenharmony_ci}
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_citemplate <typename Class, typename T>
801cb0ef41Sopenharmony_civoid NgLibMemoryManager<Class, T>::FreeImpl(void* ptr, void* user_data) {
811cb0ef41Sopenharmony_ci  if (ptr == nullptr) return;
821cb0ef41Sopenharmony_ci  CHECK_NULL(ReallocImpl(ptr, 0, user_data));
831cb0ef41Sopenharmony_ci}
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_citemplate <typename Class, typename T>
861cb0ef41Sopenharmony_civoid* NgLibMemoryManager<Class, T>::CallocImpl(size_t nmemb,
871cb0ef41Sopenharmony_ci                                            size_t size,
881cb0ef41Sopenharmony_ci                                            void* user_data) {
891cb0ef41Sopenharmony_ci  size_t real_size = MultiplyWithOverflowCheck(nmemb, size);
901cb0ef41Sopenharmony_ci  void* mem = MallocImpl(real_size, user_data);
911cb0ef41Sopenharmony_ci  if (mem != nullptr)
921cb0ef41Sopenharmony_ci    memset(mem, 0, real_size);
931cb0ef41Sopenharmony_ci  return mem;
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_citemplate <typename Class, typename T>
971cb0ef41Sopenharmony_civoid NgLibMemoryManager<Class, T>::StopTrackingMemory(void* ptr) {
981cb0ef41Sopenharmony_ci  size_t* original_ptr = reinterpret_cast<size_t*>(
991cb0ef41Sopenharmony_ci      static_cast<char*>(ptr) - sizeof(size_t));
1001cb0ef41Sopenharmony_ci  Class* manager = static_cast<Class*>(this);
1011cb0ef41Sopenharmony_ci  manager->DecreaseAllocatedSize(*original_ptr);
1021cb0ef41Sopenharmony_ci  manager->env()->isolate()->AdjustAmountOfExternalAllocatedMemory(
1031cb0ef41Sopenharmony_ci      -static_cast<int64_t>(*original_ptr));
1041cb0ef41Sopenharmony_ci  *original_ptr = 0;
1051cb0ef41Sopenharmony_ci}
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci}  // namespace mem
1081cb0ef41Sopenharmony_ci}  // namespace node
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci#endif  // SRC_NODE_MEM_INL_H_
113