/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ECMASCRIPT_MEM_C_ADDRESS_ALLOCATOR_H #define ECMASCRIPT_MEM_C_ADDRESS_ALLOCATOR_H #include "ecmascript/mem/chunk.h" namespace panda::ecmascript { template class CAddressAllocator { public: // using by std allocator using value_type = T; using pointer = T *; using reference = T &; using const_pointer = const T *; using const_reference = const T &; using size_type = size_t; using difference_type = ptrdiff_t; using propagate_on_container_swap = std::true_type; template struct Rebind { using other = CAddressAllocator; }; template using rebind = Rebind; CAddressAllocator() = default; template explicit CAddressAllocator(const CAddressAllocator &other [[maybe_unused]]) { } CAddressAllocator(const CAddressAllocator &) = default; CAddressAllocator &operator=(const CAddressAllocator &) = default; CAddressAllocator(CAddressAllocator &&other) noexcept = default; CAddressAllocator &operator=(CAddressAllocator &&other) noexcept = default; ~CAddressAllocator() = default; // NOLINTNEXTLINE(readability-identifier-naming) size_type max_size() const { return static_cast(-1) / sizeof(T); } bool operator==([[maybe_unused]] CAddressAllocator const &other) const { return false; } bool operator!=([[maybe_unused]] CAddressAllocator const &other) const { return true; } // NOLINTNEXTLINE(readability-identifier-naming) pointer allocate(size_type n, [[maybe_unused]] const void *ptr = nullptr) { ASSERT(n <= max_size()); return static_cast(Allocate(n * sizeof(T))); } // NOLINTNEXTLINE(readability-identifier-naming) void deallocate(pointer p, [[maybe_unused]] size_type n) { Free(static_cast(p)); } template void construct(U *p, Args &&... args) // NOLINT(readability-identifier-naming) { if (p == nullptr) { return; } ::new (static_cast(p)) U(std::forward(args)...); } template void destroy(U *p) // NOLINT(readability-identifier-naming) { if (p == nullptr) { return; } p->~U(); } [[nodiscard]] void *Allocate(size_t size) { if (size == 0) { LOG_ECMA_MEM(FATAL) << "size must have a size bigger than 0"; UNREACHABLE(); } // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) void *ptr = malloc(size); if (ptr == nullptr) { LOG_ECMA_MEM(FATAL) << "malloc failed, size is: " << size; UNREACHABLE(); } return ptr; } template [[nodiscard]] S *New(Args &&... args) { auto p = reinterpret_cast(Allocate(sizeof(S))); new (p) S(std::forward(args)...); return reinterpret_cast(p); } template void Finalize(S *ptr) { ASSERT(ptr != nullptr); // NOLINTNEXTLINE(readability-braces-around-statements,bugprone-suspicious-semicolon) if constexpr (std::is_class_v) { ptr->~S(); } Free(ptr); } [[nodiscard]] T *AllocArray(size_t size) { return static_cast(Allocate(size * sizeof(T))); } void Delete(T *ptr) { if (ptr == nullptr) { return; } // NOLINTNEXTLINE(readability-braces-around-statements,bugprone-suspicious-semicolon) if constexpr (std::is_class_v) { ptr->~T(); } Free(ptr); } void Free(void *mem) { if (mem == nullptr) { return; } // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) free(mem); } }; } // namespace panda::ecmascript #endif // ECMASCRIPT_MEM_C_ADDRESS_ALLOCATOR_H