1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#ifndef ECMASCRIPT_MEM_C_ADDRESS_ALLOCATOR_H 17#define ECMASCRIPT_MEM_C_ADDRESS_ALLOCATOR_H 18 19#include "ecmascript/mem/chunk.h" 20 21namespace panda::ecmascript { 22template<typename T> 23class CAddressAllocator { 24public: 25 // using by std allocator 26 using value_type = T; 27 using pointer = T *; 28 using reference = T &; 29 using const_pointer = const T *; 30 using const_reference = const T &; 31 using size_type = size_t; 32 using difference_type = ptrdiff_t; 33 using propagate_on_container_swap = std::true_type; 34 35 template<typename U> 36 struct Rebind { 37 using other = CAddressAllocator<U>; 38 }; 39 40 template<typename U> 41 using rebind = Rebind<U>; 42 43 CAddressAllocator() = default; 44 45 template<typename U> 46 explicit CAddressAllocator(const CAddressAllocator<U> &other [[maybe_unused]]) 47 { 48 } 49 50 CAddressAllocator(const CAddressAllocator &) = default; 51 CAddressAllocator &operator=(const CAddressAllocator &) = default; 52 CAddressAllocator(CAddressAllocator &&other) noexcept = default; 53 CAddressAllocator &operator=(CAddressAllocator &&other) noexcept = default; 54 ~CAddressAllocator() = default; 55 56 // NOLINTNEXTLINE(readability-identifier-naming) 57 size_type max_size() const 58 { 59 return static_cast<size_type>(-1) / sizeof(T); 60 } 61 62 bool operator==([[maybe_unused]] CAddressAllocator const &other) const 63 { 64 return false; 65 } 66 67 bool operator!=([[maybe_unused]] CAddressAllocator const &other) const 68 { 69 return true; 70 } 71 72 // NOLINTNEXTLINE(readability-identifier-naming) 73 pointer allocate(size_type n, [[maybe_unused]] const void *ptr = nullptr) 74 { 75 ASSERT(n <= max_size()); 76 return static_cast<T *>(Allocate(n * sizeof(T))); 77 } 78 79 // NOLINTNEXTLINE(readability-identifier-naming) 80 void deallocate(pointer p, [[maybe_unused]] size_type n) 81 { 82 Free(static_cast<void *>(p)); 83 } 84 85 template<typename U, typename... Args> 86 void construct(U *p, Args &&... args) // NOLINT(readability-identifier-naming) 87 { 88 if (p == nullptr) { 89 return; 90 } 91 ::new (static_cast<void *>(p)) U(std::forward<Args>(args)...); 92 } 93 template<typename U> 94 void destroy(U *p) // NOLINT(readability-identifier-naming) 95 { 96 if (p == nullptr) { 97 return; 98 } 99 p->~U(); 100 } 101 102 [[nodiscard]] void *Allocate(size_t size) 103 { 104 if (size == 0) { 105 LOG_ECMA_MEM(FATAL) << "size must have a size bigger than 0"; 106 UNREACHABLE(); 107 } 108 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) 109 void *ptr = malloc(size); 110 if (ptr == nullptr) { 111 LOG_ECMA_MEM(FATAL) << "malloc failed, size is: " << size; 112 UNREACHABLE(); 113 } 114 return ptr; 115 } 116 117 template<typename S, typename... Args> 118 [[nodiscard]] S *New(Args &&... args) 119 { 120 auto p = reinterpret_cast<void *>(Allocate(sizeof(S))); 121 new (p) S(std::forward<Args>(args)...); 122 return reinterpret_cast<S *>(p); 123 } 124 125 template<class S> 126 void Finalize(S *ptr) 127 { 128 ASSERT(ptr != nullptr); 129 // NOLINTNEXTLINE(readability-braces-around-statements,bugprone-suspicious-semicolon) 130 if constexpr (std::is_class_v<S>) { 131 ptr->~S(); 132 } 133 Free(ptr); 134 } 135 136 [[nodiscard]] T *AllocArray(size_t size) 137 { 138 return static_cast<T *>(Allocate(size * sizeof(T))); 139 } 140 141 void Delete(T *ptr) 142 { 143 if (ptr == nullptr) { 144 return; 145 } 146 // NOLINTNEXTLINE(readability-braces-around-statements,bugprone-suspicious-semicolon) 147 if constexpr (std::is_class_v<T>) { 148 ptr->~T(); 149 } 150 Free(ptr); 151 } 152 153 void Free(void *mem) 154 { 155 if (mem == nullptr) { 156 return; 157 } 158 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) 159 free(mem); 160 } 161}; 162} // namespace panda::ecmascript 163 164#endif // ECMASCRIPT_MEM_C_ADDRESS_ALLOCATOR_H